繁体   English   中英

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

[英]How to restrict a program to a single instance

我有一个 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
     }
  }

如果您决定为此目的使用互斥锁,则您应该注意一些陷阱:

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

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

方法很多,比如——

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

每个演示如下:

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

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

添加此答案是因为以前的答案在 .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 core 特定问题上: Linux 上的单实例 dotnetcore cli 应用程序

这是一个对我有用的解决方案

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

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

对我来说最直接的答案,如下所示,取自 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
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM