// 确保运行一个进程实例的方式有很多,可以通过扫描进程列表来实现,也可以通过枚举程序窗口的方式来实现,也可以通过共享全局变量的方式来实现,
// 更简单的方式是通过创建系统命名互斥对象来实现。
// PS:实现原理:
// 通常情况下,系统中的进程是相互独立的,每个进程都有自己的独立资源和地址空间,进程间互不影响。所以同一个进程可以重复运行。对于特殊情况(共享系统资源)下,会有进程互斥现象产生。
// 微软提供了CreateMutex函数来创建或者打开一个已命名或未命名的互斥对象,程序在每次运行的时候,通过判断系统中是否存在相同的互斥对象来确定程序是否重复运行。
// PS:CreateMutext函数:
// 原型:HANDLE WINAPI CreateMutex(
// _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
// _In_ BOOL bInitialOwner,
// _In_opt_ LPCTSTR lpName
// );
// 参数:lpMutexAttributes:表示互斥对象的安全设置,是一个指向SECURITY_ATTRIBUTES结构的指针,在该程序中直接设置为NULL即可。
// bInitialOwner:表示线程是否获取互斥锁对象的初始所有权,在该程序中,无论该参数设置为TRUE或者FALSE都不影响程序的正确运行。
// lpName:表示互斥对象的名称。
// 结果:返回互斥对象句柄。
// PS:对于通过互斥对象来判断进程实例是否重复运行的程序来说,该参数一定要设置,而且要保证设置名称的唯一性。
// PS:如果lpName与现有事件、信号量、等待定时器、作业或者文件映射对象的名称匹配,且这些对象共享相同的命名空间(Namespace),
// 则该函数失败,GetLastError()返回ERROR_INVALID_HANDLE。
// PS:程序判断原理是通过CreateMutex函数创建一个命名的互斥对象,如果对象创建成功,而且通过调用GetLastError获取的返回码为ERROR_ALREADY_EXISTS,
// 则表示该命名互斥对象已经存在,即程序重复运行。否则,认为程序是首次运行。
// ps:
// 1.在程序中不要调用CloseHandle来关闭互斥对象句柄。
// 2.在线程同步时,使用ReleaseHandle来释放线程对互斥对象的控制权。
// 示例代码:
BOOL IsAlreadyRun() {
Handle hMutex = NULL;
hMutex = ::CreateMutex(NULL, FALSE, "TEST");
if (hMutex) {
if (ERROR_ALREADY_EXISTS == ::GetLastError()) {
return TRUE;
}
}
return FALSE;
}