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

Windows 程式防止多重啟動的四種經典方法

     編輯:組合語言

在 Windows 環境下,雙擊關聯檔案會啟動程式並傳遞路徑參數。多文檔介面(MDI)程式通常要求單一實例:若已運行,新啟動的實例應將參數傳遞給現有實例並自行退出。本文介紹四種防止多重啟動的核心技術。

方法一:FindWindow 尋找視窗標題

szWindowName db "Hello World!",0
invoke FindWindow, NULL, offset szWindowName
.if eax != NULL
  ; 已有實例,傳遞參數並退出
  invoke ExitProcess, 0
.endif

缺點:視窗標題極易重複,不可靠。

方法二:FindWindow 尋找視窗類別名(推薦)

szClassName db "MY_UNIQUE_CLASS_NAME!",0
invoke FindWindow, offset szClassName, NULL
.if eax != NULL
  invoke ExitProcess, 0
.endif

視窗類別名在進程內唯一,通常由 RegisterClassEx 註冊時指定。缺點:無標準視窗(如對話框為主視窗)的程式類別名固定為 #32768,無法區分實例。

方法三:建立 Mutex 互斥體(最通用、推薦)

.data
  szMutex db "Global\\MyApp_Unique_Mutex_Name",0
  hMutex  dd ?
  hInstance dd ?

.code
START:
  invoke GetModuleHandle, NULL
  mov hInstance, eax
  invoke CreateMutex, NULL, TRUE, offset szMutex
  mov hMutex, eax
  invoke GetLastError
  cmp eax, ERROR_ALREADY_EXISTS   ; 互斥體已存在
  jz @F                           ; 跳轉退出
  ; 首次運行:正常啟動
  invoke WinMain, ...
  invoke ReleaseMutex, hMutex     ; 正常結束才釋放
@@:
  invoke ExitProcess, 0

優點:

  • 系統全域可見,跨進程、跨會話(加 Global\\ 前綴)
  • 不依賴視窗結構,適用於服務、控制台、GUI 所有類型
  • 核心物件,自動隨進程終結釋放,無殘留風險

關鍵點:必須用 GetLastError 判斷 ERROR_ALREADY_EXISTS,而非單檢查傳回值(即使已存在也會傳回有效句柄)。

方法四:檔案/登錄/INI 標記法(不推薦)

  • 啟動時建立暫存檔/寫入登錄鍵值/修改 INI 標記
  • 退出時刪除/清零
  • 後續實例檢測存在性決定是否退出

缺點:異常終止(崩潰、強制結束進程)會導致標記殘留,造成誤判;需額外清理機制,複雜度高。

總結建議

方法適用性可靠度推薦等級
視窗標題僅限有標題視窗的 GUI低⭐
視窗類別名標準視窗 GUI中⭐⭐⭐
Mutex 互斥體所有類型(GUI/控制台/服務)高⭐⭐⭐⭐⭐
檔案/登錄標記簡單場景低(殘留風險)⭐⭐

下一篇將探討:檢測到已有實例後,如何將新實例的命令列參數傳遞給現有實例(進程間通訊:WM_COPYDATA、命名管道、共享記憶體等)。

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