防止我的应用程序的多个实例

时间:2012-01-10 06:56:13

标签: c++ visual-c++ mfc

其他信息

我再次撰写上述问题(防止我的应用程序的多个实例)

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

一个实例正在从Window Service运行。

另一个来自具有相同参数的桌面快捷方式。

任何帮助如何编写代码?

5 个答案:

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