如何将程序限制为单个实例

我在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应用程序