From 711fab94af2eb1331a64e0bac6ed3823c81af44b Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Fri, 22 Nov 2024 16:52:48 +0100 Subject: [PATCH 1/2] Fixed MSI upgrade issue. This changes the removal order to avoid duplicate entries being installed. Upper-cased the upgrade code as that is what WiX does. --- ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs | 2 +- ReleaseBuilder/Resources/Windows/Agent/UpgradeData.wxi | 2 +- ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs | 2 +- ReleaseBuilder/Resources/Windows/TrayIcon/UpgradeData.wxi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs b/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs index f0084f4f6..c191d38f0 100644 --- a/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs +++ b/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs @@ -69,7 +69,7 @@ - + diff --git a/ReleaseBuilder/Resources/Windows/Agent/UpgradeData.wxi b/ReleaseBuilder/Resources/Windows/Agent/UpgradeData.wxi index 5cf2fc65a..f1813da74 100644 --- a/ReleaseBuilder/Resources/Windows/Agent/UpgradeData.wxi +++ b/ReleaseBuilder/Resources/Windows/Agent/UpgradeData.wxi @@ -1,6 +1,6 @@ - + diff --git a/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs b/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs index 321113e1f..73a0111cd 100644 --- a/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs +++ b/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs @@ -70,7 +70,7 @@ - + diff --git a/ReleaseBuilder/Resources/Windows/TrayIcon/UpgradeData.wxi b/ReleaseBuilder/Resources/Windows/TrayIcon/UpgradeData.wxi index 714b792ea..a8449f755 100644 --- a/ReleaseBuilder/Resources/Windows/TrayIcon/UpgradeData.wxi +++ b/ReleaseBuilder/Resources/Windows/TrayIcon/UpgradeData.wxi @@ -1,6 +1,6 @@ - + From 9de6869e5bb55998bb772db18a5a86d8680b329c Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Fri, 22 Nov 2024 16:54:06 +0100 Subject: [PATCH 2/2] Added support for restarting the Windows Service, if it is running. --- .../Resources/Windows/Agent/Duplicati.wxs | 19 +++++ .../Resources/Windows/Agent/StartService.js | 47 +++++++++++ .../Resources/Windows/Agent/StopService.js | 78 +++++++++++++++++++ .../Resources/Windows/TrayIcon/Duplicati.wxs | 20 +++++ .../Windows/TrayIcon/StartService.js | 47 +++++++++++ .../Resources/Windows/TrayIcon/StopService.js | 78 +++++++++++++++++++ 6 files changed, 289 insertions(+) create mode 100644 ReleaseBuilder/Resources/Windows/Agent/StartService.js create mode 100644 ReleaseBuilder/Resources/Windows/Agent/StopService.js create mode 100644 ReleaseBuilder/Resources/Windows/TrayIcon/StartService.js create mode 100644 ReleaseBuilder/Resources/Windows/TrayIcon/StopService.js diff --git a/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs b/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs index c191d38f0..ffca583d8 100644 --- a/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs +++ b/ReleaseBuilder/Resources/Windows/Agent/Duplicati.wxs @@ -70,6 +70,10 @@ + + + + SERVICE_WAS_STOPPED=1 @@ -79,5 +83,20 @@ + + + + + + + diff --git a/ReleaseBuilder/Resources/Windows/Agent/StartService.js b/ReleaseBuilder/Resources/Windows/Agent/StartService.js new file mode 100644 index 000000000..05136d497 --- /dev/null +++ b/ReleaseBuilder/Resources/Windows/Agent/StartService.js @@ -0,0 +1,47 @@ +function LogMessage(message) { + var record = Session.Installer.CreateRecord(1); + record.StringData(1) = message; + var INSTALLMESSAGE_INFO = 0x04000000; + // MessageType 1 = Shown as warning in the UI + Session.Message(INSTALLMESSAGE_INFO, record); // MessageType 1 = informational log +} + +// Function to start a service +function StartService(serviceName) { + var service; + + try { + // Connect to the WMI service + var locator = new ActiveXObject("WbemScripting.SWbemLocator"); + var root = locator.ConnectServer(".", "root\\CIMV2"); + + // Query the service + var query = "SELECT * FROM Win32_Service WHERE Name = '" + serviceName + "'"; + var services = root.ExecQuery(query); + + // Check if the service exists and start it if not already running + var enumerator = new Enumerator(services); + if (!enumerator.atEnd()) { + service = enumerator.item(); + if (service.State != "Running") { + service.StartService(); + LogMessage("Service '" + serviceName + "' started successfully."); + return 0; // Success + } else { + LogMessage("Service '" + serviceName + "' is already running."); + return 0; // Success + } + } else { + LogMessage("Service '" + serviceName + "' not found."); + return 1; // Failure + } + } catch (e) { + LogMessage("Error starting service '" + serviceName + "': " + e.message); + return 1; // Failure + } +} + +// Entry point for the custom action +function CustomAction() { + return StartService("Duplicati.Agent"); +} \ No newline at end of file diff --git a/ReleaseBuilder/Resources/Windows/Agent/StopService.js b/ReleaseBuilder/Resources/Windows/Agent/StopService.js new file mode 100644 index 000000000..33a64a1b1 --- /dev/null +++ b/ReleaseBuilder/Resources/Windows/Agent/StopService.js @@ -0,0 +1,78 @@ +function LogMessage(message) { + var record = Session.Installer.CreateRecord(1); + record.StringData(1) = message; + var INSTALLMESSAGE_INFO = 0x04000000; + // MessageType 1 = Shown as warning in the UI + Session.Message(INSTALLMESSAGE_INFO, record); +} + +// Function to check the status of a Windows service +function CheckServiceStatus(serviceName) { + var locator; + var root; + var query; + var services; + var enumerator; + var service; + + try { + // Connect to WMI (Windows Management Instrumentation) + locator = new ActiveXObject("WbemScripting.SWbemLocator"); + root = locator.ConnectServer(".", "root\\CIMV2"); + + // Query for the service by name + query = "SELECT * FROM Win32_Service WHERE Name = '" + serviceName + "'"; + services = root.ExecQuery(query); + + // Enumerate the results + enumerator = new Enumerator(services); + if (!enumerator.atEnd()) { + service = enumerator.item(); + + // Check if the service is running + if (service.State == "Running") { + LogMessage("Service '" + serviceName + "' is running. Attempting to stop it."); + + // Attempt to stop the service + var result = service.StopService(); + if (result === 0) { + LogMessage("Service '" + serviceName + "' stopped successfully."); + } else { + LogMessage("Failed to stop service '" + serviceName + "'. Error code: " + result); + } + + // Service was running and stopped + Session.Property("SERVICE_WAS_STOPPED") = "1"; + return true; + } else { + LogMessage("Service '" + serviceName + "' is not running."); + return false; // Service is not running + } + } else { + LogMessage("Service '" + serviceName + "' not found."); + return null; // Service not found + } + } catch (e) { + LogMessage("Error checking service status: " + e.message); + return null; // Error occurred + } +} + +// Entry point for the custom action +function CustomAction() { + // Check the service status + var isRunning = CheckServiceStatus("Duplicati.Agent"); + + // Set a property in the installer to track the service status + if (isRunning === true) { + Session.Property("SERVICE_WAS_STOPPED") = "1"; // Service was running + } else if (isRunning === false) { + Session.Property("SERVICE_WAS_STOPPED") = "0"; // Service was not running + } else { + // Service not found or error occurred + LogMessage("Failed to determine service status."); + Session.Property("SERVICE_WAS_STOPPED") = "0"; // Service was not running + } + + return 0; // Success +} \ No newline at end of file diff --git a/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs b/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs index 73a0111cd..928fe26dd 100644 --- a/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs +++ b/ReleaseBuilder/Resources/Windows/TrayIcon/Duplicati.wxs @@ -71,6 +71,10 @@ + + + + SERVICE_WAS_STOPPED=1 @@ -79,6 +83,22 @@ + + + + + + + + diff --git a/ReleaseBuilder/Resources/Windows/TrayIcon/StartService.js b/ReleaseBuilder/Resources/Windows/TrayIcon/StartService.js new file mode 100644 index 000000000..65e51a02c --- /dev/null +++ b/ReleaseBuilder/Resources/Windows/TrayIcon/StartService.js @@ -0,0 +1,47 @@ +function LogMessage(message) { + var record = Session.Installer.CreateRecord(1); + record.StringData(1) = message; + var INSTALLMESSAGE_INFO = 0x04000000; + // MessageType 1 = Shown as warning in the UI + Session.Message(INSTALLMESSAGE_INFO, record); // MessageType 1 = informational log +} + +// Function to start a service +function StartService(serviceName) { + var service; + + try { + // Connect to the WMI service + var locator = new ActiveXObject("WbemScripting.SWbemLocator"); + var root = locator.ConnectServer(".", "root\\CIMV2"); + + // Query the service + var query = "SELECT * FROM Win32_Service WHERE Name = '" + serviceName + "'"; + var services = root.ExecQuery(query); + + // Check if the service exists and start it if not already running + var enumerator = new Enumerator(services); + if (!enumerator.atEnd()) { + service = enumerator.item(); + if (service.State != "Running") { + service.StartService(); + LogMessage("Service '" + serviceName + "' started successfully."); + return 0; // Success + } else { + LogMessage("Service '" + serviceName + "' is already running."); + return 0; // Success + } + } else { + LogMessage("Service '" + serviceName + "' not found."); + return 1; // Failure + } + } catch (e) { + LogMessage("Error starting service '" + serviceName + "': " + e.message); + return 1; // Failure + } +} + +// Entry point for the custom action +function CustomAction() { + return StartService("Duplicati"); +} \ No newline at end of file diff --git a/ReleaseBuilder/Resources/Windows/TrayIcon/StopService.js b/ReleaseBuilder/Resources/Windows/TrayIcon/StopService.js new file mode 100644 index 000000000..aacebcda2 --- /dev/null +++ b/ReleaseBuilder/Resources/Windows/TrayIcon/StopService.js @@ -0,0 +1,78 @@ +function LogMessage(message) { + var record = Session.Installer.CreateRecord(1); + record.StringData(1) = message; + var INSTALLMESSAGE_INFO = 0x04000000; + // MessageType 1 = Shown as warning in the UI + Session.Message(INSTALLMESSAGE_INFO, record); +} + +// Function to check the status of a Windows service +function CheckServiceStatus(serviceName) { + var locator; + var root; + var query; + var services; + var enumerator; + var service; + + try { + // Connect to WMI (Windows Management Instrumentation) + locator = new ActiveXObject("WbemScripting.SWbemLocator"); + root = locator.ConnectServer(".", "root\\CIMV2"); + + // Query for the service by name + query = "SELECT * FROM Win32_Service WHERE Name = '" + serviceName + "'"; + services = root.ExecQuery(query); + + // Enumerate the results + enumerator = new Enumerator(services); + if (!enumerator.atEnd()) { + service = enumerator.item(); + + // Check if the service is running + if (service.State == "Running") { + LogMessage("Service '" + serviceName + "' is running. Attempting to stop it."); + + // Attempt to stop the service + var result = service.StopService(); + if (result === 0) { + LogMessage("Service '" + serviceName + "' stopped successfully."); + } else { + LogMessage("Failed to stop service '" + serviceName + "'. Error code: " + result); + } + + // Service was running and stopped + Session.Property("SERVICE_WAS_STOPPED") = "1"; + return true; + } else { + LogMessage("Service '" + serviceName + "' is not running."); + return false; // Service is not running + } + } else { + LogMessage("Service '" + serviceName + "' not found."); + return null; // Service not found + } + } catch (e) { + LogMessage("Error checking service status: " + e.message); + return null; // Error occurred + } +} + +// Entry point for the custom action +function CustomAction() { + // Check the service status + var isRunning = CheckServiceStatus("Duplicati"); + + // Set a property in the installer to track the service status + if (isRunning === true) { + Session.Property("SERVICE_WAS_STOPPED") = "1"; // Service was running + } else if (isRunning === false) { + Session.Property("SERVICE_WAS_STOPPED") = "0"; // Service was not running + } else { + // Service not found or error occurred + LogMessage("Failed to determine service status."); + Session.Property("SERVICE_WAS_STOPPED") = "0"; // Service was not running + } + + return 0; // Success +} \ No newline at end of file