From 725d70493f0f56e73a46d87d5f8eecd1f80df3cc Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Fri, 21 Mar 2014 10:34:34 +0100 Subject: [PATCH] Improved handling of multiple instance detection --- .../GUI/Duplicati.GUI.TrayIcon/Program.cs | 20 ++++++++-- Duplicati/Server/Program.cs | 38 ++++++++++++------- Duplicati/Server/SingleInstance.cs | 34 +++++++++++++++++ 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs index 7fd459f44..67a23b33d 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Program.cs @@ -82,9 +82,21 @@ namespace Duplicati.GUI.TrayIcon else toolkit = DEFAULT_TOOLKIT; } - - - using (var hosted = Library.Utility.Utility.ParseBoolOption(options, NOHOSTEDSERVER_OPTION) ? null : new HostedInstanceKeeper(_args)) + + HostedInstanceKeeper hosted = null; + if (!Library.Utility.Utility.ParseBoolOption(options, NOHOSTEDSERVER_OPTION)) + { + try + { + hosted = new HostedInstanceKeeper(_args); + } + catch (Server.SingleInstance.MultipleInstanceException) + { + return; + } + } + + using (hosted) { string url; if (!options.TryGetValue(HOSTURL_OPTION, out url)) @@ -104,6 +116,8 @@ namespace Duplicati.GUI.TrayIcon { using(var tk = RunTrayIcon(toolkit)) { + if (hosted != null && Server.Program.Instance != null) + Server.Program.Instance.SecondInstanceDetected += new Server.SingleInstance.SecondInstanceDelegate(x => { tk.ShowUrlInWindow(url); }); tk.Init(_args); } } diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs index 28867a583..b77976400 100644 --- a/Duplicati/Server/Program.cs +++ b/Duplicati/Server/Program.cs @@ -32,6 +32,11 @@ namespace Duplicati.Server /// public static string DATAFOLDER { get { return Library.Utility.Utility.AppendDirSeparator(Environment.ExpandEnvironmentVariables("%" + DATAFOLDER_ENV_NAME + "%").TrimStart('"').TrimEnd('"')); } } + /// + /// The single instance + /// + public static SingleInstance Instance = null; + /// /// A flag indicating if database encryption is in use /// @@ -199,13 +204,6 @@ namespace Duplicati.Server foreach (string s in Enum.GetNames(typeof(Duplicati.Library.Logging.LogMessageType))) if (s.Equals(commandlineOptions["log-level"].Trim(), StringComparison.InvariantCultureIgnoreCase)) Duplicati.Library.Logging.Log.LogLevel = (Duplicati.Library.Logging.LogMessageType)Enum.Parse(typeof(Duplicati.Library.Logging.LogMessageType), s); - - if (commandlineOptions.ContainsKey("log-file")) - { - if (System.IO.File.Exists(commandlineOptions["log-file"])) - System.IO.File.Delete(commandlineOptions["log-file"]); - Duplicati.Library.Logging.Log.CurrentLog = new Duplicati.Library.Logging.StreamLog(commandlineOptions["log-file"]); - } //Set the %DUPLICATI_HOME% env variable, if it is not already set if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(DATAFOLDER_ENV_NAME))) @@ -229,14 +227,12 @@ namespace Duplicati.Server #endif } - SingleInstance instance = null; - try { try { //This will also create Program.DATAFOLDER if it does not exist - instance = new SingleInstance(ApplicationName, Program.DATAFOLDER); + Instance = new SingleInstance(ApplicationName, Program.DATAFOLDER); } catch (Exception ex) { @@ -251,7 +247,7 @@ namespace Duplicati.Server } } - if (!instance.IsFirstInstance) + if (!Instance.IsFirstInstance) { if (writeConsole) { @@ -260,10 +256,16 @@ namespace Duplicati.Server } else { - throw new Exception(Strings.Program.AnotherInstanceDetected); + throw new SingleInstance.MultipleInstanceException(Strings.Program.AnotherInstanceDetected); } } + if (commandlineOptions.ContainsKey("log-file")) + { + if (System.IO.File.Exists(commandlineOptions["log-file"])) + System.IO.File.Delete(commandlineOptions["log-file"]); + Duplicati.Library.Logging.Log.CurrentLog = new Duplicati.Library.Logging.StreamLog(commandlineOptions["log-file"]); + } Version sqliteVersion = new Version((string)Duplicati.Library.Utility.SQLiteLoader.SQLiteConnectionType.GetProperty("SQLiteVersion").GetValue(null, null)); if (sqliteVersion < new Version(3, 6, 3)) @@ -345,6 +347,14 @@ namespace Duplicati.Server ServerStartedEvent.Set(); ApplicationExitEvent.WaitOne(); } + catch (SingleInstance.MultipleInstanceException mex) + { + System.Diagnostics.Trace.WriteLine(string.Format(Strings.Program.SeriousError, mex.ToString())); + if (writeConsole) + Console.WriteLine(Strings.Program.SeriousError, mex.ToString()); + else + throw mex; + } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(string.Format(Strings.Program.SeriousError, ex.ToString())); @@ -361,8 +371,8 @@ namespace Duplicati.Server Scheduler.Terminate(true); if (WorkThread != null) WorkThread.Terminate(true); - if (instance != null) - instance.Dispose(); + if (Instance != null) + Instance.Dispose(); #if DEBUG //Flush the file diff --git a/Duplicati/Server/SingleInstance.cs b/Duplicati/Server/SingleInstance.cs index 86818201f..fbdeb572c 100644 --- a/Duplicati/Server/SingleInstance.cs +++ b/Duplicati/Server/SingleInstance.cs @@ -30,6 +30,40 @@ namespace Duplicati.Server /// public class SingleInstance : IDisposable { + /// + /// An exception that can be thrown to indicate a second instance was running + /// + [Serializable] + public class MultipleInstanceException : Exception + { + /// + /// Constructs the new exception + /// + public MultipleInstanceException() + : base() + { + } + + /// + /// Constructs the new exception + /// + /// The message + public MultipleInstanceException(string message) + : base(message) + { + } + + /// + /// Constructs the new exception + /// + /// The message + /// The inner exception + public MultipleInstanceException(string message, Exception innerException) + : base(message, innerException) + { + } + } + /// /// The folder where control files are placed ///