C++ Windows服务和Windows 7中的exe具有相同的互斥体名称
我想使用CreateMutex函数通过Windows服务和同名的exe创建互斥。如果一个互斥体是由Windows服务创建的,并且当exe尝试创建另一个具有相同名称的互斥体时,它会成功,而不会出现任何错误,如error_ready_ 这种情况只在Windows7中发生。但对于Windows XP,显示已存在的错误。 我无法找出操作系统中出现这种差异的原因以及如何纠正此问题 示例代码 服务代码C++ Windows服务和Windows 7中的exe具有相同的互斥体名称,c++,windows,mutex,C++,Windows,Mutex,我想使用CreateMutex函数通过Windows服务和同名的exe创建互斥。如果一个互斥体是由Windows服务创建的,并且当exe尝试创建另一个具有相同名称的互斥体时,它会成功,而不会出现任何错误,如error_ready_ 这种情况只在Windows7中发生。但对于Windows XP,显示已存在的错误。 我无法找出操作系统中出现这种差异的原因以及如何纠正此问题 示例代码 服务代码 #include<iostream> #include<windows.h> #i
#include<iostream>
#include<windows.h>
#include<winbase.h>
using namespace std;
#define SLEEP_TIME 50000
typedef void* handle;
typedef WINADVAPI BOOL (WINAPI *PInitializeSecurityDescriptor)(PSECURITY_DESCRIPTOR, DWORD);
typedef WINADVAPI BOOL (WINAPI *PSetSecurityDescriptorDacl)(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);
#define LOGFILE "D:\\result.txt"
handle temp=NULL;
static int a=65;
char muname[]={"NewMutex2"};
int errNm;
char *str;
FILE* log;
SECURITY_ATTRIBUTES *g_pSaCms;
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService();
bool Win32Mutex(char muname[8])
{
HINSTANCE hAdvApi = LoadLibrary("Advapi32.DLL");
PInitializeSecurityDescriptor pInitializeSecurityDescriptor = 0;
PSetSecurityDescriptorDacl pSetSecurityDescriptorDacl = 0;
PSECURITY_DESCRIPTOR pSD = 0;
g_pSaCms = new SECURITY_ATTRIBUTES;
if (g_pSaCms == 0)
{
prinerr();
return 1;
}
memset(g_pSaCms,0X0, sizeof(*g_pSaCms));
g_pSaCms->nLength = sizeof(*g_pSaCms);
g_pSaCms->bInheritHandle = 1;
pSD = new SECURITY_DESCRIPTOR;
if (pSD == 0)
{
printerr();
goto LABEL_CSA_ERROR;
}
pInitializeSecurityDescriptor = (PInitializeSecurityDescriptor)GetProcAddress(hAdvApi,"InitializeSecurityDescriptor");
if (pInitializeSecurityDescriptor == 0)
{
printerr();
goto LABEL_CSA_ERROR;
}
pSetSecurityDescriptorDacl = (PSetSecurityDescriptorDacl)GetProcAddress(hAdvApi, "SetSecurityDescriptorDacl");
if (pSetSecurityDescriptorDacl == 0)
{
goto LABEL_CSA_ERROR;
}
if (!(*pInitializeSecurityDescriptor)(pSD, SECURITY_DESCRIPTOR_REVISION)
|| (!(*pSetSecurityDescriptorDacl)(pSD, TRUE, (PACL)0, FALSE)))
{
goto LABEL_CSA_ERROR;
}
(void)FreeLibrary(hAdvApi);
g_pSaCms->lpSecurityDescriptor=pSD;
goto LABEL_CSA_PASS;
LABEL_CSA_ERROR:
(void)FreeLibrary(hAdvApi);
if (pSD != 0)
{
delete pSD;
pSD = 0;
}
if (g_pSaCms != 0)
{
delete g_pSaCms;
g_pSaCms = 0;
}
LABEL_CSA_PASS:
temp=::CreateMutex(g_pSaCms,0,muname); //for icdcomm
errNm=GetLastError();
if (!temp)
{
print_err();
}
else
{
print_err();
}
if ((!temp) || errNm == ERROR_ALREADY_EXISTS)
{
if(temp)
{
(void)CloseHandle(temp);
a++;
muname[8]=a;
Win32Mutex(muname);
}
else
{
printInf()
}
return 0;
}
return 1;
}
int main()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "MemoryStatus";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
StartServiceCtrlDispatcher(ServiceTable);
return 0;
}
void ServiceMain(int argc, char** argv)
{
int error;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandler(
"MemoryStatus",
(LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}
// Initialize Service
error = InitService();
if (error)
{
// Initialization failed
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// My service
muname[8]=a;
Win32Mutex(muname);
// We report the running status to SCM.
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);
// The worker loop of a service
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
Sleep(SLEEP_TIME);
}
return;
}
// Control handler function
void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}
在XP上:
在会话0中运行的服务创建互斥锁。同样在会话0中运行的应用程序成功地打开了现有互斥锁的句柄,最后一个错误被设置为error_ready_EXISTS,以让您知道发生了什么
在Windows 7上:
在会话0中运行的服务创建互斥锁。该应用程序可能正在会话1中运行,它创建了一个新的互斥锁,该互斥锁恰好具有相同的名称。这两个互斥体是独立的。这是可能的,因为互斥体名称的作用域是当前会话
如果希望共享互斥体,则需要在名称前加上“Global\”前缀,在全局命名空间中创建互斥体,即:
char muname[]={"Global\\NewMutex2"};
您可以在这里找到更多详细信息。您的意思是什么?您说过,
ERROR\u已经存在
在这两种情况下都会出现(在两个版本的Windows上)。进程可以共享(命名)互斥。一个会创建它(在您的情况下是服务,因为它在您的独立应用程序之前运行),另一个(您的应用程序)只会打开它(使用CreateMutex
,它将返回ERROR\u ready\u EXIST
)。@Bojan:不,他说代码在Win7上运行时没有ERROR\u ready\u EXIST
。我的错误是,打开的窗口太多了,我们在做多重任务时忽略了这个词:)谢谢你的回答。接下来的问题是,我们如何制作一段既适用于pre-Vista又适用于pos-Vista的代码。我们可以在WIN操作系统中使用GLOBAL\吗?或者我们需要使用头保护来保护不同类型的互斥。您的建议是什么?这篇文章暗示从Windows 2000开始就支持“GLOBAL”:我也遇到了同样的问题,浪费了数小时来回答各种随机答案(包括microsoft官方网站)这建议更改互斥体权限。这么简单。
char muname[]={"Global\\NewMutex2"};