只允许一个应用程序实例

 

最近在研究这个问题,想限制只有一个应用程序实例。不过这个问题已经是老生常谈的话题了,去网上搜索一下,一大堆的结果。通常的做法都是通过 Mutex 或者 FindWindow 来进行,可是并不符合本文的需求。因为我要达到的要求是:

1、首先肯定只允许一个应用程序实例运行;

2、当第二个实例运行时,激活第一个实例,并可将相应的参数(比如需要处理的新文件名)传递给第一个实例;

3、鉴于 FrameWnd 和 Dialog 基类的处理方式(Dialog 的 DoModal() 会导致 padding)不一样,要求可以通用;

4、代码简洁高效,不想把这一个功能分散到 App 类和 Frame/Dialog 类,一个地方能搞定的就一个地方搞定。

 

常规的做法,比如 Mutex,可以达到第一点,但是无法实现第 2 点;用 FindWindow 的做法,完全没有考虑到窗口标题的变化(比如单文档或多文档,程序标题常变化),根本不可能做到通用;好不容易在 CodeProject 上找到一篇很有价值的文章,PJ Naughter 写的,整体是很不错,不过可惜的是没有达到第 4 点,完成这一个功能还要在好几个类里面加代码,似乎有些麻烦。

...

难道就没有合适的办法了吗?

 

有的!答案是肯定的。

其实 PJ Naughter 为我们指出了一条明路:在应用程序实例间共享数据,首选内存映射文件 MMF (Memory Mapped File),通过它建立一个指向虚拟的内存文件句柄,以便确定确定只有一个应用程序实例。

那激活第一个实例怎么办?我们只有在一个地方(InitInstance)有代码,此时在 Frame/Dialog 完全还没建立,所以要激活第一个实例,也就没有第一个实例的窗口句柄了,怎么办?

好办,咱不是还有 EnumWindows、EnumThreadWindows 么?枚举呗,在我们第二个实例运行的时候,第一个实例的主窗口句柄是肯定有了,并且有效(IsWindow),所以只要枚举获取了主窗口的句柄,剩下的激活主窗口、关闭第一个实例啥的都好办(这也是我转载上一篇文章的原因)。

还有一个大的问题,就是传参。前面说了,如果第 2 个实例启动的时候带命令行,比如文件、打印等,那我们需要把这个参数传递给第一个应用程序实例。说白了就是进程间通信的事情,文件?注册表?都不合适,我觉得,只有消息,还是 Windows 的消息机制是正统。但是常规的消息是不行的,不是空指针就是乱码,只有 WM_SETTEXT、WM_COPYDATA 最合适,而这两个中,后者还支持可以传递结构,所以选定后者作为参数传递的消息载体。

 

最终完成之后的调用代码:

 

 

hoho,是不是简洁多了? :)

 

 

 

参考文献:

CSingleInstance - Single Instance Apps

http://www.codeproject.com/KB/cpp/csingleinst.aspx

 

Avoiding Multiple Instances of an Application

http://www.codeproject.com/KB/cpp/avoidmultinstance.aspx

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值