using System; using System.Threading; using System.Windows.Forms; using EveOPreview.Configuration; using EveOPreview.Presenters; using EveOPreview.Services; using EveOPreview.View; using MediatR; namespace EveOPreview { static class Program { private static string MutexName = "EVE-O Preview Single Instance Mutex"; /// The main entry point for the application. [STAThread] static void Main() { #if DEBUG var expirationDate = new DateTime(2019, 5, 1); if (DateTime.Today >= expirationDate) { MessageBox.Show(@"This Beta version is expired. Please download a new build at https://github.com/Phrynohyas/eve-o-preview/releases", @"EVE-O Preview", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } #endif // 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 acquire the app token then another app instance is already running // Nothing to do here if (token == null) { return; } ExceptionHandler handler = new ExceptionHandler(); handler.SetupExceptionHandlers(); IApplicationController controller = Program.InitializeApplicationController(); Program.InitializeWinForms(); controller.Run(); } 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 thread was literally paralyzed by // a failed Mutex operation. That did lead to weird OutOfMemory // exceptions later try { Mutex.OpenExisting(Program.MutexName); // if that didn't fail then another instance is already running return null; } catch (UnauthorizedAccessException) { return null; } catch (Exception) { Mutex token = new Mutex(true, Program.MutexName, out var result); return result ? token : null; } } private static void InitializeWinForms() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); } private static IApplicationController InitializeApplicationController() { IIocContainer container = new LightInjectContainer(); // Singleton registration is used for services // Low-level services container.Register(); container.Register(); // MediatR container.Register(); container.RegisterInstance(t => container.Resolve(t)); container.Register(typeof(INotificationHandler<>), typeof(Program).Assembly); container.Register(typeof(IRequestHandler<>), typeof(Program).Assembly); container.Register(typeof(IRequestHandler<,>), typeof(Program).Assembly); // Configuration services container.Register(); container.Register(); container.Register(); // Application services container.Register(); container.Register(); container.Register(); IApplicationController controller = new ApplicationController(container); // UI classes controller.RegisterView() .RegisterView() .RegisterInstance(new ApplicationContext()); return controller; } } }