互斥體核心層面作業系統物件,跨語言、跨編譯器、跨進程邊界通用。CreateMutex 參數:
lpMutexAttributes:安全屬性,NULL=不可繼承bInitialOwner:FALSE=建立者不立即擁有lpName:全系統唯一名稱,建議格式 Global\\AppName_GUIDHANDLE hMutex = CreateMutex(NULL, FALSE, szUniqueName);
if (hMutex == NULL) {
// 建立失敗 (權限/資源不足)
ExitProcess(1);
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
// 已有同名互斥體 = 已有實例在執行
CloseHandle(hMutex);
// 可選:尋找既有視窗並置前
ExitProcess(0);
}
// 首次實例,繼續執行...
// 程式結束前 CloseHandle(hMutex);
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow) {
const char* MUTEX_NAME = "Global\\MyVCApp_UniqueID_{12345678-ABCD-EF01-2345-6789ABCDEF00}";
HANDLE hMutex = CreateMutex(NULL, FALSE, MUTEX_NAME);
if (hMutex == NULL) {
MessageBox(NULL, "建立互斥體失敗", "錯誤", MB_OK | MB_ICONERROR);
return 1;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
MessageBox(NULL, "程式已在執行中!", "提示", MB_OK | MB_ICONINFORMATION);
CloseHandle(hMutex);
return 0;
}
// 首次實例主邏輯
MessageBox(NULL, "首次啟動成功", "歡迎", MB_OK);
// 模擬主迴圈
Sleep(5000);
CloseHandle(hMutex);
return 0;
}
// MyApp.cpp
BOOL CMyApp::InitInstance() {
const TCHAR* MUTEX_NAME = _T("Global\\MyMFCApp_{GUID}");
m_hMutex = CreateMutex(NULL, FALSE, MUTEX_NAME);
if (GetLastError() == ERROR_ALREADY_EXISTS) {
// 找到既有主視窗並置前
CWnd* pWnd = CWnd::FindWindow(_T("MyMainFrameClass"), NULL);
if (pWnd) {
CWnd* pPopup = pWnd->GetLastActivePopup();
if (pWnd->IsIconic()) pWnd->ShowWindow(SW_RESTORE);
pPopup->SetForegroundWindow();
}
CloseHandle(m_hMutex);
return FALSE;
}
// ... 正常初始化 ...
return TRUE;
}
int CMyApp::ExitInstance() {
if (m_hMutex) CloseHandle(m_hMutex);
return CWinApp::ExitInstance();
}
program OnlyOneInstance;
uses
Windows, Forms, SysUtils, uMain in 'uMain.pas' {FormMain};
{$R *.res}
var
hAppMutex: THandle;
MutexName: string;
begin
MutexName := 'Global\MyDelphiApp_UniqueID_{GUID}';
// 必須在 Application.Initialize 之前建立互斥體
hAppMutex := CreateMutex(nil, False, PChar(MutexName));
if (hAppMutex = 0) then begin
MessageBox(0, '建立互斥體失敗!', '錯誤', MB_OK + MB_ICONERROR);
Exit;
end;
if GetLastError = ERROR_ALREADY_EXISTS then begin
MessageBox(0, '程式已在執行中!', '提示', MB_OK + MB_ICONINFORMATION);
CloseHandle(hAppMutex);
Exit;
end;
Application.Initialize;
Application.CreateForm(TFormMain, FormMain);
Application.Run;
// 正常結束釋放
CloseHandle(hAppMutex);
end.
| 項目 | 說明 |
|---|---|
| 名稱唯一性 | 使用 GUID + Global\\ 前綴,避免衝突並支援終端機多 Session |
| 建立時機 | 越早越好:WinMain 進入點 / MFC InitInstance 最前 / Delphi .dpr 開頭 |
| 錯誤碼檢查時機 | 緊接著 CreateMutex 呼叫 GetLastError,中間不可插入其他 API 呼叫 |
| 釋放時機 | 進程正常結束前 CloseHandle;異常結束 OS 會自動釋放 |
| 跨 Session 隔離 | 無 Global\\ 前綴時,各 Terminal Services Session 互斥體獨立 |
| 惡意阻斷防護 | 數位簽章驗證 + 互斥體名稱加密/混淆,防止惡意程式預先建立同名互斥體 |
若需「雙擊關聯檔案 → 傳遞參數給主實例」:
\\.\pipe\MyApp_CmdPipe 執行緒監聽掌握具名互斥體單一實例模式,您的 VC++ 與 Delphi 程式都將具備專業級的進程管理能力。