using System; using System.IO; using System.IO.Pipes; using System.Threading; using System.Collections.Generic; namespace Mesen.GUI { public class ArgumentsReceivedEventArgs : EventArgs { public String[] Args { get; set; } } public class SingleInstance : IDisposable { /// /// Taken from flawlesscode.com (website no longer available) /// private Mutex _mutex = null; private Boolean _firstInstance = false; private Guid _identifier = Guid.Empty; /// /// Enforces single instance for an application. /// /// An identifier unique to this application. public SingleInstance(Guid identifier) { this._identifier = identifier; this._mutex = new Mutex(true, identifier.ToString(), out _firstInstance); } /// /// Indicates whether this is the first instance of this application. /// public Boolean FirstInstance { get { return _firstInstance; } } /// /// Passes the given arguments to the first running instance of the application. /// /// The arguments to pass. /// Return true if the operation succeded, false otherwise. public Boolean PassArgumentsToFirstInstance(String[] arguments) { try { using(NamedPipeClientStream client = new NamedPipeClientStream(_identifier.ToString())) { using(StreamWriter writer = new StreamWriter(client)) { client.Connect(200); foreach(String argument in arguments) { writer.WriteLine(argument); } } } return true; } catch { } return false; } /// /// Listens for arguments being passed from successive instances of the applicaiton. /// public void ListenForArgumentsFromSuccessiveInstances() { ThreadPool.QueueUserWorkItem(new WaitCallback(ListenForArguments)); } /// /// Listens for arguments on a named pipe. /// /// State object required by WaitCallback delegate. private void ListenForArguments(Object state) { try { using(NamedPipeServerStream server = new NamedPipeServerStream(_identifier.ToString())) { using(StreamReader reader = new StreamReader(server)) { server.WaitForConnection(); List arguments = new List(); while(server.IsConnected) { arguments.Add(reader.ReadLine()); } ThreadPool.QueueUserWorkItem(new WaitCallback(CallOnArgumentsReceived), arguments.ToArray()); } } } catch(IOException) { //Pipe was broken } finally { ListenForArguments(null); } } /// /// Calls the OnArgumentsReceived method casting the state Object to String[]. /// /// The arguments to pass. private void CallOnArgumentsReceived(Object state) { OnArgumentsReceived((String[])state); } /// /// Event raised when arguments are received from successive instances. /// public event EventHandler ArgumentsReceived; /// /// Fires the ArgumentsReceived event. /// /// The arguments to pass with the ArgumentsReceivedEventArgs. private void OnArgumentsReceived(String[] arguments) { if(ArgumentsReceived != null) ArgumentsReceived(this, new ArgumentsReceivedEventArgs() { Args = arguments }); } #region IDisposable private Boolean _disposed = false; protected virtual void Dispose(bool disposing) { if(!_disposed) { if(_mutex != null && _firstInstance) { _mutex.ReleaseMutex(); _mutex = null; } _disposed = true; } } ~SingleInstance() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } }