很多时候,我们都只希望我们的程序只有一个实例在运行,这意味着我们在程序刚初始化的时候,需要检测是否已经存在一个实例。检测的方法多种多样,比如尝试端口占用、进程名称检查、窗口名称检测、文件或注册表标记、后互斥量等等。
以上各有优缺点,推荐使用互斥量的方法,具体的使用方法如下:
第一步,声明一个成员变量来保存一个互斥量
HANDLE m_hExistInst; //用于保存实例互斥
第二步,初始化该互斥量为NULL
//初始化 m_hExistInst = NULL;
第三步,在窗口初化的化的时候做如下检测
m_hExistInst = CreateMutex(NULL, FALSE, _T("www.suchone.com")); if (NULL != m_hExistInst && ERROR_ALREADY_EXISTS == GetLastError()) { CloseHandle(m_hExistInst); MessageBox(_T("已经有一个实例在运行,程序将退出!"), _T("警告"), MB_OK); exit(-1); }
第四步,在程序退出前关闭句柄
//销毁互斥量句柄 if (NULL != m_hExistInst) { CloseHandle(m_hExistInst); }
这样程序就可以保证程序在运行的时候只有一个实例了,如果之前已经有一个实例在运行,即会提示并退出。
这是因为我们第一个实例在初始化的时候,已经在系统中创建了一个有对象名的互斥对象,对象名称就是CreateMutex的第三个参数,任何进程都可以检测并共享该命名对象,所以第二次在运行的时候就可以通过GetLastError()返回的错误码来决定是否已经存在该对象从而可以确定程序是否运行,基于以上几点,所以这个名称最好是一个独特的名称,因为这种方式同样适用于整个系统中的其它进程,从而可能影响到你的或别的程序或的实例判断依据。——更多具体的细节可以参考《Windows核心编程第五版》3.3.3章节
Demo下载地址(VS2008):http://files.suchone.com/upload/2015/12/20151204235638_12504.zip
封装成类:
#pragma once #include <Windows.h> /*! * 单实例应用程序 * */ class ZSingleApplication { public: ZSingleApplication(LPCTSTR name) { m_hInstance = ::CreateMutex(NULL, FALSE, name); if (NULL != m_hInstance) { DWORD dwLastError = ::GetLastError(); if (ERROR_ALREADY_EXISTS == dwLastError) { m_bIsRunning = true; } } } ~ZSingleApplication() { if (NULL != m_hInstance) { ::CloseHandle(m_hInstance); } } /*! * 是否有一个实例在运行 * * \return 如果已经有一个实例在运行返回true,否则返回false。 */ bool IsRunning() { return m_bIsRunning; } private: HANDLE m_hInstance = NULL; bool m_bIsRunning = false; };
使用方法:
//单实例检查 ZSingleApplication instance(L"XXX"); //XXX请按实际情况填写,填写一个你自己定义的与其它应用程序不重复的名称 if (instance.IsRunning()) { assert(false); return 0; }
本站部分资源收集于网络,纯个人收藏,无商业用途,如有侵权请及时告知!