单实例应用程序的实现

在软件开发中,有时需要确保同一时间只有一个应用程序实例在运行。这可以通过实现单实例应用程序来实现。本文将介绍如何使用命名互斥体、线程休眠、内存映射文件等技术来实现单实例应用程序。

单实例应用程序的特点

单实例应用程序的一个关键特点是,它将新的命令行参数传递给现有的应用程序实例。这种方法不需要寻找或定位窗口,并且实例之间的CPU开销几乎为零。要查看这个示例的实际效果,只需使用不同的命令行参数运行多个实例,应该能看到命令行参数被传递给初始实例。

在同事询问如何实现单实例应用程序后编写了这个示例。第一反应是使用“命名互斥体”。花了一些时间查看代码项目和以下文章:

  • CSingleInstance - Single Instance Apps By PJ Naughter
  • Single Instance Checker By bigZidane

这两篇文章都很好,值得称赞,但它们都没有解决传递命令行参数的问题。目标是展示以下内容:

  • 使用休眠线程来处理激活,而不是使用post/send消息。
  • 抽象类,使用“pimple”方法,接口和实现类。
  • 使用内存映射文件在实例之间共享数据。
  • 低用户足迹,实例化一个对象并调用create;用户不需要做更多。
  • 允许命令行传递,将新实例的命令行发送到旧实例。

使用代码

使用CSingleInstance类非常简单,只需将其作为CWinApp类的第二个父类添加即可。

// singleton.h class CSingletonApp : public CWinApp, public CSingleInstance { ... };

接下来,在CWinApp::InitInstance内部的第一个语句调用CSingleInstance::Create,创建参数必须提供一个唯一的字符串。可以提供"MyCompany_MyApplication",但这样做总是有别人使用相同字符串的风险,所以更喜欢使用GUID。

可以通过在命令提示符下运行"guidgen"来生成GUID;它是MSVC的一部分,使用注册表格式。可以使用Microsoft定义的任何前缀,"Global\"或"Local\",必须了解应用程序的目标环境,因为"命名对象"在XP、NT等系统下的行为不同。

有关更多信息,建议阅读以下内容:

  • Kernel Object Name Spaces
  • Creating the single instance object.

示例代码

// singleton.cpp BOOL CSingletonApp::InitInstance() { // 在这里使用GUID,以确保字符串是100%唯一的 if (CSingleInstance::Create(_T("E435FC13-82C1-4f80-97C5-006FF4A4Exxx")) == FALSE) return FALSE; ... }

以下是可选的,允许处理唤醒或激活消息,应该通过派生一个类从CSingleInstance,然后添加一个虚拟方法WakeUp来实现。

// singleton.h class CSingletonApp : public CWinApp, public CSingleInstance { public: virtual void WakeUp(LPCTSTR aCommandLine) const; }; // singleton.cpp void CSingletonApp::WakeUp(LPCTSTR aCommandLine) const { // 调用父类来处理基本功能(设置前景) CSingleInstance::WakeUp(aCommandLine); // 处理命令行,对于这个示例,将新命令行发送到对话框 CSingletonDlg* lSingletonDlg = (CSingletonDlg*) m_pMainWnd; if (lSingletonDlg) { lSingletonDlg->SetCommandLine(aCommandLine); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485