如何确定我的应用程序的先前实例是否正在运行?

Jos*_*lio 25 .net c#

我在C#中有一个控制台应用程序,我在其中运行各种神秘的自动化任务.我很清楚这应该是一个Windows服务,因为它需要连续运行,但我现在不想这样做.(所以,不要建议作为答案).

与此同时,我需要一些示例C#代码,这将允许我确定是否已经运行了应用程序的实例.

在旧的VB6.0天,我会用的 App.PrevInstance()

我希望能够在我的Main方法中执行此操作:

static void Main()
{
  if(!MyApp.IsAlreadyRunning())
  {
    while(true)
    {
      RockAndRollAllNightAndPartyEveryDay();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Rom*_*kov 24

为此目的使用互斥锁的正确方法:

private static Mutex mutex;

static void Main()
{
    // STEP 1: Create and/or check mutex existence in a race-free way
    bool created;
    mutex = new Mutex(false, "YourAppName-{add-your-random-chars}", out created);
    if (!created)
    {
        MessageBox.Show("Another instance of this application is already running");
        return;
    }

    // STEP 2: Run whatever the app needs to do
    Application.Run(new Form1());

    // No need to release the mutex because it was never acquired
}
Run Code Online (Sandbox Code Playgroud)

以上内容不适用于检测同一台计算机上的多个用户是否在不同的用户帐户下运行该应用程序.类似的情况是一个过程可以运行两个下服务主机独立的.要使这些工作,请按如下方式创建互斥锁:

        var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
        var mutexsecurity = new MutexSecurity();
        mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow));
        mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.ChangePermissions, AccessControlType.Deny));
        mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.Delete, AccessControlType.Deny));
        _mutex = new Mutex(false, "Global\\YourAppName-{add-your-random-chars}", out created, mutexsecurity);
Run Code Online (Sandbox Code Playgroud)

这里有两个不同之处 - 首先,需要使用允许其他用户帐户打开/获取它的安全权限来创建互斥锁.其次,在服务主机下运行的服务的情况下,名称必须以"Global"为前缀(不确定在同一台机器上本地运行的其他用户).


Ian*_*Ian 17

Jeroen已经回答了这个问题,但到目前为止最好的方法是使用Mutex ...而不是使用Process.这是一个更全面的代码答案.

Mutex mutex;

try
{
   mutex = Mutex.OpenExisting("SINGLEINSTANCE");
   if (mutex!= null)
   {
      Console.WriteLine("Error : Only 1 instance of this application can run at a time");
      Application.Exit();
   }
}
catch (WaitHandleCannotBeOpenedException ex)
{
   mutex  = new Mutex(true, "SINGLEINSTANCE");
}
Run Code Online (Sandbox Code Playgroud)

另外请记住,您需要在某种Try {} Finally {}块中运行您的应用程序.否则,如果您在没有释放互斥锁的情况下发生应用程序崩溃,那么您可能无法在以后再次重新启动它.

  • -1:获取互斥锁时存在竞争条件; 看到我的另类答案.另外,提到"SINGLEINSTANCE"应该是应用程序的独特之处是必须的! (4认同)
  • @romkyns:你可能是对的.然而,我发布的解决方案几乎与.NET Foundation书中的解决方案完全相同,因此得到了微软的认可......可能也希望向他们的作者投诉. (2认同)