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

取得執行檔版本資訊:GetFileVersionInfo API 完整實作

     編輯:關於C++

前言:版本資源與 API

Windows 執行檔 (.exe/.dll/.ocx) 內建 **版本資源 (VS_VERSION_INFO)**,包含檔案版本、產品版本、公司名稱、著作權等中繼資料。GetFileVersionInfo 系列 API 可在執行期讀取這些資訊,常用於自動更新檢查、診斷日誌、關於對話框顯示。

完整實作函數 (C++Builder)

String __fastcall TForm1::GetFileVersion(String FileName)
{
    String asVer = "";
    DWORD dwHandle = 0;
    UINT  uiSize = 0;

    // 1. 取得版本資源大小
    DWORD dwVerSize = GetFileVersionInfoSize(FileName.c_str(), &dwHandle);
    if (dwVerSize == 0) return asVer; // 無版本資源

    // 2. 分配緩衝區並讀取版本資源
    std::vector buf(dwVerSize);
    if (!GetFileVersionInfo(FileName.c_str(), dwHandle, dwVerSize, buf.data()))
        return asVer;

    // 3. 查詢固定檔案資訊 (VS_FIXEDFILEINFO)
    VS_FIXEDFILEINFO *pInfo = NULL;
    UINT uiLen = 0;
    if (VerQueryValue(buf.data(), "\\", (LPVOID*)&pInfo, &uiLen) && pInfo)
    {
        // dwFileVersionMS: 高字=主版本, 低字=次版本
        // dwFileVersionLS: 高字=建置編號, 低字=修訂編號
        asVer = IntToStr(HIWORD(pInfo->dwFileVersionMS)) + "." +
                IntToStr(LOWORD(pInfo->dwFileVersionMS)) + "." +
                IntToStr(HIWORD(pInfo->dwFileVersionLS)) + "." +
                IntToStr(LOWORD(pInfo->dwFileVersionLS));
    }
    return asVer; // 格式: "1.2.3.4"
}

API 流程圖解

  1. GetFileVersionInfoSize → 取得資源大小 (bytes)
  2. 配置記憶體緩衝區
  3. GetFileVersionInfo → 將版本資源複製至緩衝區
  4. VerQueryValue(buf, "\\", ...) → 取得 VS_FIXEDFILEINFO 結構指標
  5. 解析 dwFileVersionMS/LS 四個 16-bit 欄位組合版本號

擴充:取得字串資訊 (公司、說明、著作權等)

// 查詢字串表 (語言/代碼頁相關)
struct LANGANDCODEPAGE { WORD wLanguage; WORD wCodePage; } *lpTranslate;
UINT cbTranslate;
VerQueryValue(buf.data(), "\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate);

for (UINT i=0; i < cbTranslate/sizeof(LANGANDCODEPAGE); ++i) {
    AnsiString subBlock = "\\StringFileInfo\\" + 
        IntToHex(lpTranslate[i].wLanguage, 4) + IntToHex(lpTranslate[i].wCodePage, 4) + "\\";
    
    char *pValue; UINT len;
    if (VerQueryValue(buf.data(), (subBlock + "CompanyName").c_str(), (LPVOID*)&pValue, &len))
        ShowMessage("Company: " + String(pValue));
    // 同理:FileDescription, FileVersion, InternalName, LegalCopyright, OriginalFilename, ProductName, ProductVersion...
}

常見問題排查

  • 回傳空字串:檔案無版本資源、路徑錯誤、檔案鎖定
  • 版本號不符預期:專案選項 Version Info 未啟用或欄位未填寫
  • 64-bit 應用讀取 32-bit 檔案:API 支援跨架構讀取,無需特別處理

現代替代:C++17 filesystem (僅檔案時間/大小)

標準庫 std::filesystem::file_time_type 無法讀取版本資源,仍需 Win32 API。

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