diff --git a/Dashboard/RemoveServerDialog.xaml b/Dashboard/RemoveServerDialog.xaml index 5edef594..dd0d6f02 100644 --- a/Dashboard/RemoveServerDialog.xaml +++ b/Dashboard/RemoveServerDialog.xaml @@ -23,9 +23,9 @@ - + - diff --git a/Dashboard/Services/ServerManager.cs b/Dashboard/Services/ServerManager.cs index cf9099dd..3fcba888 100644 --- a/Dashboard/Services/ServerManager.cs +++ b/Dashboard/Services/ServerManager.cs @@ -152,6 +152,17 @@ public async Task DropMonitorDatabaseAsync(ServerConnection server) using var connection = new SqlConnection(builder.ConnectionString); await connection.OpenAsync(); + // Remove SQL Agent jobs before dropping the database + using var jobCmd = new SqlCommand(@" + IF EXISTS (SELECT 1 FROM msdb.dbo.sysjobs WHERE name = N'PerformanceMonitor - Collection') + EXEC msdb.dbo.sp_delete_job @job_name = N'PerformanceMonitor - Collection', @delete_unused_schedule = 1; + IF EXISTS (SELECT 1 FROM msdb.dbo.sysjobs WHERE name = N'PerformanceMonitor - Data Retention') + EXEC msdb.dbo.sp_delete_job @job_name = N'PerformanceMonitor - Data Retention', @delete_unused_schedule = 1; + IF EXISTS (SELECT 1 FROM msdb.dbo.sysjobs WHERE name = N'PerformanceMonitor - Hung Job Monitor') + EXEC msdb.dbo.sp_delete_job @job_name = N'PerformanceMonitor - Hung Job Monitor', @delete_unused_schedule = 1;", connection); + jobCmd.CommandTimeout = 30; + await jobCmd.ExecuteNonQueryAsync(); + // Close active connections before dropping using var killCmd = new SqlCommand(@" IF DB_ID('PerformanceMonitor') IS NOT NULL @@ -162,7 +173,7 @@ IF DB_ID('PerformanceMonitor') IS NOT NULL killCmd.CommandTimeout = 30; await killCmd.ExecuteNonQueryAsync(); - Logger.Info($"Dropped PerformanceMonitor database on '{server.DisplayName}'"); + Logger.Info($"Dropped PerformanceMonitor database and Agent jobs on '{server.DisplayName}'"); } public void UpdateLastConnected(string id) diff --git a/Installer/Program.cs b/Installer/Program.cs index 952fe273..a47ed83c 100644 --- a/Installer/Program.cs +++ b/Installer/Program.cs @@ -649,7 +649,7 @@ INSERT...WHERE NOT EXISTS re-populates with current recommended values */ if (resetSchedule && fileName.StartsWith("04_", StringComparison.Ordinal)) { - sqlContent = "TRUNCATE TABLE config.collection_schedule;\nGO\n" + sqlContent; + sqlContent = "TRUNCATE TABLE [PerformanceMonitor].[config].[collection_schedule];\nGO\n" + sqlContent; Console.Write("(resetting schedule) "); } @@ -1155,17 +1155,22 @@ private static List GetApplicableUpgrades( return upgradeFolders; } - /*Parse current version - if invalid, skip upgrades*/ - if (!Version.TryParse(currentVersion, out var current)) + /*Parse current version - if invalid, skip upgrades + Normalize to 3-part (Major.Minor.Build) to avoid Revision mismatch: + folder names use 3-part "1.3.0" but DB stores 4-part "1.3.0.0" + Version(1,3,0).Revision=-1 which breaks >= comparison with Version(1,3,0,0)*/ + if (!Version.TryParse(currentVersion, out var currentRaw)) { return upgradeFolders; } + var current = new Version(currentRaw.Major, currentRaw.Minor, currentRaw.Build); /*Parse target version - if invalid, skip upgrades*/ - if (!Version.TryParse(targetVersion, out var target)) + if (!Version.TryParse(targetVersion, out var targetRaw)) { return upgradeFolders; } + var target = new Version(targetRaw.Major, targetRaw.Minor, targetRaw.Build); /* Find all upgrade folders matching pattern: {from}-to-{to} diff --git a/InstallerGui/MainWindow.xaml.cs b/InstallerGui/MainWindow.xaml.cs index a516f680..91a199d7 100644 --- a/InstallerGui/MainWindow.xaml.cs +++ b/InstallerGui/MainWindow.xaml.cs @@ -40,7 +40,9 @@ public partial class MainWindow : Window private static readonly SolidColorBrush WarningBrush = new(Color.FromRgb(0xFF, 0xC1, 0x07)); // Yellow /* - Cached version string + Cached version strings + Display version includes git hash suffix for UI/logs + Assembly version is clean (e.g. "2.0.0.0") for upgrade version comparison */ private static readonly string AppVersion = Assembly.GetExecutingAssembly() @@ -48,6 +50,10 @@ Cached version string ?? Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown"; + private static readonly string AppAssemblyVersion = + Assembly.GetExecutingAssembly().GetName().Version?.ToString() + ?? "Unknown"; + private static readonly char[] NewLineChars = { '\r', '\n' }; public MainWindow() @@ -260,7 +266,7 @@ private async void TestConnection_Click(object sender, RoutedEventArgs e) var upgrades = InstallationService.GetApplicableUpgrades( _monitorRootDirectory, _installedVersion, - AppVersion); + AppAssemblyVersion); if (upgrades.Count > 0) { LogMessage($"Found {upgrades.Count} upgrade(s) to apply", "Warning"); @@ -377,7 +383,7 @@ private async void Install_Click(object sender, RoutedEventArgs e) _monitorRootDirectory, _connectionString, _installedVersion, - AppVersion, + AppAssemblyVersion, progress, cancellationToken); diff --git a/InstallerGui/Services/InstallationService.cs b/InstallerGui/Services/InstallationService.cs index 7c061461..512a6ab3 100644 --- a/InstallerGui/Services/InstallationService.cs +++ b/InstallerGui/Services/InstallationService.cs @@ -414,7 +414,7 @@ Execute SQL files /*Reset schedule to defaults if requested*/ if (resetSchedule && fileName.StartsWith("04_", StringComparison.Ordinal)) { - sqlContent = "TRUNCATE TABLE config.collection_schedule;\nGO\n" + sqlContent; + sqlContent = "TRUNCATE TABLE [PerformanceMonitor].[config].[collection_schedule];\nGO\n" + sqlContent; progress?.Report(new InstallationProgress { Message = "Resetting schedule to recommended defaults...", @@ -1053,17 +1053,22 @@ public static List GetApplicableUpgrades( return upgrades; } - /*Parse current version - if invalid, skip upgrades*/ - if (!Version.TryParse(currentVersion, out var current)) + /*Parse current version - if invalid, skip upgrades + Normalize to 3-part (Major.Minor.Build) to avoid Revision mismatch: + folder names use 3-part "1.3.0" but DB stores 4-part "1.3.0.0" + Version(1,3,0).Revision=-1 which breaks >= comparison with Version(1,3,0,0)*/ + if (!Version.TryParse(currentVersion, out var currentRaw)) { return upgrades; } + var current = new Version(currentRaw.Major, currentRaw.Minor, currentRaw.Build); /*Parse target version - if invalid, skip upgrades*/ - if (!Version.TryParse(targetVersion, out var target)) + if (!Version.TryParse(targetVersion, out var targetRaw)) { return upgrades; } + var target = new Version(targetRaw.Major, targetRaw.Minor, targetRaw.Build); /* Find all upgrade folders matching pattern: {from}-to-{to}