How to restrict a program to a single instance
I have a console application in C# and I want to restrict my application to run only one instance at开发者_JAVA技巧 a time. How do I achieve this in C#?
I would use a Mutex
static void Main()
{
string mutex_id = "MY_APP";
using (Mutex mutex = new Mutex(false, mutex_id))
{
if (!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance Already Running!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
// Do stuff
}
}
If you decide to use a Mutex for that purpose, there are some pitfalls you should be aware of:
If you want to limit the application to one instance per machine (i.e. not one per logged on user), then you will need your mutex name to start with the prefix
Global\
. If you don't add this prefix, a different instance of the mutex will be created by the OS for each user.If you are running on a Windows Vista or later machine with UAC enabled, and by some chance the current application instance is running as an admin, then the next instances will fail detecting it, and you will get permission exceptions. To avoid this you need to specify a different set of permissions for the Mutex when creating it.
There are many ways, such as -
- Enumerating list of processes before starting and denying the startup if process name already exists.
- Creating a mutex on startup and checking if mutex already exists.
- Launching a program through a singleton class.
Each is demoed below:
http://iridescence.no/post/CreatingaSingleInstanceApplicationinC.aspx
http://www.codeproject.com/KB/cs/restricting_instances.aspx
http://www.codeproject.com/KB/cs/singleinstance.aspx
Each has its pros and cons. But I believe the creating mutex is the best one to go for.
Adding this answer because previous ones did not work on linux(ubuntu 14.0.4 tested) with .net core1.1 and because this question is high up in search results. Variation of @MusuNaji's solution, if it wasn't already obvious to you.
private static bool AlreadyRunning()
{
Process[] processes = Process.GetProcesses();
Process currentProc = Process.GetCurrentProcess();
logger.LogDebug("Current proccess: {0}", currentProc.ProcessName);
foreach (Process process in processes)
{
if (currentProc.ProcessName == process.ProcessName && currentProc.Id != process.Id)
{
logger.LogInformation("Another instance of this process is already running: {pid}", process.Id);
return true;
}
}
return false;
}
This answer is also posted on my dotnet core specific question here: Single instance dotnetcore cli app on linux
here is a solution that worked for me
private static bool AlreadyRunning()
{
Process[] processes = Process.GetProcesses();
Process currentProc = Process.GetCurrentProcess();
foreach (Process process in processes)
{
try
{
if (process.Modules[0].FileName == System.Reflection.Assembly.GetExecutingAssembly().Location
&& currentProc.Id != process.Id)
return true;
}
catch (Exception)
{
}
}
return false;
}
I then check the output of this method at program startup.
The most straight-forward answer for me, shown below, taken from Madhur Ahuja posted link (http://www.webskaper.no/wst/creatingasingleinstanceapplicationinc-aspx/) - reproduced here (the code project solutions were hidden from me).
The important point was to hold the mutex until the process is complete (obvious I guess).
bool createdNew;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
if (createdNew) {
// process
}
else {
// in my case, quietly exit
}
}
精彩评论