Browse Source

Uninstaller: Try to shut down a running SyncTrayzor instances

Fixes #516
Antony Male 4 years ago
parent
commit
23dfac124d

+ 5 - 0
installer/common.iss

@@ -324,9 +324,14 @@ begin
   end;
 end;
 
+[UninstallRun]
+Filename: "{app}\SyncTrayzor.exe"; Parameters: "--shutdown"; RunOnceId: "ShutdownSyncTrayzor"; Flags: skipifdoesntexist
+
 [UninstallDelete]
 Type: files; Name: "{app}\ProcessRunner.exe.old"
 Type: files; Name: "{app}\InstallCount.txt"
+; Not sure why this gets left behind, but it does. Clean it up...
+Type: filesandordirs; Name: "{app}\locales"
 Type: filesandordirs; Name: "{userappdata}\{#AppDataFolder}"
 Type: filesandordirs; Name: "{localappdata}\{#AppDataFolder}"
 

+ 21 - 0
src/SyncTrayzor/Bootstrapper.cs

@@ -119,6 +119,21 @@ namespace SyncTrayzor
             {
                 try
                 {
+                    if (this.options.Shutdown)
+                    {
+                        client.Shutdown();
+                        // Give it some time to shut down
+                        var elapsed = Stopwatch.StartNew();
+                        while (elapsed.Elapsed < TimeSpan.FromSeconds(10) &&
+                            this.Container.Get<IIpcCommsClientFactory>().TryCreateClient() != null)
+                        {
+                            Thread.Sleep(100);
+                        }
+                        // Wait another half-second -- it seems it can take the browser process a little longer to exit
+                        Thread.Sleep(500);
+                        Environment.Exit(0);
+                    }
+
                     if (this.options.StartSyncthing || this.options.StopSyncthing)
                     {
                         if (this.options.StartSyncthing)
@@ -142,6 +157,12 @@ namespace SyncTrayzor
                     logger.Error(e, $"Failed to talk to {client}: {e.Message}. Pretending that it doesn't exist...");
                 }
             }
+            
+            // If we got this far, there probably isn't another instance running, and we should just shut down
+            if (this.options.Shutdown)
+            {
+                Environment.Exit(0);
+            }
 
             var configurationProvider = this.Container.Get<IConfigurationProvider>();
             configurationProvider.Initialize(AppSettings.Instance.DefaultUserConfiguration);

+ 9 - 0
src/SyncTrayzor/Services/CommandLineOptionsParser.cs

@@ -1,7 +1,9 @@
 using Mono.Options;
 using Stylet;
 using System.IO;
+using System.Runtime.InteropServices.ComTypes;
 using System.Windows;
+using System.Windows.Forms;
 
 namespace SyncTrayzor.Services
 {
@@ -9,6 +11,7 @@ namespace SyncTrayzor.Services
     {
         private readonly IWindowManager windowManager;
 
+        public bool Shutdown { get; private set; }
         public bool StartMinimized { get; private set; }
         public bool StartSyncthing { get; private set; }
         public bool StopSyncthing { get; private set; }
@@ -30,6 +33,7 @@ namespace SyncTrayzor.Services
             bool show = false;
 
             var options = new OptionSet()
+                .Add("shutdown", "\nIf another SyncTrayzor process is running, tell it to shutdown.", v => this.Shutdown = true)
                 .Add("start-syncthing", "\nIf another SyncTrayzor process is running, tell it to start Syncthing. Otherwise, launch with Syncthing started regardless of configuration.", v => this.StartSyncthing = true)
                 .Add("stop-syncthing", "\nIf another SyncTrayzor process is running, tell it to stop Syncthing. Otherwise, launch with Syncthing stopped regardless of configuration.", v => this.StopSyncthing = true)
                 .Add("noautostart", null, v => this.StopSyncthing = true, hidden: true)
@@ -47,6 +51,11 @@ namespace SyncTrayzor.Services
                 return false;
             }
 
+            if (this.Shutdown && (this.StartSyncthing || this.StopSyncthing || minimized || show))
+            {
+                this.windowManager.ShowMessageBox("--shutdown may not be used with any other options", "Error", icon: MessageBoxImage.Error);
+                return false;
+            }
             if (this.StartSyncthing && this.StopSyncthing)
             {
                 this.windowManager.ShowMessageBox("--start-syncthing and --stop-syncthing may not be used together", "Error", icon: MessageBoxImage.Error);

+ 6 - 0
src/SyncTrayzor/Services/Ipc/IpcCommsClient.cs

@@ -14,6 +14,7 @@ namespace SyncTrayzor.Services.Ipc
 
     public interface IIpcCommsClient
     {
+        void Shutdown();
         void ShowMainWindow();
         void StartSyncthing();
         void StopSyncthing();
@@ -30,6 +31,11 @@ namespace SyncTrayzor.Services.Ipc
             this.pid = pid;
         }
 
+        public void Shutdown()
+        {
+            this.SendCommand("Shutdown");
+        }
+
         public void ShowMainWindow()
         {
             this.SendCommand("ShowMainWindow");

+ 12 - 1
src/SyncTrayzor/Services/Ipc/IpcCommsServer.cs

@@ -20,15 +20,17 @@ namespace SyncTrayzor.Services.Ipc
         private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
 
         private readonly ISyncthingManager syncthingManager;
+        private readonly IApplicationState applicationState;
         private readonly IApplicationWindowState windowState;
 
         private CancellationTokenSource cts;
 
         public string PipeName =>  $"SyncTrayzor-{Process.GetCurrentProcess().Id}";
 
-        public IpcCommsServer(ISyncthingManager syncthingManager, IApplicationWindowState windowState)
+        public IpcCommsServer(ISyncthingManager syncthingManager, IApplicationState applicationState, IApplicationWindowState windowState)
         {
             this.syncthingManager = syncthingManager;
+            this.applicationState = applicationState;
             this.windowState = windowState;
         }
 
@@ -101,6 +103,10 @@ namespace SyncTrayzor.Services.Ipc
         {
             switch (command)
             {
+                case "Shutdown":
+                    this.Shutdown();
+                    return "OK";
+
                 case "ShowMainWindow":
                     this.ShowMainWindow();
                     return "OK";
@@ -118,6 +124,11 @@ namespace SyncTrayzor.Services.Ipc
             }
         }
 
+        private void Shutdown()
+        {
+            this.applicationState.Shutdown();
+        }
+
         private void ShowMainWindow()
         {
             this.windowState.EnsureInForeground();