如何阻止给 一个程序 开启多个实例 ?

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何阻止给 一个程序 开启多个实例 ?相关的知识,希望对你有一定的参考价值。

咨询区

  • C. Dragon 76

在 .NET 中是否有比较好的方法可以阻止一个 application 被同时开启了多个实例?如果没有好的办法,那么只能退其次,给每个 application 配一些操作规范。

回答区

  • ImJustPondering

我总结有两种解法。

  1. 使用 Meutx。

[STAThread]
static void Main() 
{
   using(Mutex mutex = new Mutex(false, "Global\\\\" + appGuid))
   {
      if(!mutex.WaitOne(0, false))
      {
         MessageBox.Show("Instance already running");
         return;
      }

      Application.Run(new Form1());
   }
}

private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";

关于 Mutex 更多资料,可参考:http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx

  1. 使用 Process

可以迭代进程列表,判断是否已经存在该进程名即可,参考如下代码:

using System.Diagnostics;
....
[STAThread]
static void Main()
{
...
        int procCount = 0;
        foreach (Process pp in Process.GetProcesses())
        {
            try
            {
                if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0)
                {
                    procCount++;                        
                    if(procCount > 1) {
                       Application.Exit();
                       return;
                    }
                }
            }
            catch { }
        }
        Application.Run(new Form1());
}
  • Tono Nam

其实可以仿 linux 上生成进程文件的方式,所以要做的就是在程序启动后,在某一个文件中写入一个默认的 uniqueid 值,参考如下代码:

public static void PreventMultipleInstance(string applicationId)
    {
        // Under Windows this is:
        //      C:\\Users\\SomeUser\\AppData\\Local\\Temp\\ 
        // Linux this is:
        //      /tmp/
        var temporaryDirectory = Path.GetTempPath();

        // Application ID (Make sure this guid is different accross your different applications!
        var applicationGuid = applicationId + ".process-lock";

        // file that will serve as our lock
        var fileFulePath = Path.Combine(temporaryDirectory, applicationGuid);

        try
        {
            // Prevents other processes from reading from or writing to this file
            var _InstanceLock = new FileStream(fileFulePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
            _InstanceLock.Lock(0, 0);
            MonoApp.Logger.LogToDisk(LogType.Notification, "04ZH-EQP0", "Aquired Lock", fileFulePath);

            // todo investigate why we need a reference to file stream. Without this GC releases the lock!
            System.Timers.Timer t = new System.Timers.Timer()
            {
                Interval = 500000,
                Enabled = true,
            };
            t.Elapsed += (a, b) =>
            {
                try
                {
                    _InstanceLock.Lock(0, 0);
                }
                catch
                {
                    MonoApp.Logger.Log(LogType.Error, "AOI7-QMCT", "Unable to lock file");
                }
            };
            t.Start();

        }
        catch
        {
            // Terminate application because another instance with this ID is running
            Environment.Exit(102534); 
        }
    }

点评区

这个需求本质上和防重复登录时一样的,大概三种吧:

  1. 机器内作用域:

Metux,Process 是一个好办法。

  1. 跨机器或局域网作用域:

生成 PID 文件是一个好办法。

  1. 局域网,广域网:

可用 redis,zookeeper 之类的全局锁机制。

以上是关于如何阻止给 一个程序 开启多个实例 ?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Mac 上启动多个 MonoDevelop 实例?

Android阻止恢复活动

Android 片段问题的多个实例

如何阻止片段一直弹出到根片段? [导航组件]

Android:保持屏幕开启[重复]

web前端开发JQuery常用实例代码片段(50个)