在 Windows 程式開發中,防止使用者重複啟動同一個應用程式是常見需求。與關鍵區段不同,Mutex(互斥物件)屬於核心物件,支援跨進程同步,非常適合實現單一實例應用程式。本文將詳細介紹如何利用 OpenMutex 與 CreateMutex 達到此目的,並提供完整的 Delphi 程式碼範例。
OpenMutex 開啟一個自訂名稱的 Mutex 物件。CreateMutex 建立它,代表這是首次啟動。CloseHandle 釋放 Mutex。function OpenMutex(
dwDesiredAccess: DWORD; { 存取權限 }
bInheritHandle: BOOL; { 是否可被子進程繼承 }
pName: PWideChar { Mutex 物件名稱 }
): THandle; stdcall; { 成功返回句柄,失敗返回 0 }
注意: CreateMutex 的第二個參數(初始擁有權)在這裡不再關鍵,因為判斷依據是 Mutex 的名稱是否已存在。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
hMutex: THandle;
const
NameMutex = 'MyUniqueAppMutex';
procedure TForm1.FormCreate(Sender: TObject);
begin
{ 嘗試開啟已存在的 Mutex }
if OpenMutex(MUTEX_ALL_ACCESS, False, NameMutex) <> 0 then
begin
ShowMessage('程式已在執行中,請勿重複啟動。');
Application.Terminate;
Exit;
end;
{ 建立新的 Mutex,標記為首次啟動 }
hMutex := CreateMutex(nil, False, NameMutex);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
{ 釋放 Mutex 句柄 }
if hMutex <> 0 then
CloseHandle(hMutex);
end;
end.
將檢查邏輯放在專案檔的最前端,可避免後啟動的實例載入表單、初始化資源等無謂動作:
program Project1;
uses
Forms, Windows,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
var
hMutex: THandle;
const
NameMutex = 'MyUniqueAppMutex';
begin
{ 主執行緒入口處檢查 }
if OpenMutex(MUTEX_ALL_ACCESS, False, NameMutex) <> 0 then
begin
MessageBox(0, '程式已在執行中,請勿重複啟動。', '提示', MB_OK or MB_ICONINFORMATION);
Exit;
end;
hMutex := CreateMutex(nil, False, NameMutex);
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
{ 主執行緒出口釋放 }
if hMutex <> 0 then
CloseHandle(hMutex);
end.
Global\{CompanyName-AppName}),避免與其他程式衝突。Global\;僅限當前 Session 則用 Local\(預設)。掌握此技巧,即可輕鬆為 Delphi 應用程式加上「單一實例」保護,提升使用者體驗與系統資源利用率。