65.9K
CodeProject 正在变化。 阅读更多。
Home

CreateMutexwithatwist

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.75/5 (7投票s)

2004年12月1日

1分钟阅读

viewsIcon

29441

创建互斥锁,但稍作修改……使用了一些非默认参数。

引言

这是对Liviu Birjega提交的优秀文章的一个简短补充:使用WtsAPI32在终端服务上运行基于Windows的应用程序

在我的经验中,在WTS下,CreateMutex函数可以简单地这样调用

hMutex = CreateMutex(NULL, FALSE, csAppName);

但是,在第二个及后续会话中这样做,调用GetLastError()时会返回错误 5(ERROR_ACCESS_DENIED)。

进一步阅读MSDN文档后,它提供了一些解释如下

“……指向控制对象共享的安全描述符。如果为此成员指定 NULL,则对象将分配调用进程的默认安全描述符。

这与通过分配空DACL来授予所有人访问权限不同.

默认安全描述符基于属于调用进程的访问令牌的默认DACL。默认情况下,进程访问令牌中的默认DACL仅允许访问由访问令牌表示的用户。如果其他用户必须访问对象,则可以创建一个带有空DACL的安全描述符,或者向DACL添加ACE,以授予一组用户访问权限。”

Rob Manderson的优秀文章对此进行了更详细的解释:使用访问控制列表来保护对对象的访问

因此,为了在调用GetLastError()时获得期望的结果(183 = ERROR_ALREADY_EXISTS),你实际上需要做类似这样的事情……

BOOL IsAnotherWTSUserLoggedIn(LPCTSTR sAppName)
{
   if(GetSystemMetrics(SM_REMOTESESSION))
   {
      HANDLE hMutex = NULL;
      SECURITY_DESCRIPTOR sd;
 
      InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);

      SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);

      SECURITY_ATTRIBUTES sa = { sizeof sa, &sd, FALSE };

      CString csAppName;
      csAppName.Format(_T(“Global\\%s”), sAppName);

      hMutex = ::CreateMutex(&sa, FALSE, csAppName);

      if( GetLastError() == ERROR_ALREADY_EXISTS )
      {
          CloseHandle(hMutex);
          return TRUE;
      }
   }

   return FALSE;
}

是的,还有一点小评论给Liviu,似乎正确的“动词”是“Global”(全局)——不是“Session”(会话)——MSDN文档中也支持这一点。希望有人能找到这些内容有用,我知道我找到了。

© . All rights reserved.