Files
EngineeringSync/EngineeringSync.Setup/Views/Pages/InstallingPage.xaml.cs
EngineeringSync 04ae8a0aae Initial commit: EngineeringSync v1.0.0
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>
2026-03-26 21:52:26 +01:00

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.";
});
}
}