CreateMutexwithatwist






3.75/5 (7投票s)
2004年12月1日
1分钟阅读

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文档中也支持这一点。希望有人能找到这些内容有用,我知道我找到了。