zoukankan      html  css  js  c++  java
  • 禁止程序多开,程序单一实例实现

    不少应用程序有单一实例的需求,也就是同时只能开启一个实例(一般也就是一个进程)。

    实现的方式可能有判断进程名字,使用特殊文件等等,但是最靠谱的方式还是使用系统提供的 Mutex 工具。

    Mutex是互斥体,命名的互斥体可以跨进程使用,所以可以用以实现程序单一实例这个需求。相关的例子网上应该不少,不过很多给出的例子中并没有注意到一些细节,这里就完整总结下。

    命名Permalink

    Mutex 需要一个名字,这个名字需要唯一,一般的方式是使用一个固定的 GUID 作为名字。

    对于 .NET 应用,可以通过 Assembly 上的GuidAttribute来获取。默认情况下建立工程的时候 VS 就会生成一个 GUID 给 Assembly,这样无需自己再生成一个 GUID 来使用。

    另外,为了调试方面,最好给 GUID 加一个便于人识别的前缀,一般就是程序的名字。这样使用一些查看系统对象的工具时,可以方便找到这个 Mutex。

    var guidAttr = (GuidAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(),typeof(GuidAttribute));
    var key = string.Format("MyApp-}", guidAttr.Value);
    _mutex = new Mutex(true, key);


    判断Permalink

    一般在程序启动的代码中进行判断,判断的方式是使用 Mutex 上的WaitOne方法。但是有两点需要注意:

    1. 程序异常退出,WaitOne 会抛出AbandonedMutexException异常,需要处理。
    2. 如果程序使用了Application.Restart来重新启动,就需要 WaitOne 等待更长的时间。这是因为Application.Restart会在程序退出前启动新程序实例,需要等待原程序完全退出释放 Mutex。
    try
    {
        return _mutex.WaitOne(TimeSpan.FromSeconds(1), true);
    }
    catch (AbandonedMutexException ex)
    {
        if (ex.Mutex != null)
            ex.Mutex.ReleaseMutex();
        return true;
    }

    返回true则可以正常启动,否则程序已在运行。

    释放Permalink

    在程序退出时需要释放 Mutex。

    _mutex.ReleaseMutex();


    通知Permalink

    有些场景下,如果应用已在运行,用户再启动应用时,需要将已在运行的应用显示给用户。如果应用已经有自己的进程间通讯方式,那就可以直接利用,如果没有,则可以使用 Windows 系统的消息广播。

    P/Invoke 定义:

    public const int HWND_BROADCAST = 0xffff;
    
    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    public static extern bool SendMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);

    程序启动时注册消息:

    _showMeMessage = RegisterWindowMessage(key);

    判断程序已运行时广播消息:

    PostMessage((IntPtr)NativeMethods.HWND_BROADCAST,_showMeMessage,IntPtr.Zero,IntPtr.Zero);

    处理消息循环,显示已运行的实例:

    protected override void WndProc(ref Message m)
     {
        if (m.Msg == _showMeMessage)
        {
          if (form.WindowState == FormWindowState.Minimized)
              form.WindowState = FormWindowState.Normal;
    
              if (!form.Visible)
                  form.Show();
    
              var top = form.TopMost;
              form.TopMost = true;
              form.TopMost = top;
        }
        base.WndProc(ref m);
    }

    参考:http://sanity-free.org/143/csharp_dotnet_single_instance_application.html

  • 相关阅读:
    Java进阶——线程安全和非线程安全
    Java进阶——线程与多线程
    Java进阶——反射
    SpringBoot——SpringBoot框架介绍
    亲逢APP项目知识点
    诗韵APP项目技术点
    Spring框架——WebService
    Spring框架——ORM
    Spring框架——JDBC
    Spring框架——Spring响应
  • 原文地址:https://www.cnblogs.com/MuNet/p/5563462.html
Copyright © 2011-2022 走看看