我試圖查詢安裝程序安裝的文件的版本詳細信息,並將其與正在執行的安裝程序中存在的同一文件的版本詳細信息進行比較。細節並不在文件版本或領域的ProductVersion,但可以像INTERNALNAME等在運行時從可執行文件查詢版本信息
等領域我看到的Win32 API解決這一點,也有一些示例代碼,如:
但是,這些代碼示例中使用的某些數據類型不適用於Inno Setup。此外,一些樣本和描述似乎表明,語言和代碼頁本身將是一個數組,但一些樣本使用它,假設只有一個條目用於語言和代碼頁。 我被困在試圖找到語言和代碼頁,並根據下面的評論,我硬編碼它爲我們。
我看到this答案,它有一個代碼示例Inno Setup Pascal,但語言和代碼頁計算不基於lplpBufferCP變量,這讓我懷疑它的正確性。
是否可以從Inno Setup Pascal腳本中讀取通用版本信息屬性?如果是這樣,請幫助解決如何查找語言和代碼頁值。
下面列出了基於上述解決方案編寫的代碼,其中包含有問題的部分的在線註釋。
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function GetFileVersionInfoSize(lptstrFilename: String; lpdwHandle: Integer): Integer;
external 'GetFileVersionInfoSize{#AW}@version.dll stdcall delayload';
function GetFileVersionInfo(lptstrFilename: String; dwHandle, dwLen: Integer; var lpData: Byte): Boolean;
external 'GetFileVersionInfo{#AW}@version.dll stdcall delayload';
function VerQueryValue(var pBlock: Byte; lpSubBlock: String; var lplpBuffer: Byte; var puLen: Integer): Boolean;
external 'VerQueryValue{#AW}@version.dll stdcall delayload';
function GetFileVersionProperty(const FileName, PropertyName: String): String;
var
VerSize: Integer;
VerInfo: array of Byte;
Dummy: Integer;
InternalNameArr: array of Byte;
begin
Result := '';
if not FileExists(FileName) then
begin
Log('File ' + FileName + ' does not exist');
Exit;
end;
VerSize := GetFileVersionInfoSize(FileName, 0);
if not VerSize > 0 then
begin
Log('File ' + FileName + ' has no version information');
Exit;
end;
SetArrayLength(VerInfo, VerSize);
if not GetFileVersionInfo(FileName, 0, VerSize, VerInfo[0]) then
begin
Log('Failed to get version info for ' + FileName);
Exit;
end;
if not GetFileVersionInfo(FileName, 0, VerSize, VerInfo[0]) then
begin
Log('Failed to get version info for ' + FileName);
Exit;
end;
{ Getting 'Version size = 2156' }
Log(Format('Version size = %d', [VerSize]));
{ Hard coded value just for testing }
SetArrayLength(InternalNameArr, 512);
{ 040904E4 hard coded for en-us }
{ Is this the correct way of querying the details ? }
{ If not, what needs to be done here }
{ TODO : InternalName hard coded. Use parameter PropertyName }
if VerQueryValue(VerInfo[0], '\StringFileInfo\040904E4\InternalName', InternalNameArr[0], Dummy) then
begin
Log('Failed to query internal name of ' + FileName);
Exit;
end
else
begin
{ What needs to be done here to convert an array of byte to string ? }
{ Do I need to iterate over the array and do the conversion ?}
{ The following does not work because of SetString() being unavailable : }
{ InternalName = SetString(AnsiStr, PAnsiChar(@InternalNameArr[0]), Len);}
{ Getting 'ProductName = 0000' and 'Dummy = 0' }
Log(Format('ProductName = %d%d', [InternalNameArr[0], InternalNameArr[1], InternalNameArr[2], InternalNameArr[3]]));
Log(Format('Dummy = %d', [Dummy]));
end;
{ TODO : Populate Result with appropriate value }
end;
的替代方法可以保存在註冊表中的安裝文件的文件屬性(我感興趣的文件11個屬性),並在安裝程序中可用的屬性中靜態的新文件。
那麼你是否嘗試了@Jens A. Koch的代碼? –
你究竟需要什麼?這是你的可執行文件,對嗎?所以你知道它使用它的資源是什麼語言和代碼頁,不是嗎? –
也許您可以向我們展示可執行文件版本信息的轉儲,以使您的問題更加清晰。 –