Linux: Fixed single instance option

This commit is contained in:
Souryo 2016-12-30 15:02:36 -05:00
parent 328136eb08
commit b0dafd311a

View File

@ -12,97 +12,15 @@ namespace Mesen.GUI
public String[] Args { get; set; }
}
#if __MonoCS__
public class SingleInstance : IDisposable
{
private bool _firstInstance = false;
private FileStream _fileStream;
public SingleInstance()
{
try {
_fileStream = System.IO.File.Open("mesen.lock", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_fileStream.Lock(0, 0);
_firstInstance = true;
} catch {
_firstInstance = false;
}
}
public bool FirstInstance { get { return _firstInstance; } }
public bool PassArgumentsToFirstInstance(string[] arguments)
{
try {
File.WriteAllText("mesen.arguments", string.Join(Environment.NewLine, arguments));
} catch { }
return true;
}
public void ListenForArgumentsFromSuccessiveInstances()
{
Task.Run(() => this.ListenForArguments());
}
private void ListenForArguments()
{
while(true) {
if(File.Exists("mesen.arguments")) {
try {
string[] arguments = File.ReadAllLines("mesen.arguments");
ThreadPool.QueueUserWorkItem(new WaitCallback(CallOnArgumentsReceived), arguments);
File.Delete("mesen.arguments");
} catch { }
}
System.Threading.Thread.Sleep(200);
}
}
private void CallOnArgumentsReceived(object state)
{
OnArgumentsReceived((string[])state);
}
public event EventHandler<ArgumentsReceivedEventArgs> ArgumentsReceived;
private void OnArgumentsReceived(string[] arguments)
{
if(ArgumentsReceived != null)
ArgumentsReceived(this, new ArgumentsReceivedEventArgs() { Args = arguments });
}
private bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if(!_disposed) {
if(_fileStream != null) {
_fileStream.Dispose();
}
_disposed = true;
}
}
~SingleInstance()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
#else
public class SingleInstance : IDisposable
{
/// <summary>
/// Taken from flawlesscode.com (website no longer available)
/// </summary>
private Mutex _mutex = null;
private Boolean _firstInstance = false;
private bool _firstInstance = false;
private Guid _identifier = Guid.Empty;
private FileStream _fileStream = null;
/// <summary>
/// Enforces single instance for an application.
@ -110,36 +28,54 @@ namespace Mesen.GUI
/// <param name="identifier">An identifier unique to this application.</param>
public SingleInstance()
{
this._identifier = new Guid("{A46606B7-2D1C-4CC5-A52F-43BCAF094AED}");
this._mutex = new Mutex(true, _identifier.ToString(), out _firstInstance);
if(Program.IsMono) {
try {
_fileStream = System.IO.File.Open("mesen.lock", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_fileStream.Lock(0, 0);
_firstInstance = true;
} catch {
_firstInstance = false;
}
} else {
this._identifier = new Guid("{A46606B7-2D1C-4CC5-A52F-43BCAF094AED}");
this._mutex = new Mutex(true, _identifier.ToString(), out _firstInstance);
}
}
/// <summary>
/// Indicates whether this is the first instance of this application.
/// </summary>
public Boolean FirstInstance { get { return _firstInstance; } }
public bool FirstInstance { get { return _firstInstance; } }
/// <summary>
/// Passes the given arguments to the first running instance of the application.
/// </summary>
/// <param name="arguments">The arguments to pass.</param>
/// <returns>Return true if the operation succeded, false otherwise.</returns>
public Boolean PassArgumentsToFirstInstance(String[] arguments)
public bool PassArgumentsToFirstInstance(string[] arguments)
{
try {
using(NamedPipeClientStream client = new NamedPipeClientStream(_identifier.ToString())) {
using(StreamWriter writer = new StreamWriter(client)) {
client.Connect(200);
if(Program.IsMono) {
try {
File.WriteAllText("mesen.arguments", string.Join(Environment.NewLine, arguments));
} catch { }
foreach(String argument in arguments) {
writer.WriteLine(argument);
return true;
} else {
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 true;
} catch { }
return false;
return false;
}
}
/// <summary>
@ -147,32 +83,44 @@ namespace Mesen.GUI
/// </summary>
public void ListenForArgumentsFromSuccessiveInstances()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ListenForArguments));
Task.Run(() => this.ListenForArguments());
}
/// <summary>
/// Listens for arguments on a named pipe.
/// </summary>
/// <param name="state">State object required by WaitCallback delegate.</param>
private void ListenForArguments(Object state)
private void ListenForArguments()
{
try {
using(NamedPipeServerStream server = new NamedPipeServerStream(_identifier.ToString())) {
using(StreamReader reader = new StreamReader(server)) {
server.WaitForConnection();
List<String> arguments = new List<String>();
while(server.IsConnected) {
arguments.Add(reader.ReadLine());
}
ThreadPool.QueueUserWorkItem(new WaitCallback(CallOnArgumentsReceived), arguments.ToArray());
if(Program.IsMono) {
while(true) {
if(File.Exists("mesen.arguments")) {
try {
string[] arguments = File.ReadAllLines("mesen.arguments");
ThreadPool.QueueUserWorkItem(new WaitCallback(CallOnArgumentsReceived), arguments);
File.Delete("mesen.arguments");
} catch { }
}
System.Threading.Thread.Sleep(200);
}
} else {
try {
using(NamedPipeServerStream server = new NamedPipeServerStream(_identifier.ToString())) {
using(StreamReader reader = new StreamReader(server)) {
server.WaitForConnection();
List<String> arguments = new List<String>();
while(server.IsConnected) {
arguments.Add(reader.ReadLine());
}
ThreadPool.QueueUserWorkItem(new WaitCallback(CallOnArgumentsReceived), arguments.ToArray());
}
}
} catch(IOException) {
//Pipe was broken
} finally {
ListenForArguments();
}
} catch(IOException) {
//Pipe was broken
} finally {
ListenForArguments(null);
}
}
@ -180,9 +128,9 @@ namespace Mesen.GUI
/// Calls the OnArgumentsReceived method casting the state Object to String[].
/// </summary>
/// <param name="state">The arguments to pass.</param>
private void CallOnArgumentsReceived(Object state)
private void CallOnArgumentsReceived(object state)
{
OnArgumentsReceived((String[])state);
OnArgumentsReceived((string[])state);
}
/// <summary>
@ -194,7 +142,7 @@ namespace Mesen.GUI
/// Fires the ArgumentsReceived event.
/// </summary>
/// <param name="arguments">The arguments to pass with the ArgumentsReceivedEventArgs.</param>
private void OnArgumentsReceived(String[] arguments)
private void OnArgumentsReceived(string[] arguments)
{
if(ArgumentsReceived != null)
ArgumentsReceived(this, new ArgumentsReceivedEventArgs() { Args = arguments });
@ -206,6 +154,10 @@ namespace Mesen.GUI
protected virtual void Dispose(bool disposing)
{
if(!_disposed) {
if(_fileStream != null) {
_fileStream.Dispose();
}
if(_mutex != null && _firstInstance) {
_mutex.ReleaseMutex();
_mutex = null;
@ -226,5 +178,4 @@ namespace Mesen.GUI
}
#endregion
}
#endif
}