Recently I needed to assure that a process could not be started for a second time on the same machine. I had done this before with a mutex but rather than rummaging through old code on my own personal machine, I did the expedient thing and found this question on Stack Overflow.
I liked the answer as many others did and after a few minutes of tweaking came up with this useful adaptation. I share it here in part to help others but mostly to create a permanent “note to self” as this will surely come up again in the future.
private static void Main(string[] args)
{
// assure only one instance running
RunExclusively(() =>
{
// do your exclusive stuff
});
}
static void RunExclusively(Action action)
{
// global mutex to prevent multiple instances from being started
// get application GUID as defined in AssemblyInfo.cs
string appGuid = ((GuidAttribute)
Assembly.GetExecutingAssembly()
.GetCustomAttributes(typeof(GuidAttribute), false)
.GetValue(0))
.Value;
// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", appGuid);
using (var mutex = new Mutex(false, mutexId))
{
// set security settings for mutex - allow everyone
var allowEveryoneRule = new MutexAccessRule(
new SecurityIdentifier(WellKnownSidType.WorldSid, null),
MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
mutex.SetAccessControl(securitySettings);
var hasHandle = false;
try
{
try
{
// wait to acquire for up to five seconds
if (!mutex.WaitOne(5000, exitContext: false))
{
throw new TimeoutException("Timeout waiting for exclusive access");
}
}
catch (AbandonedMutexException)
{
// mutex abandoned in another process
// it will still get acquired
hasHandle = true;
}
action(); //execute work
}
finally
{
if (hasHandle) mutex.ReleaseMutex();
}
}
}
If you know of a better way or see any flaws in this one, please do share.