Wince下開發應用程式時很多情況下需要讓程式只能有一個執行個體運行,實現方法主要是在程式進入點檢查當前執行個體是否正在運行,如執行個體已運行,則退出本次執行。總結了一下,主要有以下三種方式:
1.通過FindWindow尋找指定視窗是否存在,參考代碼如下:
// 尋找是否有執行個體運行<br />HWND hExistWnd = ::FindWindow(NULL,_T("WindowName"));<br />if (!hExistWnd)<br />{<br /> printf("The app is already running...../n");<br /> return FALSE;<br />}
此種方式只限於有視窗的程式,對於無視窗程序或者指定視窗還未建立但執行個體已經存在的程式就無效了。一個更好的方法是通過核心對象---定義一個互斥體來實現。
2.通過定義一個互斥體來確保只有一個執行個體運行,參考代碼如下:
// 定義一個互斥體,確保程式只有一個執行個體在運行<br />HANDLE hMutex=CreateMutex(NULL, FALSE, _T("WindowName"));</p><p>if(!hMutex)<br />{<br /> printf("Failed to CreateMutex().../n")<br /> return FALSE;<br />}</p><p>if(ERROR_ALREADY_EXISTS == GetLastError())<br />{<br /> printf("The app is already running.../n");<br /> CloseHandle(hMutex);<br /> return FALSE;<br />}
3.全域原子方法,在程式進入點檢查指定原子是否存在,若存在則退出程式,若不存在,則在系統原子表中添加原子,用以記錄當前執行個體正在運行,並在程式退出之前刪除改原子,表示該執行個體已退出。參考代碼如下
// 全域原子<br />ATOM g_AtomRAS=0;</p><p>// 程式進入點檢查原子是否存在<br />if (GlobalFindAtom(_T("AtomName")))<br />{<br /> printf("The app is already running.../n");<br /> return FALSE;<br />}<br />else<br />{<br /> // 建立原子<br /> g_AtomRAS=GlobalAddAtom(_T("AtomName"));<br />}
記得在程式退出時將原子刪除// 刪除全域原子<br />GlobalDeleteAtom(g_AtomRAS);</p><p>
採用全域原子的方法相當於是在系統原子表中記錄了程式啟動並執行兩種狀態:運行狀態和非運行狀態。新執行個體在啟動時通過尋找原子的存在與否來判斷程式處於何種狀態,但需要注意一點的是:有些程式在退出的時候由於需要卸載組件釋放資源,但這個過程可能需要一定的時間。如果這個時候運行程式的另一個執行個體,由於之前程式還在運行,根據單一實例原則這個新執行個體會立即退出,而之前執行個體在資源卸載完後也會立即退出。這樣就會造成兩個程式都退出了。所以對於這樣的程式,就需要記錄另外一種狀態:退出狀態,這樣新的執行個體在啟動時能夠知道當前執行個體是否正在退出,若正在退出,則繼續運行當前執行個體。
所以可以在原子表中另外定義一個原子來表示程式處在退出狀態。在視窗WM_DESTROY訊息處理中添加以下代碼:
case WM_DESTROY:<br /> // 添加原子,記錄程式處於退出狀態<br /> g_AtomRAS=GlobalAddAtom(_T("AppClosing"));<br /> // 卸載資源<br /> // TODO:place code here<br /> // 刪除原子<br /> GlobalDeleteAtom(_T("AppClosing"))<br /> PostQuitMessage(0);<br /> break;
在程式入口時候判斷是否有執行個體運行,有則繼續判斷執行個體是否正在退出,從而對三種狀態分別做不同處理。參考代碼如下:
// 定義一個互斥體,確保程式只有一個執行個體在運行<br />HANDLE hMutex=CreateMutex(NULL, FALSE, _T("WindowName")); </p><p> if(!hMutex)<br /> {<br /> printf("Failed to CreateMutex().../n")<br /> return FALSE;<br /> } </p><p> if(ERROR_ALREADY_EXISTS == GetLastError())<br /> {<br /> if(GloalFindAtom(_T("AppClosing")))<br /> {<br /> // 程式正在退出<br /> printf("The app is closing.../")<br /> }<br /> else<br /> {<br /> // 程式正在運行<br /> printf("The app is already running.../n");<br /> CloseHandle(hMutex);<br /> return FALSE;<br /> }<br /> }<br /> // 沒有正在啟動並執行執行個體<br /> .....