檔案版本資訊(版本號、描述、作者、版權等)讓安裝程式能判斷覆蓋策略、多語系環境選擇正確語言、防止重複安裝、運行時驗證版本、顯示於「關於」對話框、線上更新檢查。Windows 透過 VERSION.DLL 提供 API:GetFileVersionInfoSize、GetFileVersionInfo、VerQueryValue、VerLanguageName 等。
function GetFileVersionInfoSize(lptstrFilename: PChar; var lpdwHandle: DWORD): DWORD; stdcall;
// 回傳版本資源大小(位元組),失敗回傳 0
function GetFileVersionInfo(lptstrFilename: PChar; dwHandle: DWORD; dwLen: DWORD; lpData: Pointer): BOOL; stdcall;
// 將版本資源複製至緩衝區 lpData,dwLen 需 >= GetFileVersionInfoSize 回傳值
function VerQueryValue(pBlock: Pointer; lpSubBlock: PChar; var lplpBuffer: Pointer; var puLen: UINT): BOOL; stdcall;
// 從版本資源區塊查詢特定值,lpSubBlock 格式:
// "\" 根區域 → VS_FIXEDFILEINFO
// "\VarFileInfo\Translation" → 語言/代碼頁陣列
// "\StringFileInfo\lang-codepage\string-name" → 字串值(如 FileVersion, CompanyName)
function VerLanguageName(wLang: DWORD; szLang: PChar; nSize: DWORD): DWORD; stdcall;
// 語言識別碼轉換為描述字串(如 0x0404 → "繁體中文")
預定義字串名稱:Comments, InternalName, ProductName, CompanyName, LegalCopyright, ProductVersion, FileDescription, LegalTrademarks, PrivateBuild, FileVersion, OriginalFilename, SpecialBuild。
步驟 1:專案選項填寫版本資訊(Shift+Ctrl+F11,Version Info 頁面勾選 Include Version Information,填入上述預定義欄位)。
步驟 2:關於對話框 OnCreate 事件代碼:
const InfoNum = 9;
InfoStr: array[1..InfoNum] of String = (
'ProductName', 'ProductVersion', 'FileDescription', 'LegalCopyright',
'FileVersion', 'CompanyName', 'LegalTradeMarks', 'InternalName', 'OriginalFileName');
var S: String; BufSize, Len: DWORD; Buf, Value: PChar;
begin
S := Application.ExeName;
BufSize := GetFileVersionInfoSize(PChar(S), BufSize);
if BufSize > 0 then
begin
Buf := AllocMem(BufSize);
GetFileVersionInfo(PChar(S), 0, BufSize, Buf);
// 080403A8 = 語言代碼頁(繁體中文 CP950),需根據實際資源調整
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[1]), Pointer(Value), Len) then
ProductName.Caption := Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[2]), Pointer(Value), Len) then
ProductVersion.Caption := '產品版本: ' + Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[3]), Pointer(Value), Len) then
FileDescription.Caption := '檔案說明: ' + Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[4]), Pointer(Value), Len) then
LegalCopyright.Caption := '合法版權: ' + Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[5]), Pointer(Value), Len) then
FileVersion.Caption := '檔案版本: ' + Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[6]), Pointer(Value), Len) then
CompanyName.Caption := '公司名稱: ' + Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[7]), Pointer(Value), Len) then
LegalTrademarks.Caption := '合法商標: ' + Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[8]), Pointer(Value), Len) then
InternalName.Caption := '內部名稱: ' + Value;
if VerQueryValue(Buf, PChar('\StringFileInfo\080403A8\' + InfoStr[9]), Pointer(Value), Len) then
OriginalFilename.Caption := '原始檔名: ' + Value;
FreeMem(Buf, BufSize);
end
else
begin
Application.MessageBox('讀取版本資訊失敗,請重新啟動。', '錯誤', MB_OK + MB_ICONSTOP);
Application.Terminate;
end;
end;
GetFileVersionInfoSize → AllocMem → GetFileVersionInfo → VerQueryValue → FreeMem080403A8)必須與資源編譯器產生的值一致,可透過 \VarFileInfo\Translation 動態查詢此技術讓應用程式具備專業級的版本管理與顯示能力,是部署與維護的基礎設施。