如何将程序限制为单个实例
我在C#中有一个控制台应用程序,我想限制我的应用程序一次只运行一个实例。 我如何在C#中实现这一点?
我会使用互斥
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 } }
如果您决定使用互斥锁来实现这个目的,那么您应该注意一些陷阱:
-
如果你想限制应用程序每台机器一个实例(即不是每个login用户一个),那么你将需要你的互斥体名称开始前缀
Global\
。 如果不添加这个前缀,操作系统将为每个用户创build一个不同的互斥量实例。 -
如果您在启用了UAC的Win7 / Vista计算机上运行,并且当前应用程序实例正在以pipe理员身份运行,则下一个实例将无法检测到它,您将获得权限例外。 为了避免这种情况,您需要在创buildMutex时为其指定一组不同的权限。
有很多方法,比如 –
- 在启动之前枚举进程列表,如果进程名已经存在,则拒绝启动。
- 在启动时创build一个互斥量,并检查互斥量是否已经存在。
- 通过单身课程启动一个程序。
每个演示如下:
http://iridescence.no/post/CreatingaSingleInstanceApplicationinC.aspx
http://www.codeproject.com/KB/cs/restricting_instances.aspx
http://www.codeproject.com/KB/cs/singleinstance.aspx
各有利弊。 但是我相信创build互斥体是最好的select。
这是一个为我工作的解决scheme
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; }
然后在程序启动时检查这个方法的输出。
添加这个答案是因为之前的那些在.net core1.1下的linux(ubuntu 14.0.4testing版)上不工作,并且因为这个问题在search结果中很高。 @ MusuNaji的解决scheme的变化,如果它不是已经很明显。
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; }
这个答案也发布在我的dotnet核心的具体问题在这里: Linux上的单实例dotnetcore cli应用程序