创建单实例应用程序的三种方法
2012-12-06 10:32
483 查看
背景
在编写windows桌面应用程序时,如果我们没有特别处理,我们是可以打开多个应用程序实例的。例如,我们在同一台机器上挂打开多个QQ程序,也可以打开多个浏览器窗口。但有些应用程序,却只运行单个实例运行,如Outlook,MSN等。那么如何实现单实例应用程序呢?下面介绍三种方法。方法一,扫描进程
这是最容易想到的方法,实现起来也比较简单。扫描进程的代码如下,假设应用程序名称为MySingleInstance.exe。Process[] processes = Process.GetProcessesByName("MySingleInstance"); // no ".exe" if (processes.Length > 1) { MessageBox.Show("Another instance is running."); return; }
简单几行代码就可以实现单例应用程序了,只是稍微有些不够友好,因为当试图打开第二个实例时会弹出一个不够友好的对话框“Another instance is running.”,但如果我们把这行代码去掉后,又缺少了用户的交互。因此我们可以安装MSN或OUTLOOK的方式--激活正在运行的实例。
这需要调用WINDOWS API,如下代码:
Process[] processes = Process.GetProcessesByName("MySingleInstance"); if (processes.Length > 1) { IntPtr hwnd = processes[0].MainWindowHandle; // NOTE: ensure the first intance handle selected if (Process.GetCurrentProcess().MainWindowHandle == hwnd) { hwnd = processes[1].MainWindowHandle; } long style = GetWindowLong(hwnd, GWL_STYLE); if ((style & WS_MINIMIZE) == WS_MINIMIZE) { ShowWindow(hwnd, SW_SHOWNOACTIVATE); } SetForegroundWindow(hwnd); return; }
使用的WINDOWS API的声明,如下:
[DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hwnd); [DllImport("user32.dll")] private static extern long GetWindowLong(IntPtr hwnd, int nIndex); private const int SW_SHOWNOACTIVATE = 4; const int GWL_STYLE = -16; const long WS_MINIMIZE = 0x20000000L; 完整的代码键附近中Program1.cs
方法二,互斥量Mutex
如果你觉得扫描进程比较“笨拙”的话,那么有一个稍微专业一点的做法,使用互斥量Mutex。如果有多线程开发经验的,都应该使用过Mutex,该类比较可以实现线程的同步,而且是可以对其命名,并且是跨进程的。Mutex的构造函数签名:Mutex(bool initiallyOwned, string name, out bool createdNew),其中createdNew表示十分已经存在相同名称的Mutex,如果存在createdNew为false,没有则为true。利用该值可以判断应用程序的实例是否已经被创建。但在createdNew为false的情况时,还是需要方法一,来激活已创建的实例窗口。其实是有Mutex没有减少创建单实例的复杂度,反而更复杂了,而且创建的Mutex对象也不再使用,创建该对象也比较耗资源,该方法一般不会采用。方法三,Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
当然我们有更加简单,更加专业的方法--使用Microsoft提供的接口--WindowsFormsApplicationBase。Ms提供了Application基类,并且提供了IsSingleInstance的属性,该类位于命名空间Microsoft.VisualBasic.ApplicationServices下,必须添加Microsoft.VisualBasic.dll的引用。我们要做的就是实现该类,并且设置属性IsSingleInstance=True。实现代码:internal sealed class MySingleInstanceApplication : WindowsFormsApplicationBase { public MySingleInstanceApplication() { base.IsSingleInstance = true; base.EnableVisualStyles = true; } protected override void OnCreateMainForm() { this.MainForm = new Form1(); } }
该类的使用,同Application类基本相同,并且看上去更加简洁。
[STAThread] static void Main(string[] args) { MySingleInstanceApplication app = new MySingleInstanceApplication(); app.Run(args); }运行效果同方法一,二相同,关键是代码更简洁,面向对象。完整代码见Program3.cs
相关文章推荐
- [转]创建单实例应用程序的三种方法
- java创建对象实例的三种方法
- SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论 SignalR 简单示例 通过三个DEMO学会SignalR的三种实现方式 SignalR推送框架两个项目永久连接通讯使用 SignalR 集线器简单实例2 用SignalR创建实时永久长连接异步网络应用程序
- Spring创建Bean实例的三种方法
- 写出三种创建类的实例的方法
- 动态创建窗体实例的三种方法
- Java创建对象实例的三种方法
- JS创建事件的三种方法(实例代码)
- 实现单实例应用程序的三种方法
- 创建代理类实例的三种方法
- JS创建事件的三种方法(实例代码)
- spring创建bean的三种方式-通过构造器,通过静态工厂方法,通过实例工厂方法
- Java创建对象实例的三种方法
- 创建Bean的三种方式 在大多数情况下,Spring容器直接通过new关键字调用构造器来创建Bean实例,而class属性指定Bean实例的实现类,但这不是实例化Bean的唯一方法。实际上,Sprin
- JavaScript 三种创建对象的方法
- Spring使用实例工厂方法创建Bean(一)
- 获得对象实例的三种方法
- Java如何根据类名和方法名创建类的实例,并调用对应方法?
- cocos2dx中创建动画的三种方法
- java中创建线程三种方法及对比