正在阻止我的应用程序的多个实例

Preventing multiple instances of my application

本文关键字:实例 应用程序 我的      更新时间:2023-10-16

附加信息

再次,我正在写上面的问题(防止我的应用程序的多个实例)

如果我从programe菜单/桌面快捷方式启动两个实例,代码就有效了。但在我的环境中,

一个实例正在从窗口服务运行。

另一个来自"桌面"快捷方式,参数相同。

如何编写代码有什么帮助吗?

最常见的方法是使用互斥,类似于以下内容:

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);
}

这里有一个在大多数情况下都有效的简单解决方案:

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是最常见的,但它并不完美。如果你想要一个真正彻底的解决方案,以及为什么以上方法不好,请查看Codeproject上的此链接。

TLDR:防止同一进程的多个实例的唯一安全和通用的方法是使用互斥,因为只有这样才能保证不会给您带来竞争条件。

这里有一篇关于这个主题的好文章。当我不得不做类似的事情时,我使用了它,并且解决方案运行得很好:避免多个实例。

您正在寻找命名互斥体(以参数命名,如果它应该禁止应用程序在多个实例中运行的话)。

我也看到过这个解决方案,没有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);
    }