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>
4.1 KiB
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
# 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 changesProjectConfigChanged()– Project CRUD happened
TrayApp Windows
- ProjectManagementWindow – CRUD for projects with
FolderBrowserDialogfor 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? |