其他信息
我再次撰写上述问题(防止我的应用程序的多个实例)
如果我从programe菜单/桌面快捷方式启动两个实例,则代码适用。但在我的环境中,
一个实例正在从Window Service运行。
另一个来自具有相同参数的桌面快捷方式。
任何帮助如何编写代码?
答案 0 :(得分:13)
最常用的方法是使用互斥锁,类似于以下内容:
int WINAPI WinMain(...)
{
const char szUniqueNamedMutex[] = "com_mycompany_apps_appname";
HANDLE hHandle = CreateMutex( NULL, TRUE, szUniqueNamedMutex );
if( ERROR_ALREADY_EXISTS == GetLastError() )
{
// Program already running somewhere
return(1); // Exit program
}
// Program runs...
// Upon app closing:
ReleaseMutex( hHandle ); // Explicitly release mutex
CloseHandle( hHandle ); // close handle before terminating
return( 1 );
}
您必须确保正确关闭 - 不删除互斥锁的程序崩溃可能会阻止程序再次运行,但理论上操作系统将在进程结束后清除任何悬空互斥锁。
常用的另一种方法是搜索节目标题的窗口标题:
HWND hWnd=::FindWindow(LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to window name
);
如果它为null,则找不到窗口,因此程序未运行。在关闭这个新实例之前,你可以使用它来关注正在运行的应用程序,这样用户就不会想知道应用程序没有打开的原因。
if(hWnd != NULL)
{
ShowWindow(hWnd,SW_NORMAL);
// exit this instance
return(1);
}
答案 1 :(得分:8)
这是一个大部分时间都可以使用的简单解决方案:
CreateEvent(NULL, FALSE, FALSE, "MyEvent");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// Do Stuff
return FALSE;
}
另一种方式:
CreateSemaphore(NULL, TRUE, TRUE, "MySemaphore");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// Do Stuff
return FALSE;
}
另一种方式:
CreateMutex(NULL, TRUE, "MyMutex");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// Do Stuff
return FALSE;
}
正如,提到的另一个答案,CreateMutex
是最常见的,但它并不完美。如果您想要一个非常彻底的解决方案以及为什么上述方法不好,请查看link on Codeproject。
答案 2 :(得分:5)
TLDR :防止同一进程的多个实例的唯一安全和一般方法是使用互斥锁,因为只有这样才能保证不会给你带来竞争条件。
这里有一篇关于这个主题的好文章。我在必须做类似的事情时使用它,解决方案工作正常:AvoidingMultipleInstances。
答案 3 :(得分:3)
您正在寻找named mutex(以参数命名,如果它应该禁止该应用在多个实例中运行)。
答案 4 :(得分:2)
我也见过这个解决方案,没有GetLastError():
HANDLE hMutex = CreateMutexA(NULL, FALSE, "my mutex");
DWORD dwMutexWaitResult = WaitForSingleObject(hMutex, 0);
if (dwMutexWaitResult != WAIT_OBJECT_0)
{
MessageBox(HWND_DESKTOP, TEXT("This application is already running"), TEXT("Information"), MB_OK | MB_ICONINFORMATION);
CloseHandle(hMutex);
}