首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

讓 MFC 應用程式只能執行單一實例:使用 Mutex 同步物件

     編輯:VC 教學

問題背景

在 Windows 上開發應用程式時,常需確保同一時間只有一個實例在執行。若使用者重複點擊捷徑,應直接啟動既有視窗而非開啟新視窗。MFC 專案中,最簡單且可靠的做法是在 CWinApp::InitInstance() 中建立具名 Mutex。

核心程式碼

// 在 CMyApp::InitInstance() 最前面加入
HANDLE hMutexOneInstance = CreateMutex(NULL, TRUE, _T("Global\\MyApp_Unique_Mutex_Name"));
if (GetLastError() == ERROR_ALREADY_EXISTS) {
    // 已有實例在執行
    if (hMutexOneInstance) CloseHandle(hMutexOneInstance);
    // 可選:將既有視窗帶到前景
    CWnd* pWnd = CWnd::FindWindow(_T("MyAppMainWndClass"), NULL);
    if (pWnd) {
        pWnd->SetForegroundWindow();
        if (pWnd->IsIconic()) pWnd->ShowWindow(SW_RESTORE);
    }
    return FALSE; // 結束新實例
}
// 正常初始化流程...
// 程式結束前記得釋放 Mutex(或由系統自動回收)

關鍵細節

  1. Mutex 名稱:建議加上 Global\\ 前綴(需管理員權限)或 Local\\ 確保跨 Session 可見性;名稱應包含 GUID 或公司/產品前綴避免衝突。
  2. bInitialOwner = TRUE:建立時立即擁有,若已存在則 GetLastError() 回傳 ERROR_ALREADY_EXISTS。
  3. 釋放時機:正常結束時呼叫 ReleaseMutex 並 CloseHandle;異常終止時系統會自動釋放。
  4. 啟動既有視窗:結合 FindWindow + SetForegroundWindow 讓使用者感覺「沒有重複開啟」。

常見錯誤

  • 在 InitInstance 之後才檢查 Mutex,導致資源已分配完畢才發現重複。
  • 使用區域變數接收 CreateMutex 回傳值,導致函數結束時 Handle 遺失,無法正確釋放。
  • Mutex 名稱過於簡單(如 "MyApp"),易與其他軟體衝突。

進階:跨使用者 Session 的單一實例

若需跨不同登入使用者仍只能有一個實例(如系統服務),需在 Mutex 名稱加上 Global\\ 並確保建立處理序具備 SE_CREATE_GLOBAL_NAME 權限;一般桌面應用僅需 Local\\ 即可。

結語

使用具名 Mutex 是實現單一實例最標準、最穩健的 Windows API 做法,幾行程式碼即可解決重複啟動問題,並可延伸至跨 Session、帶前景視窗等進階需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved