VC 實現程序只運行一個實例,並顯示已運行的程序

轉載:http://blog.sina.com.cn/s/blog_4b44e1c00100bh69.html

 

進程的互斥運行:CreateMutex函數實現只運行一個程序實例

  正常情況下,一個進程的運行一般是不會影響到其他正在運行的進程的。但是對於某些有特殊要求的如以獨佔方式使用串行口等硬件設備的程序就要求在其進程運行期間不允許其他試圖使用此端口設備的程序運行的,而且此類程序通常也不允許運行同一個程序的多個實例。這就引出了進程互斥的問題。

  實現進程互斥的核心思想比較簡單:進程在啓動時首先檢查當前系統是否已經存在有此進程的實例,如果沒有,進程將成功創建並設置標識實例已經存在的標記。此後再創建進程時將會通過該標記而知曉其實例已經存在,從而保證進程在系統中只能存在一個實例。具體可以採取內存映射文件、有名事件量、有名互斥量以及全局共享變量等多種方法來實現。下面就分別對其中具有代表性的有名互斥量和全局共享變量這兩種方法進行介紹:

 // 創建互斥量
 HANDLE m_hMutex = CreateMutex(NULL, FALSE, “Sample07”);
 // 檢查錯誤代碼

 // 如果程序已經存在並且正在運行
 if (GetLastError() == ERROR_ALREADY_EXISTS)

 {
   // 如果已有互斥量存在則釋放句柄並復位互斥量
  CloseHandle(m_hMutex);
  m_hMutex = NULL;
  // 程序退出
  return FALSE;
 }

  上面這段代碼演示了有名互斥量在進程互斥中的用法。代碼的核心是CreateMutex()對有名互斥量的創建。CreateMutex()函數可用來創建一個有名或無名的互斥量對象,其函數原型爲:

   HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全屬性的指針
  BOOL bInitialOwner, // 初始化互斥對象的所有者
  LPCTSTR lpName // 指向互斥對象名的指針
  );

  如果函數成功執行,將返回一個互斥量對象的句柄。如果在CreateMutex()執行前已經存在有相同名字的互斥量,函數將返回這個已經存在互斥量的句柄,並且可以通過GetLastError()得到錯誤代碼ERROR_ALREADY_EXIST。可見,通過對錯誤代碼ERROR_ALREADY_EXIST的檢測可以實現CreateMutex()對進程的互斥。

建立互斥體,用來同步。如果一個線程獲取了互斥體,則要獲取該互斥體的第二個線程將被掛起,直到第一個線程釋放該互斥體。  
  參數  
  lpMutexAttributes    
  指向一個SECURITY_ATTRIBUTES結構的指針,這個結構決定互斥體句柄是否被子進程繼承。     
  bInitialOwner 
  布爾類型,決定互斥體的創建者是否爲擁有者  
  lpName    
  指向互斥體名字字符串的指針。互斥體可以有名字。  
  互斥體的好處是可以在進程間共享

 

將 CreateMutex 代碼加到  ****App::InitInstance() 函數中即可實現只運行一個實例的效果。

以上文章轉載自:我的程序員生涯 http://steveq.blog.sohu.com/71112121.html

 

通過上面文章我們知道:使用CreateMutex可以防止一個實例多次運行。

下面介紹如何實現當再次運行程序時如何激活已經運行的程序,比如此程序只是已被最小化。

方法如下:

 

複製代碼
 1 BOOL C**App::InitInstance()
 2 {
 3 
 4  //創建進程互斥體Sample07
 5  m_hMutex = CreateMutex(NULL,TRUE,_T("Sample07"));
 6 
 7  if (m_hMutex == NULL)
 8  {
 9   return FALSE;
10  }
11 
12  //如果程序已經存在並且正在運行
13  if (GetLastError() == ERROR_ALREADY_EXISTS)
14  {
15 
16   HWND hProgramWnd = ::FindWindow(NULL,L"Sample07");
17   if (hProgramWnd)
18   {
19    WINDOWPLACEMENT* pWndpl = NULL;
20 
21    WINDOWPLACEMENT   wpm; 
22    pWndpl =&wpm;
23    GetWindowPlacement(hProgramWnd,&wpm);
24    if (pWndpl)
25    {
26     //將運行的程序窗口還原成正常狀態
27     pWndpl->showCmd = SW_SHOWNORMAL;
28     ::SetWindowPlacement(hProgramWnd,pWndpl);
29     SetWindowPos(hProgramWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
30     FlashWindow(hProgramWnd,TRUE);//任務欄圖標閃爍
31    }
32 
33   }
34   //關閉進程互斥體
35 
36   CloseHandle(m_hMutex);
37   m_hMutex = NULL;
38   return FALSE;
39  }
40 }
複製代碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章