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

使用 Mutex 防止無視窗 Windows 程式重複執行

     編輯:關於C++

前言:單一實例執行的最佳實踐

開發無視窗(Console、Service 或背景工具)Windows 程式時,防止使用者重複啟動多個實例是基本需求。傳統做法使用 FindWindow 檢視窗標題/類別名,但無視窗程式無視窗句柄,且易受竄改影響。本文介紹使用核心物件 Mutex(互斥體) 實現優雅、可靠的單一實例保護。

核心程式碼

在程式進入點(main、WinMain 或 MFC InitInstance)放入以下程式碼:

HANDLE hMutex = CreateMutex(
    NULL,                   // 無安全性屬性
    FALSE,                  // 初始不擁有
    "RunOnlyOneInstance"    // 命名 Mutex,全域可見
);

// 所有進程均可存取此命名 Mutex
if (hMutex == NULL || ERROR_ALREADY_EXISTS == ::GetLastError())
{
    // 程式第二次或之後執行,取得 Mutex 已存在錯誤
    return FALSE; // 直接結束
}

// ... 正常執行主邏輯 ...

// 程式結束前釋放(系統會自動回收,但建議顯式關閉)
CloseHandle(hMutex);

原理說明

  • 命名 Mutex 為核心物件:跨進程可見,作業系統保證同名 Mutex 在系統範圍內唯一。
  • CreateMutex 行為:首次呼叫建立並返回句柄,GetLastError() 為 0;後續呼叫返回現有句柄,GetLastError() 為 ERROR_ALREADY_EXISTS。
  • 自動清理:進程結束時系統自動釋放 Mutex,無殘留風險。

進階:限制同時執行 N 個實例

若需允許最多 N 個實例同時執行(例如授權控制),請改用 Semaphore(信號量):

HANDLE hSem = CreateSemaphore(NULL, N, N, "MyAppInstanceLimit");
if (hSem == NULL || ERROR_ALREADY_EXISTS == ::GetLastError())
{
    // 嘗試等待信號
    if (WaitForSingleObject(hSem, 0) != WAIT_OBJECT_0)
        return FALSE; // 已達上限
}
// ... 執行 ...
ReleaseSemaphore(hSem, 1, NULL); // 釋放一個名額

優勢總結

比起 FindWindow、建立暫存檔、註冊表旗標等方法,Mutex 具備:無視窗需求、核心級同步、自動生命週期管理、跨會話隔離(Global\ 前綴可跨 Terminal Services 會話) 等優勢,是 Windows 單一實例控制的標準解法。

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