From fcf29a4b139e23d81fa066e878df7d85c31e25e5 Mon Sep 17 00:00:00 2001 From: Anton Kasyanov Date: Sat, 15 Oct 2016 22:50:13 +0300 Subject: [PATCH] Add a single-instance check on application startup --- Eve-O-Preview/Program.cs | 42 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/Eve-O-Preview/Program.cs b/Eve-O-Preview/Program.cs index e0090bc..3203ca7 100644 --- a/Eve-O-Preview/Program.cs +++ b/Eve-O-Preview/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Windows.Forms; using EveOPreview.Configuration; using EveOPreview.UI; @@ -7,16 +8,28 @@ namespace EveOPreview { static class Program { + private static string MutexName = "EVE-O Preview Single Instance Mutex"; private static string ConfigParameterName = "--config:"; /// The main entry point for the application. [STAThread] static void Main(string[] args) { + // The very usual Mutex-based single-instance screening + // 'token' variable is used to store reference to the instance Mutex + // during the app lifetime + object token = Program.GetInstanceToken(); + + // If it was not possible to aquite the app token then another app instance is already running + // Nothing to do here + if (token == null) + { + return; + } + Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - // TODO Switch to another container that provides signed assemblies IIocContainer container = new LightInjectContainer(); // UI classes @@ -37,6 +50,8 @@ namespace EveOPreview controller.Create().ConfigFileName = Program.GetCustomConfigFile(args); controller.Run(); + + token = null; } // Parse startup parameters @@ -68,5 +83,30 @@ namespace EveOPreview return configFile; } + + private static object GetInstanceToken() + { + // The code might look overcomplicated here for a single Mutex operation + // Yet we had already experienced a Windows-level issue + // where .NET finalizer theread was literally paralyzed by + // a failed Mutex operation. That did lead to weird OutOfMemory + // exceptions later + try + { + Mutex mutex = Mutex.OpenExisting(Program.MutexName); + // if that didn't fail then anotherinstance is already running + return null; + } + catch (UnauthorizedAccessException) + { + return null; + } + catch (Exception) + { + bool result; + Mutex token = new Mutex(true, Program.MutexName, out result); + return result ? token : null; + } + } } } \ No newline at end of file