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

时间:2010-12-06 18:34:43

标签: c#

我在C#中有一个控制台应用程序,我想限制我的应用程序一次只运行一个实例。我如何在C#中实现这一目标?

6 个答案:

答案 0 :(得分:46)

我会使用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
     }
  }

答案 1 :(得分:32)

如果您决定使用Mutex用于此目的,您应该注意一些陷阱:

  • 如果要将应用程序限制为每台计算机一个实例(即每个登录用户不是一个),那么您需要使用前缀Global\开头的互斥锁名称。如果您不添加此前缀,操作系统将为每个用户创建一个不同的互斥锁实例。

  • 如果您在启用了UAC的Windows Vista或更高版本的计算机上运行,​​并且当前的应用程序实例有可能以管理员身份运行,那么下一个实例将无法检测到它,您将获得权限异常。为避免这种情况,您需要在创建Mutex时为其指定一组不同的权限。

答案 2 :(得分:18)

有很多方法,例如 -

  • 在开始之前枚举进程列表,如果进程名称已存在则拒绝启动。
  • 在启动时创建互斥锁并检查互斥锁是否已存在。
  • 通过单件类启动程序。

每个都在下面演示:

http://iridescence.no/post/CreatingaSingleInstanceApplicationinC.aspx
http://www.codeproject.com/KB/cs/restricting_instances.aspx
http://www.codeproject.com/KB/cs/singleinstance.aspx

每个都有其优点和缺点。但我相信创建互斥锁是最好的。

答案 3 :(得分:3)

添加这个答案,因为以前的那些在使用.net core1.1的linux(ubuntu 14.0.4已测试)上不起作用,因为这个问题在搜索结果中很高。 @ MusuNaji的解决方案的变化,如果它对你来说已经很明显了。

    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核心特定问题上:Single instance dotnetcore cli app on linux

答案 4 :(得分:2)

这是一个适合我的解决方案

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;
}

然后我在程序启动时检查此方法的输出。

答案 5 :(得分:0)

对我来说最直接的答案,如下所示,取自Madhur Ahuja发布的链接 (http://www.webskaper.no/wst/creatingasingleinstanceapplicationinc-aspx/) - 在这里转载(代码项目解决方案对我来说是隐藏的)。

重点是保持互斥锁直到过程完成(显然我猜)。

bool createdNew;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
    if (createdNew) {
         // process
    }
    else {
         // in my case, quietly exit
    }
}