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}