From b71bfb85c8393e7888e8dc87671b9e7d6108b61a Mon Sep 17 00:00:00 2001 From: Lesueur Benjamin Date: Thu, 9 Dec 2021 13:07:16 +0100 Subject: [PATCH] replace SingleInstanceApplication by Mutex and PipeClient/PipeServer --- ControllerCommon/PipeClient.cs | 25 ++-- ControllerCommon/PipeMessage.cs | 20 +++ ControllerCommon/PipeServer.cs | 27 ++-- ControllerHelper/ControllerHelper.cs | 4 - ControllerHelper/Program.cs | 184 ++++++++++++--------------- 5 files changed, 132 insertions(+), 128 deletions(-) diff --git a/ControllerCommon/PipeClient.cs b/ControllerCommon/PipeClient.cs index 584d944c2..daa12b50b 100644 --- a/ControllerCommon/PipeClient.cs +++ b/ControllerCommon/PipeClient.cs @@ -12,6 +12,9 @@ public class PipeClient public readonly NamedPipeClient client; private readonly ILogger logger; + public event ConnectedEventHandler Connected; + public delegate void ConnectedEventHandler(Object sender); + public event DisconnectedEventHandler Disconnected; public delegate void DisconnectedEventHandler(Object sender); @@ -23,10 +26,8 @@ public class PipeClient public bool connected; - public PipeClient(string pipeName, ILogger logger) + public PipeClient(string pipeName) { - this.logger = logger; - m_queue = new ConcurrentQueue(); // monitors processes and settings @@ -41,9 +42,14 @@ public PipeClient(string pipeName, ILogger logger) client.Error += OnError; } + public PipeClient(string pipeName, ILogger logger) : this(pipeName) + { + this.logger = logger; + } + private void OnClientDisconnected(NamedPipeConnection connection) { - logger.LogInformation("Client {0} disconnected", connection.Id); + logger?.LogInformation("Client {0} disconnected", connection.Id); Disconnected?.Invoke(this); connected = false; @@ -55,7 +61,7 @@ public void Start() return; client.Start(); - logger.LogInformation($"Pipe Client has started"); + logger?.LogInformation($"Pipe Client has started"); } public void Stop() @@ -64,26 +70,27 @@ public void Stop() return; client.Stop(); - logger.LogInformation($"Pipe Client has stopped"); + logger?.LogInformation($"Pipe Client has stopped"); } private void OnServerMessage(NamedPipeConnection connection, PipeMessage message) { - logger.LogDebug("Client {0} opcode: {1} says: {2}", connection.Id, message.code, string.Join(" ", message.ToString())); + logger?.LogDebug("Client {0} opcode: {1} says: {2}", connection.Id, message.code, string.Join(" ", message.ToString())); ServerMessage?.Invoke(this, message); switch (message.code) { case PipeCode.SERVER_PING: connected = true; - logger.LogInformation("Client {0} is now connected!", connection.Id); + Connected?.Invoke(this); + logger?.LogInformation("Client {0} is now connected!", connection.Id); break; } } private void OnError(Exception exception) { - logger.LogError("PipClient failed. {0}", exception.Message); + logger?.LogError("PipClient failed. {0}", exception.Message); } public void SendMessage(PipeMessage message) diff --git a/ControllerCommon/PipeMessage.cs b/ControllerCommon/PipeMessage.cs index 30d95e460..cdf2f23a2 100644 --- a/ControllerCommon/PipeMessage.cs +++ b/ControllerCommon/PipeMessage.cs @@ -117,5 +117,25 @@ public PipeClientHidder() code = PipeCode.CLIENT_HIDDER; } } + + [Serializable] + public class PipeConsoleArgs : PipeMessage + { + public string[] args; + + public PipeConsoleArgs() + { + code = PipeCode.CLIENT_CONSOLE; + } + } + + [Serializable] + public class PipeServerShutdown : PipeMessage + { + public PipeServerShutdown() + { + code = PipeCode.SERVER_SHUTDOWN; + } + } #endregion } diff --git a/ControllerCommon/PipeServer.cs b/ControllerCommon/PipeServer.cs index 174c4d20f..34085d1e0 100644 --- a/ControllerCommon/PipeServer.cs +++ b/ControllerCommon/PipeServer.cs @@ -36,6 +36,12 @@ public enum PipeCode CLIENT_SCREEN = 11, // Sent to server to update screen details // args: width, height + + CLIENT_CONSOLE = 12, // Sent from client to client to pass parameters + // args: string[] parameters + + SERVER_SHUTDOWN = 13, // Sent to client to halt process + // args: ... } public class PipeServer @@ -57,10 +63,8 @@ public class PipeServer public bool connected; - public PipeServer(string pipeName, ILogger logger) + public PipeServer(string pipeName) { - this.logger = logger; - m_queue = new ConcurrentQueue(); // monitors processes and settings @@ -79,13 +83,18 @@ public PipeServer(string pipeName, ILogger logger) server.Error += OnError; } + public PipeServer(string pipeName, ILogger logger) : this(pipeName) + { + this.logger = logger; + } + public void Start() { if (server == null) return; server.Start(); - logger.LogInformation($"Pipe Server has started"); + logger?.LogInformation($"Pipe Server has started"); } public void Stop() @@ -94,12 +103,12 @@ public void Stop() return; server = null; - logger.LogInformation($"Pipe Server has stopped"); + logger?.LogInformation($"Pipe Server has stopped"); } private void OnClientConnected(NamedPipeConnection connection) { - logger.LogInformation("Client {0} is now connected!", connection.Id); + logger?.LogInformation("Client {0} is now connected!", connection.Id); Connected?.Invoke(this); connected = true; @@ -110,7 +119,7 @@ private void OnClientConnected(NamedPipeConnection con private void OnClientDisconnected(NamedPipeConnection connection) { - logger.LogInformation("Client {0} disconnected", connection.Id); + logger?.LogInformation("Client {0} disconnected", connection.Id); Disconnected?.Invoke(this); connected = false; @@ -118,13 +127,13 @@ private void OnClientDisconnected(NamedPipeConnection private void OnClientMessage(NamedPipeConnection connection, PipeMessage message) { - logger.LogDebug("Client {0} opcode: {1} says: {2}", connection.Id, message.code, string.Join(" ", message.ToString())); + logger?.LogDebug("Client {0} opcode: {1} says: {2}", connection.Id, message.code, string.Join(" ", message.ToString())); ClientMessage?.Invoke(this, message); } private void OnError(Exception exception) { - logger.LogError("PipeServer failed. {0}", exception.Message); + logger?.LogError("PipeServer failed. {0}", exception.Message); } public void SendMessage(PipeMessage message) diff --git a/ControllerHelper/ControllerHelper.cs b/ControllerHelper/ControllerHelper.cs index ff9d1184f..ed197e741 100644 --- a/ControllerHelper/ControllerHelper.cs +++ b/ControllerHelper/ControllerHelper.cs @@ -56,10 +56,6 @@ public partial class ControllerHelper : Form private readonly ILogger logger; - public ControllerHelper() - { - } - public ControllerHelper(ILogger logger) { InitializeComponent(); diff --git a/ControllerHelper/Program.cs b/ControllerHelper/Program.cs index 8859edb55..5e76b9dbc 100644 --- a/ControllerHelper/Program.cs +++ b/ControllerHelper/Program.cs @@ -11,6 +11,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Threading; using System.Windows.Forms; using static ControllerHelper.Options; @@ -18,40 +19,13 @@ namespace ControllerHelper { static class Program { - #region imports - - private enum ShowWindowEnum - { - Hide = 0, - ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3, - Maximize = 3, ShowNormalNoActivate = 4, Show = 5, - Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8, - Restore = 9, ShowDefault = 10, ForceMinimized = 11 - }; - - private struct Windowplacement - { - public int length; - public int flags; - public int showCmd; - public System.Drawing.Point ptMinPosition; - public System.Drawing.Point ptMaxPosition; - public System.Drawing.Rectangle rcNormalPosition; - } - - [DllImport("user32.dll")] - public static extern IntPtr FindWindow(string className, string windowTitle); - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags); - [DllImport("user32.dll")] - private static extern int SetForegroundWindow(IntPtr hwnd); - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool GetWindowPlacement(IntPtr hWnd, ref Windowplacement lpwndpl); - #endregion - static ControllerHelper MainForm; + static PipeClient PipeClient; + static PipeServer PipeServer; + static string[] args; + + static Mutex mutex = new Mutex(true, "1DDFB948-19F1-417C-903D-BE05335DB8A4"); + static AutoResetEvent autoEvent = new AutoResetEvent(false); /// /// The main entry point for the application. @@ -59,55 +33,88 @@ private struct Windowplacement [STAThread] static void Main(params string[] Arguments) { - string proc = Process.GetCurrentProcess().ProcessName; - Process[] processes = Process.GetProcessesByName(proc); - - if (processes.Length > 1 && Arguments.Length == 0) - { - // an instance of helper is already running and no arguments were given - BringWindowToFront(proc); - return; - } - else if (processes.Length > 1 && Arguments.Length != 0) + if (mutex.WaitOne(TimeSpan.Zero, true)) { - // an instance of helper is already running, pass arguments to it - MainForm = new ControllerHelper(); - SingleInstanceApplication.Run(MainForm, NewInstanceHandler); + try + { + } + finally + { + PipeServer = new PipeServer("ControllerHelper"); + PipeServer.ClientMessage += OnClientMessage; + PipeServer.Start(); + + Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); + + var configuration = new ConfigurationBuilder() + .AddJsonFile("helpersettings.json") + .Build(); + + var serilogLogger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .CreateLogger(); + + var microsoftLogger = new SerilogLoggerFactory(serilogLogger).CreateLogger("ControllerHelper"); + + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + MainForm = new ControllerHelper(microsoftLogger); + Application.Run(MainForm); + + mutex.ReleaseMutex(); + } } else { - // no instance of helper is running - Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); - - var configuration = new ConfigurationBuilder() - .AddJsonFile("helpersettings.json") - .Build(); - - var serilogLogger = new LoggerConfiguration() - .ReadFrom.Configuration(configuration) - .CreateLogger(); + args = Arguments; + + PipeClient = new PipeClient("ControllerHelper"); + PipeClient.Connected += OnServerConnected; + PipeClient.ServerMessage += OnServerMessage; + PipeClient.Start(); + + // Wait for work method to signal and kill after 4seconds + autoEvent.WaitOne(4000); + } + } - var microsoftLogger = new SerilogLoggerFactory(serilogLogger).CreateLogger("ControllerHelper"); + private static void OnServerMessage(object sender, PipeMessage e) + { + switch (e.code) + { + case PipeCode.SERVER_SHUTDOWN: + autoEvent.Set(); + break; + } + } - Application.SetHighDpiMode(HighDpiMode.SystemAware); - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); + private static void OnClientMessage(object sender, PipeMessage e) + { + PipeConsoleArgs console = (PipeConsoleArgs)e; - MainForm = new ControllerHelper(microsoftLogger); - SingleInstanceApplication.Run(MainForm, NewInstanceHandler); + if (console.args.Length == 0) + { + MainForm.BeginInvoke((MethodInvoker)delegate () + { + MainForm.WindowState = FormWindowState.Normal; + }); + } + else + { + Parser.Default.ParseArguments(console.args).MapResult( + (ProfileOption opts) => RunProfile(opts), + errs => RunError(errs) + ); } + + PipeServer.SendMessage(new PipeServerShutdown()); } - public static void NewInstanceHandler(object sender, StartupNextInstanceEventArgs e) + private static void OnServerConnected(object sender) { - string[] args = new string[e.CommandLine.Count - 1]; - Array.Copy(e.CommandLine.ToArray(), 1, args, 0, e.CommandLine.Count - 1); - - Parser.Default.ParseArguments(args).MapResult( - (ProfileOption opts) => RunProfile(opts), - errs => RunError(errs) - ); - e.BringToForeground = false; + PipeClient.SendMessage(new PipeConsoleArgs() { args = args }); } private static bool RunError(IEnumerable errs) @@ -143,40 +150,5 @@ private static bool RunProfile(ProfileOption opts) MainForm.ProfileManager.SerializeProfile(profile); return true; } - - public class SingleInstanceApplication : WindowsFormsApplicationBase - { - private SingleInstanceApplication() - { - base.IsSingleInstance = true; - } - - public static void Run(Form f, StartupNextInstanceEventHandler startupHandler) - { - SingleInstanceApplication app = new SingleInstanceApplication(); - app.MainForm = f; - app.StartupNextInstance += startupHandler; - app.Run(Environment.GetCommandLineArgs()); - } - } - - private static void BringWindowToFront(string name) - { - IntPtr wdwIntPtr = FindWindow(null, name); - - //get the hWnd of the process - Windowplacement placement = new Windowplacement(); - GetWindowPlacement(wdwIntPtr, ref placement); - - // Check if window is minimized - if (placement.showCmd == 2) - { - //the window is hidden so we restore it - ShowWindow(wdwIntPtr, ShowWindowEnum.Restore); - } - - //set user's focus to the window - SetForegroundWindow(wdwIntPtr); - } } }