Fork me on GitHub

只能同时运行一个实例的程序

      很多情况下,程序会要求同一时间内只能运行一个实例,以免发生系统崩溃、数据遭破坏等后果。最常用被使用的是创建一个有名字的Mutex(互斥)的方法。程序的实例或对象含有Mutex之后,同一时间内将只能被一个线程访问。

      Windows给我们提供了CreateMutex函数来创建Mutex。原型如下:

HANDLE WINAPI CreateMutex(
  __in_opt  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  __in      BOOL bInitialOwner,//Mutex的所有者的句柄。
  __in_opt  LPCTSTR lpName//Mutex对象的名称。
);

      我们为互斥体起一个名字,作为CreateMutex的第三个参数。那么程序运行时,将使用CreateMutex创建一个互斥体,再次运行将再创建一个同名的互斥体从而引发错误信息,此时GetLastError函数将返回ERROR_ALREADY_EXISTS错误信息。

      利用这一点,我们可以达到只让程序运行一个实例的目的。代码如下。

 1 #include <windows.h>
 2 #include <tchar.h>
 3 int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCMD)
 4 {
 5  CreateMutex(NULL,FALSE,_T("Mutex"));
 6  if(GetLastError()==ERROR_ALREADY_EXISTS)
 7   return FALSE;
 8  MessageBox(NULL,_T("Program Success !"),_T("Mutex"),MB_OK);
 9  return 0;
10 }

      但这样并不完善。当用户想要运行该程序时,如果已经有实例正在运行,最好能激活运行中实例的窗口,如果该窗口处于最小化则将其弹出

 1 BOOL MyMUTEX()
 2 {
 3  //1、创建Mutex
 4  HANDLE hMutex=CreateMutex(NULL,TRUE,_T("Mutex"));
 5  if (hMutex == NULL)
 6  {
 7   return FALSE;
 8  }
 9  //2、如果Mutex已经存在并且正在运行
10  if (GetLastError() == ERROR_ALREADY_EXISTS)
11  {
12   //3、获取窗口名称
13   HWND hProgramWnd =FindWindow(NULL,_T("WindowsName"));
14   if (hProgramWnd)
15   {
16    WINDOWPLACEMENT* pWndpl = NULL;
17    WINDOWPLACEMENT   wpm; 
18    
19    GetWindowPlacement(hProgramWnd,&wpm);
20    pWndpl =&wpm;
21    if (pWndpl)
22    {
23     //4、将运行的程序窗口还原成正常状态
24     pWndpl->showCmd = SW_SHOWNORMAL;
25     SetWindowPlacement(hProgramWnd,pWndpl);
26     SetWindowPos(hProgramWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
27     //激活窗口 
28     SetForegroundWindow(hProgramWnd); 
29    }
30   }
31   //6、关闭进程互斥体
32   CloseHandle(hMutex);
33   hMutex = NULL;
34   return FALSE;
35  }
36  return TRUE;
37 }

也可以使用下面这种更为简短的代码。但不知为什么,在我的电脑上运行时,感觉上面这段代码比下面代码的运行速度要快很多。

 1 BOOL MyMUTEX()
 2 {
 3  HANDLE hMutex=CreateMutex(NULL,TRUE,_T("Mutex"));
 4  if (hMutex == NULL)
 5  {
 6   return FALSE;
 7  }
 8  if (GetLastError() == ERROR_ALREADY_EXISTS)
 9  {
10   HWND hProgramWnd =FindWindow(NULL,_T("WindowsName"));
11   ShowWindow(hProgramWnd,SW_RESTORE);
12   SetForegroundWindow(hProgramWnd); 
13  
14   CloseHandle(hMutex);
15   hMutex = NULL;
16   return FALSE;
17  }
18  return TRUE;
19 }

 

posted on 2015-09-22 15:42  地精的贪婪  阅读(458)  评论(0编辑  收藏  举报