3

以下代码有时可以正常工作,有时会引发“访问被拒绝”错误。行为不一致。

_hMutex = CreateMutex(NULL, FALSE, MutexName);
    if (_hMutex == NULL) 
{
  throw MY_ERROR(GetLastError(), L"Error creating mutex handle");
}

我运行具有此代码的独立可执行文件,执行操作并退出。它不是多线程应用程序。每次运行此程序时,我都使用相同的用户凭据登录。

你能帮我解决这个问题吗?

谢谢, 哼哼

4

4 回答 4

3

如果互斥体是命名互斥体,并且该对象在此函数调用之前已存在,则返回值是现有对象的句柄,GetLastError返回ERROR_ALREADY_EXISTS,bInitialOwner 被忽略,调用线程不被授予所有权。

但是,如果调用者的访问权限有限,则该函数将失败,ERROR_ACCESS_DENIED调用者应使用OpenMutex函数。

MSDN

于 2012-04-13T11:32:19.717 回答
2

今天我有一个类似的问题,但有不同的会话。互斥体被命名并具有前缀Global\。当一个应用程序创建命名的全局互斥锁时,不允许不同用户帐户的其他应用程序与同一个互斥锁同步。CreateMutex 总是返回错误ERROR_ACCESS_DENIED。OpenMutex 成功,但互斥锁不能用于同步。

解决方案是每个应用程序必须使用CreateMutexEx(仅SYNCHRONIZE请求)访问全局互斥锁,并且您必须指定 SecurityAttributes。默认的 SecurityAttributes 不允许用户帐户之间的共享。

工作代码如下所示:

HANDLE hMutex;
{
    DWORD dwRes, dwDisposition;
    PSID pEveryoneSID = NULL;
    PACL pACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea[1];
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld =
            SECURITY_WORLD_SID_AUTHORITY;
    SECURITY_ATTRIBUTES sa;
    LONG lRes;

    // Create a well-known SID for the Everyone group.
    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
                     SECURITY_WORLD_RID,
                     0, 0, 0, 0, 0, 0, 0,
                     &pEveryoneSID))
    {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone read access to the key.
    ZeroMemory(&ea, 1 * sizeof(EXPLICIT_ACCESS));
    ea[0].grfAccessPermissions = SYNCHRONIZE;
    ea[0].grfAccessMode = SET_ACCESS;
    ea[0].grfInheritance= NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;
    
    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(1, ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes) 
    {
        _tprintf(_T("SetEntriesInAcl Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize a security descriptor.  
    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, 
                             SECURITY_DESCRIPTOR_MIN_LENGTH); 
    if (NULL == pSD) 
    { 
        _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
        goto Cleanup; 
    } 
 
    if (!InitializeSecurityDescriptor(pSD,
            SECURITY_DESCRIPTOR_REVISION)) 
    {  
        _tprintf(_T("InitializeSecurityDescriptor Error %u\n"),
                                GetLastError());
        goto Cleanup; 
    } 
 
    // Add the ACL to the security descriptor. 
    if (!SetSecurityDescriptorDacl(pSD, 
            TRUE,     // bDaclPresent flag   
            pACL, 
            FALSE))   // not a default DACL 
    {  
        _tprintf(_T("SetSecurityDescriptorDacl Error %u\n"),
                GetLastError());
        goto Cleanup; 
    } 

    // Initialize a security attributes structure.
    sa.nLength = sizeof (SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;

    hMutex = CreateMutexExW(&sa, L"Global\\MyNamedMutex", 0, SYNCHRONIZE);

Cleanup:

    if (pEveryoneSID) 
        FreeSid(pEveryoneSID);
    if (pAdminSID) 
        FreeSid(pAdminSID);
    if (pACL) 
        LocalFree(pACL);
    if (pSD) 
        LocalFree(pSD);
}

// Do something with hMutex
WaitForSingleObject(hMutex, INFINITE);

CloseHandle(hMutex);

来源链接:

于 2021-03-15T15:49:30.903 回答
1

这可能是因为MutexName已经存在一个互斥锁。您正在使用默认安全描述符创建互斥锁,这(取决于您使用此互斥锁的方式)可能不允许其他用途。

有关更多信息,请参阅MSDN。一个有用的片段:

如果互斥体是命名互斥体并且对象在此函数调用之前存在,[省略],如果调用者的访问权限有限,则函数将失败, ERROR_ACCESS_DENIED调用者应使用 OpenMutex 函数。

于 2012-04-13T11:33:50.713 回答
0

我终于找到了。有一个使用系统帐户运行的服务,它创建互斥锁和一个由用户尝试访问它运行的 exe。这是由于许可。

于 2013-02-06T14:09:30.120 回答