• Windows编程技术之运行单一实例


    前言

    一个程序在windows上是否存在多个运行实例,可根据访问进程列表、枚举程序窗口、共享全局变量、系统命名互斥对象进行判断。此处详述最后一种方法。


    实现

    CreateMutex该函数功能为创建或者打开一个已经命名或者未命名的互斥对象。

     HANDLE CreateMutex(
    	 LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针,常赋值为NULL
    	 BOOL bInitialOwner, // 初始化互斥对象的所有者
    	 LPCTSTR lpName // 指向互斥对象名的指针
     );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    该函数的用法有,如果在一个程序代码中创建了一个互斥对象。那么程序在每次运行的时候,就可以根据系统中是否有相同命名的互斥对象,若有,则表明程序重复运行,否则无。
    示例

    // CreateMutex_Test.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include 
    #include 
    using namespace std;
    
    HANDLE hMutex = NULL;
    DWORD WINAPI thread01(LPVOID lvParamter)
    {
    	for (int i = 0; i < 10; i++)
    	{
    		WaitForSingleObject(hMutex, INFINITE); //互斥锁
    		cout << "Thread 01 is working!" << endl;
    		ReleaseMutex(hMutex); //释放互斥锁
    	}
    	return 0;
    }
    
    DWORD WINAPI thread02(LPVOID lvParamter)
    {
    	for (int i = 0; i < 10; i++)
    	{
    		WaitForSingleObject(hMutex, INFINITE); //互斥锁
    		cout << "Thread 02 is working!" << endl;
    		ReleaseMutex(hMutex); //释放互斥锁
    	}
    	return 0;
    }
    
    // 判断是否重复运行
    BOOL IsAlreadyRun()
    {
    	hMutex = ::CreateMutex(NULL, TRUE, "TEST");
    	if (hMutex)
    	{
    		if (ERROR_ALREADY_EXISTS == ::GetLastError())
    		{
    			return TRUE;
    		}
    	}
    	return FALSE;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	// 判断是否重复运行
    	if (IsAlreadyRun())
    	{
    		printf("Already Run!!!!\n");
    	}
    	else
    	{
    		printf("NOT Already Run!\n");
    	}
    
    	HANDLE hThread = CreateThread(NULL, 0, thread01, NULL, 0, NULL);  //创建线程01
    	hThread = CreateThread(NULL, 0, thread02, NULL, 0, NULL);     //创建线程01
    	CloseHandle(hThread); //关闭句柄
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    运行结果
    在这里插入图片描述
    此外,注意到上述代码的参数中,CreateMutex函数的第二个参数设置为TRUE,导致另外两个子线程没有运行,这是因为第二个参数设置为TURE即代表调用者拥有该互斥对象的所有权,如果没有释放,则其他(如代码中的两个子线程都没有运行)希望获取该对象所有权的线程都没法正常运行。若设置为FALSE,结果如下图所示
    在这里插入图片描述可以看到两个线程正常运行了,如果第二个参数仍为TRUE,通过其他方式释放该互斥对象会造成什么效果呢?
    在主函数中,CreateThread函数的上一行添加是释放互斥对象的函数语句ReleaseMutex(hMutex);,即可达到如下图所示的结果
    在这里插入图片描述
    此外,如果除了互斥对象的名字不一样,其他都一样的程序,在运行中不会导致系统检测到一个程序在重复运行。

    当然,如果不使用ReleaseMutex()函数进行释放互斥对象,而使用CloseHandle()函数,该函数会直接关闭该互斥对象,并且该互斥对象会被废弃掉,其他等待该互斥对象所有权的线程也会被阻止。

  • 相关阅读:
    [CC2642R1][VSCODE+Embedded IDE+IAR Build+Cortex-Debug] TI CC2642R1基于VsCode的开发环境
    java 实现建造者模式
    创建对象在堆区如何分配内存
    洛谷刷题:循环结构
    FFmpeg入门详解之113:live555简介
    oracle rac了解
    UOS 序列号激活指令及方法
    vue3.0运行npm run dev 报错Cannot find module node:url
    【Java面试突击-9】Java并发编程(AQS)
    【问题排查】InheritableThreadLocal类引发的生产事故
  • 原文地址:https://blog.csdn.net/qq_44116998/article/details/127676424