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

VC++ 6.0 控制應用程式單一執行實例:共享記憶體 DLL 方案完整實作

     編輯:VC 教學

問題背景

Win32 環境下 hPrevInstance 恆為 NULL,無法像 16 位元時代直接判斷前一實例。對話框程式可用 FindWindow,但無視窗程式(服務、背景工具)則無法適用。透過 MFC Extension DLL 共享資料段 可實現跨進程計數,通用於所有類型應用程式。

實作步驟

1. 建立 MFC Extension DLL 專案

  • 專案類型:MFC AppWizard (dll) → 選擇 MFC Extension DLL (using shared MFC DLL)。
  • 命名為 Single。

2. 定義共享資料段與導出函數

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;
}

3. 應用程式端呼叫

  • 在 DLL 中新增泛型類別 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;
}

4. 部署

編譯產生 Single.dll 複製至 Windows\System32 目錄(或應用程式同目錄),確保所有實例載入同一份 DLL。

原理解析

關鍵點說明
#pragma data_seg指定命名資料段,連結器將其標記為 SHARED
.def SECTIONS設定段屬性 READ WRITE SHARED,實現跨進程單一副本
DllMain 計數每個進程載入 DLL 時遞增,卸載時遞減(參考計數)
JudgeNo()應用程式啟動時讀取計數,>0 表示已有實例

優缺點與注意事項

  • ✅ 適用於無視窗程式、服務、主控台應用程式。
  • ✅ 無需建立具名 Mutex,邏輯簡單。
  • ⚠️ DLL 必須放在系統路徑或應用程式目錄,確保所有實例載入同一份。
  • ⚠️ 若進程異常終止未執行 DLL_PROCESS_DETACH,計數可能不準;生產環境建議搭配 Mutex 雙重保險。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved