Win32 環境下 hPrevInstance 恆為 NULL,無法像 16 位元時代直接判斷前一實例。對話框程式可用 FindWindow,但無視窗程式(服務、背景工具)則無法適用。透過 MFC Extension DLL 共享資料段 可實現跨進程計數,通用於所有類型應用程式。
Single。Single.cpp:
#pragma data_seg(".SharedData")
long m_nRun = -1; // 共享計數器,初始 -1
#pragma data_seg()
// Single.def 設定段屬性
SECTIONS
.SharedData READ WRITE SHARED
// 導出函數
EXPORTS
JudgeNo @1
JudgeNo 實作:
long JudgeNo() { return m_nRun; }
DllMain 計數邏輯:
BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID) {
if (reason == DLL_PROCESS_ATTACH) {
m_nRun++; // 每次進程載入 DLL 計數 +1
}
return TRUE;
}
COut,標頭檔宣告 long JudgeNo();。Out.h 複製至應用程式專案,設定專案相依性。InitInstance() 最前端檢查:
#include "Out.h"
BOOL CMyApp::InitInstance() {
if (JudgeNo() > 0) { // 已有其他實例運行
AfxMessageBox(_T("程式已在執行中!"), MB_OK | MB_ICONINFORMATION);
return FALSE;
}
// 正常初始化...
return TRUE;
}
編譯產生 Single.dll 複製至 Windows\System32 目錄(或應用程式同目錄),確保所有實例載入同一份 DLL。
| 關鍵點 | 說明 |
|---|---|
| #pragma data_seg | 指定命名資料段,連結器將其標記為 SHARED |
| .def SECTIONS | 設定段屬性 READ WRITE SHARED,實現跨進程單一副本 |
| DllMain 計數 | 每個進程載入 DLL 時遞增,卸載時遞減(參考計數) |
| JudgeNo() | 應用程式啟動時讀取計數,>0 表示已有實例 |
DLL_PROCESS_DETACH,計數可能不準;生產環境建議搭配 Mutex 雙重保險。