禁止程序多开,程序单一实例实现
2013-05-06 13:06
99 查看
不少应用程序有单一实例的需求,也就是同时只能开启一个实例(一般也就是一个进程)。
实现的方式可能有判断进程名字,使用特殊文件等等,但是最靠谱的方式还是使用系统提供的 Mutex 工具。
Mutex是互斥体,命名的互斥体可以跨进程使用,所以可以用以实现程序单一实例这个需求。相关的例子网上应该不少,不过很多给出的例子中并没有注意到一些细节,这里就完整总结下。
命名Permalink
Mutex 需要一个名字,这个名字需要唯一,一般的方式是使用一个固定的 GUID 作为名字。
对于 .NET 应用,可以通过 Assembly 上的GuidAttribute来获取。默认情况下建立工程的时候 VS 就会生成一个 GUID 给 Assembly,这样无需自己再生成一个 GUID 来使用。
另外,为了调试方面,最好给 GUID 加一个便于人识别的前缀,一般就是程序的名字。这样使用一些查看系统对象的工具时,可以方便找到这个 Mutex。
判断Permalink
一般在程序启动的代码中进行判断,判断的方式是使用 Mutex 上的WaitOne方法。但是有两点需要注意:
程序异常退出,WaitOne 会抛出
如果程序使用了
返回
释放Permalink
在程序退出时需要释放 Mutex。
通知Permalink
有些场景下,如果应用已在运行,用户再启动应用时,需要将已在运行的应用显示给用户。如果应用已经有自己的进程间通讯方式,那就可以直接利用,如果没有,则可以使用 Windows 系统的消息广播。
P/Invoke 定义:
程序启动时注册消息:
判断程序已运行时广播消息:
处理消息循环,显示已运行的实例:
参考:http://sanity-free.org/143/csharp_dotnet_single_instance_application.html
实现的方式可能有判断进程名字,使用特殊文件等等,但是最靠谱的方式还是使用系统提供的 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方法。但是有两点需要注意:
程序异常退出,WaitOne 会抛出
AbandonedMutexException异常,需要处理。
如果程序使用了
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
相关文章推荐
- 程序单一实例实现 z
- Python实现程序的单一实例用法分析
- Python 实现程序的单一实例
- C#实现托盘程序并禁止多个应用实例运行的方法
- Python 实现程序的单一实例
- Python实现程序的单一实例用法分析
- android widget 开发实例 : 桌面便签程序的实现详解和源码 (下)
- 转:实例学习PHP程序对用户身份认证实现两种方法
- php实现的单一入口应用程序实例分析
- 关于C#禁止多个实例程序运行的详细解决
- 微信小程序 摇一摇抽奖简单实例实现代码
- wxpython实现程序最小到系统托盘的一个实例
- php实现有趣的人品测试程序实例
- JAVA程序启动单一实例妙招
- 使用 IBM 中间件实现 SaaS 解决方案,第 4 部分: 单一实例多租户应用程序中资源共享的设计模式
- 利用HttpModuler实现WEB程序同一时间只让一个用户实例登陆
- 告警程序实例(c#实现)
- 如何使.NET程序只运行单一实例
- QT中实现程序只运行一个实例--应用程序的单例化
- 如何使用进程名禁止程序运行两个实例