2014-02-12 26 views
5

我在更改可執行文件的版本信息中的內部版本號(VersionLS的低版本)。因此,我應該閱讀VS_VERSIONINFO結構,更改內部版本號,然後將其更新回PE。在可執行文件中更改內部版本號

我使用此代碼作爲基礎工作:https://stackoverflow.com/a/7999813/1970843。此代碼非常適用於更改VS_FIXEDFILEINFO數據,但它不會更改(或訪問)StringFileInfo信息。

我敢肯定,我應該包括在VERSIONHEADER包裝記錄添加VS_VERSIONINFO的兒童進入的東西,但我不知道究竟是如何做到這一點。這是我到目前爲止有:

type 
    StringStruc = Packed Record 
     wLength: Word; 
     wValueLength: Word; 
     wType: Word; 
     //szKey: ?; 
     //Value: ?; 
    End; 

    StringTable = Packed Record 
     wLength: Word; 
     wValueLength: Word; 
     wType: Word; 
     szKey: Array[0..8] Of WideChar; 
     Children: StringStruc; 
    End; 

    StringFileInfo = Packed Record 
     wLength: Word; 
     wValueLength: Word; 
     wType: Word; 
     szKey: Array[0..14] Of WideChar; // 'STRINGFILEINFO' 
     Children: StringTable; 
    End; 

    VERSIONHEADER = Packed Record 
     wLength: Word; 
     wValueLength: Word; 
     wType: Word; 
     szKey: Array[0..16] Of WideChar; // 'VS_VERSION_INFO' 
     Version: VS_FIXEDFILEINFO; 
     Children: StringFileInfo; 
    End; 

... 

var VersionHandle, VersionRes: THandle; 
    VersionSize: Cardinal; 
    Version: Array Of AnsiChar; 
    Ver: ^VERSIONHEADER; 
Begin 
    VersionSize := GetFileVersionInfoSize(PChar(sExe), VersionHandle); 

    SetLength(Version, VersionSize); 
    Ver := Pointer(Version); 
    GetFileVersionInfo(PChar(sExe), 0, VersionSize, Ver); 

因此,信息似乎是正確上來的第一StringStruc。但由於szKey和Value都不是固定大小,我不知道如何正確定義我的Packed Record(甚至有可能?)來獲取這些值。我也遇到了陣列的麻煩......我怎麼定義它們?我正在做的方式,我只是得到每個Struc上的第一個孩子。請注意,我忽略了襯墊......這可以嗎?

任何幫助表示讚賞。我在這裏所做的大部分工作都是通過試驗和錯誤,所以我不太明白髮生了什麼。

PS:我仍然在做這個,所以我可能會經常更新這個帖子。

+0

也許我應該嘗試讀取內存作爲原始二進制數據?當我找到我想要改變的東西時,我需要更新每個父母的信息和大小,並根據需要重新分配內存......聽起來很難。 – GabrielF

+1

對於一個項目,我試圖改變StringFileInfo,但它遠不是明顯的,AFAIR。因此,我堅持改變數字信息(代碼已經鏈接到你的問題:)),並在字符串字段中放置一個通用文本。重要的是「關於」框和啓動畫面(從數字字段提取)中顯示的內容,以及如果文件屬性給出確切的(數字)「文件版本」(例如2.1.231),但更通用的是「產品版本「(例如」2「或」2.1「) - 對我來說足夠了。 –

+0

你不能用'BeginUpdateResource'等來做嗎? –

回答

1

我很感謝您的關注和幫助。我在這裏找到了一個現成的解決方案。事實上,這是在我對這個問題的評論中(我對此感到羞恥!)。

它是基於由Colin Wilson庫。它使用指針算法來提取和寫入信息,所以,很難(也許是唯一)的方式。關於如何使用Jason Penny的圖書館還有一個很好的例子:SetVersion。由於我使用的是D7,我從網上下載here科林·威爾遜的庫(下資源工具),但較新的版本,使用的UnicodeString和更好的指針運算,可here

這是實際執行我現在有:

uses ..., unitResourceVersionInfo, unitPEFile; 

... 

var VersionInfo: TVersionInfoResourceDetails; 
    PEResModule: TPEResourceModule; 
    VersionNumber: ULARGE_INTEGER; 
    sVersion: String; 
    I: Integer; 
Begin 
    PEResModule := TPEResourceModule.Create; 
    Try 
     PEResModule.LoadFromFile(sExe); 

     For I := 0 To PEResModule.ResourceCount - 1 Do Begin 
      If PEResModule.ResourceDetails[I] Is TVersionInfoResourceDetails Then Begin 
       VersionInfo := (PEResModule.ResourceDetails[I] As TVersionInfoResourceDetails); 
       Break; 
      End; 
     End; 

     VersionNumber.LowPart := MakeLong(NewBuildNumber, HiWord(VersionInfo.FileVersion.LowPart)); 
     VersionNumber.HighPart := VersionInfo.FileVersion.HighPart; 
     VersionInfo.FileVersion := VersionNumber; 
     VersionInfo.ProductVersion := VersionNumber; 

     VersionInfo.CodePage := $04e4; 

     sVersion := Format('%d.%d.%d.%d', [HiWord(VersionInfo.FileVersion.HighPart), LoWord(VersionInfo.FileVersion.HighPart), HiWord(VersionInfo.FileVersion.LowPart), LoWord(VersionInfo.FileVersion.LowPart)]); 
     VersionInfo.SetKeyValue('FileVersion', sVersion); 

     PEResModule.SaveToFile(ChangeFileExt(sExe, '.exe2')); 

    Finally 
     FreeAndNil(PEResModule); 
    End; 
End; 

代碼頁行是由於在庫中的錯誤(我相信這是)。它不會讀取代碼頁(自帶0),所以,當你救回來,它顯示爲0。

相關問題