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
}
}