我想使用CreateMutex函数通过Windows服务和具有相同名称的exe创建互斥锁。如果Windows服务创建了一个互斥锁,并且当exe尝试创建另一个具有相同名称的互斥锁时,它会成功,而不会出现像ERROR_ALREADY_EXIST这样的错误。
仅在Windows 7中发生这种情况。但是对于Windows XP,会显示ERROR_ALREADY_EXIST。 我无法弄清楚这种操作系统差异的原因以及如何解决这个问题。
示例代码
服务代码
#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;
}
对于可执行代码(代码保持不变,buc仅在主函数中更改)
int main()
{
muname[8]=a;
Win32Mutex(muname);
Sleep(SLEEP_TIME);
return 0;
}
答案 0 :(得分:17)
在XP上:
在会话0中运行的服务会创建互斥锁。该应用程序也在会话0中运行,成功打开现有互斥锁的句柄,最后一个错误设置为ERROR_ALREADY_EXISTS,以便让您知道发生了什么。
在Windows 7上:
在会话0中运行的服务会创建互斥锁。该应用程序可能在第一个会话中运行,它创建了一个恰好具有相同名称的新互斥锁。这两个互斥体是独立的。这是可能的,因为互斥锁名称的范围限定为当前会话。
如果要共享互斥锁,则需要在全局命名空间中创建它们,方法是在名称前添加“Global”前缀,即:
char muname[]={"Global\\NewMutex2"};
您可以在此处找到有关session zero isolation的更多详细信息。