Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
public class ApplicationMutex : IDisposable
{
private static readonly ILog logger = LogManager.GetLogger(typeof(ApplicationMutex));
// This needs to have the prefix "Global\" in order to be system-wide
public const string MutexName = @"Global\MyApplicationNameMutex";
private Mutex mutex;
private bool acquired;
public bool TryAcquire()
{
if (this.acquired)
throw new InvalidOperationException("Mutex has already been acquired by this process");
try
{
// I think either of these calls can throw, so put them both inside the try
if (this.mutex == null)
{
this.mutex = new Mutex(initiallyOwned: false, name: MutexName);
}
this.acquired = this.mutex.WaitOne(0, false);
logger.Debug($"Queried mutex. Acquired: {this.acquired}");
}
catch (WaitHandleCannotBeOpenedException e)
{
logger.Warn($"Could not query mutex: {e.Message}");
// There's probably a win32 object with the same name but a different type.
// The only semi-sensible thing we can do is count this as "could not acquire"
}
catch (UnauthorizedAccessException)
{
logger.Info("Unable to query mutex: UnauthorizedAccessException");
// We might not have permission to even read stuff about the mutex, in which
// case someone else has acquired it.
}
catch (Exception e)
{
logger.Error("Unexpected exception when acquiring mutex", e);
}
return this.acquired;
}
public void Dispose()
{
try
{
if (this.acquired)
{
this.mutex.ReleaseMutex();
this.acquired = false;
}
this.mutex?.Close();
}
catch (Exception)
{
// not much we can do at this point. But, when process finishes exiting, the mutex will
// be closed by the OS anyway.
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment