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>
103 lines
3.2 KiB
C#
103 lines
3.2 KiB
C#
using System.Windows;
|
|
using System.Windows.Media;
|
|
using EngineeringSync.Setup.Services;
|
|
using EngineeringSync.Setup.ViewModels;
|
|
|
|
namespace EngineeringSync.Setup.Views.Pages;
|
|
|
|
public partial class InstallingPage : WizardPageBase
|
|
{
|
|
private readonly InstallerService _installer;
|
|
private bool _started;
|
|
|
|
public InstallingPage(WizardViewModel wizard, InstallerService installer) : base(wizard)
|
|
{
|
|
_installer = installer;
|
|
InitializeComponent();
|
|
}
|
|
|
|
private async void Page_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
// Nur einmal starten (Page kann bei Navigation neu erzeugt werden)
|
|
if (_started) return;
|
|
_started = true;
|
|
|
|
_installer.Progress += OnProgress;
|
|
_installer.LogMessage += OnLogMessage;
|
|
|
|
try
|
|
{
|
|
// Button während Installation deaktivieren
|
|
Wizard.SetInstallingState(true);
|
|
|
|
await _installer.InstallAsync();
|
|
ShowSuccess();
|
|
|
|
// Buttons wieder aktivieren vor Navigation
|
|
Wizard.SetInstallingState(false);
|
|
Wizard.NavigateTo(7); // → CompletionPage
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError(ex.Message);
|
|
// Buttons wieder aktivieren im Fehlerfall
|
|
Wizard.SetInstallingState(false);
|
|
}
|
|
finally
|
|
{
|
|
_installer.Progress -= OnProgress;
|
|
_installer.LogMessage -= OnLogMessage;
|
|
}
|
|
}
|
|
|
|
private void OnProgress(int percent, string step)
|
|
{
|
|
Dispatcher.Invoke(() =>
|
|
{
|
|
ProgressBar.Value = percent;
|
|
ProgressText.Text = $"{percent}%";
|
|
StepText.Text = step;
|
|
});
|
|
}
|
|
|
|
private void OnLogMessage(string message)
|
|
{
|
|
Dispatcher.Invoke(() =>
|
|
{
|
|
var ts = DateTime.Now.ToString("HH:mm:ss");
|
|
LogText.Text += $"[{ts}] {message}\n";
|
|
LogScrollViewer.ScrollToEnd();
|
|
});
|
|
}
|
|
|
|
private void ShowSuccess()
|
|
{
|
|
Dispatcher.Invoke(() =>
|
|
{
|
|
ResultBanner.Background = new SolidColorBrush(Color.FromRgb(232, 245, 233));
|
|
ResultIcon.Text = "\uE73E";
|
|
ResultIcon.Foreground = new SolidColorBrush(Color.FromRgb(16, 124, 16));
|
|
ResultText.Text = "Installation erfolgreich abgeschlossen.";
|
|
ResultText.Foreground = new SolidColorBrush(Color.FromRgb(16, 124, 16));
|
|
ResultBanner.Visibility = Visibility.Visible;
|
|
SubtitleText.Text = "Alle Komponenten wurden erfolgreich installiert.";
|
|
ProgressBar.Value = 100;
|
|
ProgressText.Text = "100%";
|
|
});
|
|
}
|
|
|
|
private void ShowError(string message)
|
|
{
|
|
Dispatcher.Invoke(() =>
|
|
{
|
|
ResultBanner.Background = new SolidColorBrush(Color.FromRgb(255, 235, 238));
|
|
ResultIcon.Text = "\uE783";
|
|
ResultIcon.Foreground = new SolidColorBrush(Color.FromRgb(196, 43, 28));
|
|
ResultText.Text = $"Fehler: {message}";
|
|
ResultText.Foreground = new SolidColorBrush(Color.FromRgb(196, 43, 28));
|
|
ResultBanner.Visibility = Visibility.Visible;
|
|
SubtitleText.Text = "Die Installation konnte nicht abgeschlossen werden.";
|
|
});
|
|
}
|
|
}
|