Vollständige Implementierung des EngineeringSync-Middleware-Tools: - Windows Service (Kestrel :5050) mit FileSystemWatcher + SignalR - WPF Tray-App mit PendingChanges- und Projektverwaltungs-Fenster - Setup-Wizard (8-Schritte-Installer) - SQLite/EF Core Datenschicht (WAL-Modus) - SHA-256-basiertes Debouncing (2s Fenster) - Backup-System mit konfigurierbarer Aufbewahrung Bugfixes & Verbesserungen: - BUG-1: AppDbContext OnConfiguring invertierte Bedingung behoben - BUG-2: Event-Handler-Leak in TrayApp (Fenster-Singleton-Pattern) - BUG-3: ProjectConfigChanged SignalR-Signal in allen CRUD-Endpoints - BUG-5: Rename-Sync löscht alte Datei im Simulations-Ordner - BUG-6: Doppeltes Dispose von SignalR verhindert - BUG-7: Registry-Deinstallation nur EngineeringSync-Eintrag entfernt - S1: Path-Traversal-Schutz via SafeCombine() im SyncManager - E1: FSW Buffer 64KB + automatischer Re-Scan bei Overflow - E2: Retry-Logik (3x) für gesperrte Dateien mit exponentiellem Backoff - E4: Channel.Writer.TryComplete() beim Shutdown - C2: HubMethodNames-Konstanten statt Magic Strings - E3: Pagination in Changes-API (page/pageSize Query-Parameter) - A1: Fire-and-Forget mit try/catch + Logging Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
91 lines
4.1 KiB
Markdown
91 lines
4.1 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project Overview
|
||
|
||
**EngineeringSync** – A .NET 10 middleware tool that bridges mechanical engineering (CAD) and simulation (Process Simulate). A Windows Service watches an engineering folder for file changes, records them in SQLite, and notifies a WPF System Tray App via SignalR. The simulation engineer reviews changes and triggers a controlled sync to avoid data corruption.
|
||
|
||
## Tech Stack
|
||
|
||
- **Framework:** .NET 10
|
||
- **Service:** Worker Service (Windows Service) + ASP.NET Core Minimal API + SignalR
|
||
- **Client:** WPF (.NET 10-Windows) with `H.NotifyIcon.Wpf` + `CommunityToolkit.Mvvm`
|
||
- **Database:** SQLite via EF Core 10 (WAL mode)
|
||
- **File Watching:** `System.IO.FileSystemWatcher` + `System.Threading.Channels` (debouncing)
|
||
|
||
## Solution Structure
|
||
|
||
```
|
||
EngineeringSync.slnx
|
||
├── EngineeringSync.Domain (Class Library, net10.0) – Entities, Enums, Interfaces
|
||
├── EngineeringSync.Infrastructure (Class Library, net10.0) – EF Core, AppDbContext
|
||
├── EngineeringSync.Service (Worker Service, net10.0) – Kestrel on :5050, SignalR hub
|
||
├── EngineeringSync.TrayApp (WPF App, net10.0-windows) – System tray + UI windows
|
||
└── EngineeringSync.Setup (WPF App, net10.0-windows) – Setup-Wizard + Installer
|
||
installer/
|
||
├── setup.iss – Inno Setup Script
|
||
└── build-installer.ps1 – Build + Publish + ISCC Pipeline
|
||
```
|
||
|
||
**Dependency direction (strict one-way):**
|
||
`TrayApp` → `Domain` | `Service` → `Domain` + `Infrastructure` | `Infrastructure` → `Domain`
|
||
|
||
## Build & Run
|
||
|
||
```bash
|
||
# Build entire solution
|
||
dotnet build EngineeringSync.slnx
|
||
|
||
# Installer bauen (benötigt Inno Setup 6 installiert)
|
||
.\installer\build-installer.ps1
|
||
|
||
# Run the background service (dev mode)
|
||
dotnet run --project EngineeringSync.Service
|
||
|
||
# Run the WPF tray app
|
||
dotnet run --project EngineeringSync.TrayApp
|
||
|
||
# Run all tests
|
||
dotnet test
|
||
|
||
# Run a single test project
|
||
dotnet test EngineeringSync.Tests --filter "FullyQualifiedName~WatcherServiceTests"
|
||
|
||
# Install as Windows Service (production)
|
||
sc create EngineeringSync binPath="<path>\EngineeringSync.Service.exe"
|
||
```
|
||
|
||
## Key Architecture Decisions
|
||
|
||
### ProjectConfig in DB (not appsettings.json)
|
||
`ProjectConfig` is managed via the TrayApp UI and stored in SQLite. The user can add/edit/delete projects with folder browser dialogs. CRUD operations go through the Service API, which dynamically starts/stops watchers.
|
||
|
||
### FileSystemWatcher Debouncing
|
||
Events (Created, Changed, Renamed, Deleted) are pushed into a `Channel<FileEvent>`. A consumer groups events by `(ProjectId, RelativePath)` within a 2000ms sliding window. SHA-256 hashing against `FileRevision` confirms actual changes before writing a `PendingChange`.
|
||
|
||
### Service API (Kestrel on localhost:5050)
|
||
- **Project CRUD:** `GET/POST/PUT/DELETE /api/projects`
|
||
- **Changes:** `GET /api/changes/{projectId}`, `GET /api/changes/{projectId}/history`
|
||
- **Actions:** `POST /api/sync`, `POST /api/ignore`
|
||
|
||
Backup before overwrite uses timestamped naming: `{filename}_{yyyyMMdd_HHmmss}.bak`
|
||
|
||
### SignalR Hub (`NotificationHub` at `/notifications`)
|
||
- `ReceiveChangeNotification(projectId, projectName, count)` – New pending changes
|
||
- `ProjectConfigChanged()` – Project CRUD happened
|
||
|
||
### TrayApp Windows
|
||
- **ProjectManagementWindow** – CRUD for projects with `FolderBrowserDialog` for path selection
|
||
- **PendingChangesWindow** – DataGrid with project selector, sync/ignore actions, auto-refresh via SignalR
|
||
|
||
All ViewModels use `CommunityToolkit.Mvvm` source generators (`[ObservableProperty]`, `[RelayCommand]`).
|
||
|
||
## Domain Entities
|
||
|
||
| Entity | Key Fields |
|
||
|---|---|
|
||
| `ProjectConfig` | `Id` (Guid), `Name`, `EngineeringPath`, `SimulationPath`, `FileExtensions`, `IsActive`, `CreatedAt` |
|
||
| `FileRevision` | `Id` (Guid), `ProjectId` (FK), `RelativePath`, `FileHash`, `Size`, `LastModified` |
|
||
| `PendingChange` | `Id` (Guid), `ProjectId` (FK), `RelativePath`, `ChangeType` (Created/Modified/Renamed/Deleted), `OldRelativePath?`, `Status` (Pending/Synced/Ignored), `CreatedAt`, `SyncedAt?` |
|