您的位置:首页 > 移动开发

CreateMutex(NULL, FALSE, strAppName); 配合GetLastError() == ERROR_ALREADY_EXISTS

2013-12-13 10:47 295 查看
正常情况下,一个进程的运行一般是不会影响到其他正在运行的进程的。但是对于某些有特殊要求的如以独占方式使用串行口等硬件设备的程序就要求在其进程运行期间不允许其他试图使用此端口设备的程序运行的,而且此类程序通常也不允许运行同一个程序的多个实例。这就引出了进程互斥的问题。

  实现进程互斥的核心思想比较简单:进程在启动时首先检查当前系统是否已经存在有此进程的实例,如果没有,进程将成功创建并设置标识实例已经存在的标记。此后再创建进程时将会通过该标记而知晓其实例已经存在,从而保证进程在系统中只能存在一个实例。具体可以采取内存映射文件、有名事件量、有名互斥量以及全局共享变量等多种方法来实现。下面就分别对其中具有代表性的有名互斥量和全局共享变量这两种方法进行介绍:

// 创建互斥量

HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");

// 检查错误代码

if (GetLastError() == ERROR_ALREADY_EXISTS) {

 // 如果已有互斥量存在则释放句柄并复位互斥量

 CloseHandle(m_hMutex);

 m_hMutex = NULL;

 // 程序退出

 return FALSE;

}

  上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex()对有名互斥量的创建。CreateMutex()函数可用来创建一个有名或无名的互斥量对象,其函数原型为:

HANDLE CreateMutex(

 LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针

 BOOL bInitialOwner, // 初始化互斥对象的所有者

 LPCTSTR lpName // 指向互斥对象名的指针

);

  如果函数成功执行,将返回一个互斥量对象的句柄。如果在CreateMutex()执行前已经存在有相同名字的互斥量,函数将返回这个已经存在互斥量的句柄,并且可以通过GetLastError()得到错误代码ERROR_ALREADY_EXIST。可见,通过对错误代码ERROR_ALREADY_EXIST的检测可以实现CreateMutex()对进程的互斥。

摘自:http://topic.csdn.net/t/20051121/15/4407868.html#

建立互斥体,用来同步。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

参数

lpMutexAttributes

指向一个SECURITY_ATTRIBUTES结构的指针,这个结构决定互斥体句柄是否被子进程继承。

bInitialOwner

布尔类型,决定互斥体的创建者是否为拥有者

lpName

指向互斥体名字字符串的指针。互斥体可以有名字。

互斥体的好处是可以在进程间共享

个人心得体会:

CreateMutex() 用于有独占要求的程序 (在其进程运行期间不允许其他使用此端口设备的程序运行,或不允许同名程序运行)。

如有同名程序运行,则通过 GetLastError()得到错误代码 ERROR_ALREADY_EXIST

刚才又执行了下得出的结果(程序名samp)

一般情况下:一进入调试阶段,进程管理器中就出现了samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,跳过不执行if中的内容,所以表示没有互斥。

调试之前先运行debug中的samp.exe再调试:一进入调试阶段,进程管理器中就出现了两个samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,执行if中的内容,表示有互斥。

另:讲的也很好http://www.netinformatique.info/tag/CreateMutex

我的OnlnitDialog()中有

if(CreateMutex(NULL, true, "Arp") != NULL )

{

if(GetLastError() == ERROR_ALREADY_EXISTS )

{

AfxMessageBox("已经有一个程序启动了。");

exit(0);

}

}

这么一段代码 然后我在一个名叫 扫描的 命令响应里

WinExec("cmd /c ping -n 4 192.168.0.1 ",SW_HIDE);



system("arp -a >static.set");

执行程序 发现出现 "已经有一个程序启动了"

怎么解决???

不行啊 改了的话 它就直接再产生一个主应用程序了…

可以不用要NULL的判断,直接判断GetLastError

跟1楼一样 因为我的主程序初始化就是在OnlnitDialog()这个函数里的

我想问 有没有办法在执行system("arp -a >static.set"); 之前不调用OnlnitDialog()这个…

1、不要在OnInitDialog函数里做,最好在InitInstance里。

2、Mutex的名字最好是用UUIDGEN命令生成的,不会重名。

例如

#define UNIQUE_NAME "{d7fdb550-4dcd-4693-9094-b5f63886c14e}"

BOOL CXXXApp::InitInstance()

{

// 为了确保只运行一个实例,建立全局互斥量

m_hUnique = CreateMutex(NULL, false, UNIQUE_NAME);

if (GetLastError() == ERROR_ALREADY_EXISTS)

{

CString strTitle("XXXXXXXX");

HWND hWnd = FindWindow(NULL, strTitle);

if (IsWindow(hWnd)) {

SetForegroundWindow(hWnd);

ShowWindow(hWnd, SW_SHOW);

}

return FALSE;

}

….

}

还有就是 为什么执行WinExec("cmd /c ping -n 4 192.168.0.1 ",SW_HIDE); 这个

的时候 它不调用OnlnitDialog()这个呢?

没有办法啊 我现在大部分都是在CArpDlg里面做的 要改动的话 很多头文件要改…

改成这样WinExec("cmd /c nbtscan -r 192.168.0.0/24&&arp -a >static.set ",SW_HIDE);

怎么效果还是一样?不管怎么样都要调用OnlnitDialog()吗?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: