无法防止来自不同用户的同一程序的多个实例
Not able to prevent multiple instances of the same program from different users
我有以下代码。它可以防止同一用户下同一应用程序的多个实例。但是,我还想防止同一台计算机上的其他用户在另一个用户已经在运行该应用程序时运行该应用程序。即使应用程序已由其他用户运行,该代码也会成功创建互斥锁。无法弄清楚我在这里做错了什么。任何帮助,不胜感激。
m_hMutex = ::CreateMutex(NULL, FALSE, PREDEFINED_UNIQUE_ID);
if (::GetLastError() == ERROR_ALREADY_EXISTS)
{
if (m_hMutex)
::CloseHandle(m_hMutex);
//in case the previous instance of APP is still in the process of closing
::Sleep(5*1000);
m_hMutex = ::CreateMutex(NULL, FALSE, PREDEFINED_UNIQUE_ID);
if (::GetLastError() == ERROR_ALREADY_EXISTS)
{
EndSplashWindow();
AfxMessageBox( _T("An instance of APPis already running."), MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
return FALSE;
}
}
您没有显示PREDEFINED_UNIQUE_ID
的实际值,但我猜测它不是在Global
内核命名空间中创建互斥锁,而是在每个会话命名空间中创建互斥锁。 使用Global
命名空间是跨越用户会话所必需的:
单独的客户端会话命名空间使多个客户端能够运行相同的应用程序,而不会相互干扰。对于在客户端会话下启动的进程,系统默认使用会话命名空间。但是,这些进程可以通过在对象名称前面加上"Global\"前缀来使用全局命名空间。例如,以下代码调用
CreateEvent
并在全局命名空间中创建名为 CSAPP 的事件对象:CreateEvent( NULL, FALSE, FALSE, "Global\CSAPP" );
。
全局命名空间的另一个用途是用于使用命名对象的应用程序,以检测系统中已存在跨所有会话运行的应用程序实例。必须在全局命名空间而不是每个会话命名空间中创建或打开此命名对象。默认情况下支持每个会话运行一次应用程序的更常见情况,因为命名对象是在每会话命名空间中创建的。
更新:您还需要处理CreateMutex()
由于安全权限而无法访问另一个会话中的互斥锁的情况。 你需要处理GetLastError()
返回ERROR_ACCESS_DENIED
的情况,这本身就意味着互斥锁存在。
尝试更多类似的东西:
#define PREDEFINED_UNIQUE_ID _T("Global\MyUniqueMutexName");
m_hMutex = ::CreateMutex(NULL, FALSE, PREDEFINED_UNIQUE_ID);
// or: m_hMutex = ::CreateMutexEx(&sa, PREDEFINED_UNIQUE_ID, 0, SYNCHRONIZE);
DWORD dwErrorCode = ::GetLastError();
if ((m_hMutex) && (dwErrorCode == ERROR_ALREADY_EXISTS))
{
::CloseHandle(m_hMutex);
//in case the previous instance of APP is still in the process of closing
::Sleep(5*1000);
// consider using WaitForSingleObject() instead, in case the app takes less than 5 seconds to close...
m_hMutex = ::CreateMutex(NULL, FALSE, PREDEFINED_UNIQUE_ID);
// or: m_hMutex = ::CreateMutexEx(&sa, PREDEFINED_UNIQUE_ID, 0, SYNCHRONIZE);
dwErrorCode = ::GetLastError();
}
if (dwErrorCode != 0)
{
EndSplashWindow();
switch (dwErrorCode)
{
case ERROR_ALREADY_EXISTS:
case ERROR_ACCESS_DENIED:
AfxMessageBox( _T("An instance of APP is already running."), MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
break;
default:
AfxMessageBox( _T("Error checking if an instance of APP is already running."), MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
break;
}
return FALSE;
}
// OK to run now!
return TRUE;
或者,为了最大程度地减少报告ERROR_ACCESS_DENIED
的机会,您可以提供空 DACL 以CreateMutex()
:
PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!pSD)
{
EndSplashWindow();
AfxMessageBox( _T("Error allocating security descriptor."), MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
return FALSE;
}
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
LocalFree(pSD);
EndSplashWindow();
AfxMessageBox( _T("Error initializing security descriptor."), MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
return FALSE;
}
if (!SetSecurityDescriptorDacl(pSD, TRUE, NULL, FALSE))
{
LocalFree(pSD);
EndSplashWindow();
AfxMessageBox( _T("Error setting access for security descriptor."), MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
return FALSE;
}
SECURITY_ATTRIBUTES sa = {};
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;
m_hMutex = ::CreateMutex(&sa, FALSE, PREDEFINED_UNIQUE_ID);
...
LocalFree(pSD);
相关文章:
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 如何使实例化在我的 OpenGL 程序中工作?
- 在Visual Studio中单实例Qt应用程序版本5.11.1中,在所有其他窗口的顶部打开Qt MainWindow
- C++ 为什么在定义的编译和链接之前引用外部实例的程序
- 当我们实例化Caffe2预测器时,应用程序被卡住了
- C++程序问题:抛出'std::invalid_argument'实例后终止调用
- 一次运行程序的多个实例C
- 无法防止来自不同用户的同一程序的多个实例
- 跨平台方式,以防止打开应用程序的多个实例
- 编译的程序是否有可能不包含实例化的模板类
- ACE在同一PC上具有多个应用程序实例 - 仅首先获取消息
- 尝试实例化 QWidget 时 QT 程序出现段错误
- 收集有关在程序中实例化哪些模板变体的信息
- 运行具有 40 个不同"身份"的同一程序与运行 40 个程序实例。优点和缺点?
- 在Windows(C++)中运行的应用程序实例中打开文件
- 一个应用程序实例,独立于平台,C++11
- 如何自定义已存在程序实例的右键单击
- 如何调用已运行的应用程序实例
- 与两个Qt程序实例通信