2014-09-28 46 views
-1

我編寫了2個程序,它們都是編譯的,都包含通過.rc文件添加的「STRINGTABLES」資源。如何更改.exe文件中存儲的StringTable值

因此,讓我們調用App#1「app1.exe」和App#2「app2.exe」。

這是我的問題。在app2.exe,我有一個字符串表看起來像這樣:

STRINGTABLE 
{ 
1000, "Hello" 
1001, "There" 
} 

當我運行app1.exe,我試圖通過更新Win32 API的UpdateResource()功能存儲在app2.exe資源。

我可以使用Delphi的LoadStr()函數從字符串表中加載字符串就好了。

我的問題是我需要了解如何使用UpdateResource()爲了更改只是字符串中的字符串。因此,舉例來說,我想app1.exe到app2.exe的字符串表從您在上面看到這個什麼改變:

STRINGTABLE 
{ 
1000, "Thank" 
1001, "You!" 
} 

我很抱歉,我沒有任何的源代碼,但是我從頭開始似乎無法弄清楚這一點。

我正在使用RAD Studio XE7。

如果你們需要更多的繼續,只是這樣說,我會盡可能更新,但就像我說我剛開始學習TResourceStream和所有這些資源的東西,所以我沒有太多以顯示。我只能告訴你,我對編程並不陌生。我很快接觸到了東西。我已經創建了一個THandle並獲得了app1.exe來查看app2.exe的資源。我可以添加東西,但似乎當我嘗試從TEditTMemo組件添加String數據時,它顯示爲app2.exe資源中的一些奇怪的奇怪中文字。所以我想知道如何格式化這些字符串,以便它們在資源和內容中正確顯示。

爲了進一步瞭解這方面的一些更多的光線,當我運行app1.exe並嘗試輸入字符串"Hello"到app2.exe的STRINGTABLE,它給了我這樣的:

00230BF8 00 00 00 00          •••• 

任何線索,爲什麼?

我正在使用名爲「Resource Hacker」的應用程序在運行程序後檢查資源。

+0

搜索關於執行此操作的教程。有人想知道爲什麼你把字符串放在可執行文件中,如果你希望它們是可變的。 – 2014-09-28 18:20:35

+0

否則,如果你需要幫助你的代碼,你需要顯示它 – 2014-09-28 18:29:57

+0

沒關係。如果你不能在問題中顯示代碼,那麼我無法提供幫助。 – 2014-09-28 19:11:12

回答

6

字符串表資源存儲在16個塊中,每個項目使用字長度標記和UTF-16編碼字符進行編碼。如果塊中的項目沒有在原始RC文件中明確定義,那麼它仍然存在於編譯資源中,但長度爲0.

因此,讓我們假設您已仔細選擇了您的ID在同一組中,我將堅持使用您提供的ID,並假定您想在EXE所在的同一目錄中更新名爲TestLib.dll的DLL;我還會假設我自己的語言環境(英式英語) - 您需要根據需要更改MAKELANGID參數:

const 
    LibName = 'TestLib.dll'; 
    ID_FIRST = 1000; 
    ID_SECOND = 1001; 

function StringIDToGroupID(ID: UINT): UINT; inline; 
begin 
    Result := (ID shr 4) + 1; 
end; 

procedure UpdateStrings(const NewFirst, NewSecond: string); 
var 
    Handle: THandle; 
    GroupID: UINT; 
    Stream: TCustomMemoryStream; 
    GroupStrings: array[0..15] of string; 
    StrLen: Word; 
    I: Integer; 
begin 
    GroupID := StringIDToGroupID(ID_FIRST); 
    //get existing data... 
    Handle := LoadLibraryEx(LibName, 0, LOAD_LIBRARY_AS_DATAFILE); 
    if Handle = 0 then RaiseLastOSError; 
    try 
    Stream := TResourceStream.CreateFromID(Handle, GroupID, RT_STRING); 
    try 
     for I := Low(GroupStrings) to High(GroupStrings) do 
     begin 
     Stream.ReadBufferData(StrLen); 
     SetLength(GroupStrings[I], StrLen); 
     Stream.ReadBuffer(PChar(GroupStrings[I])^, StrLen * SizeOf(Char)); 
     end; 
    finally 
     Stream.Free; 
    end; 
    finally 
    FreeLibrary(Handle); 
    end; 
    //update the strings we're interested in... 
    GroupStrings[ID_FIRST mod Length(GroupStrings)] := NewFirst; 
    GroupStrings[ID_SECOND mod Length(GroupStrings)] := NewSecond; 
    Stream := TMemoryStream.Create; 
    try 
    for I := Low(GroupStrings) to High(GroupStrings) do 
    begin 
     StrLen := Length(GroupStrings[I]); 
     Stream.WriteData(StrLen); 
     Stream.WriteBuffer(PChar(GroupStrings[I])^, StrLen * SizeOf(Char)); 
    end; 
    //update DLL... 
    Handle := BeginUpdateResource(LibName, False); 
    if Handle = 0 then RaiseLastOSError; 
    try 
     UpdateResource(Handle, RT_STRING, PChar(GroupID), 
     MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), Stream.Memory, Stream.Size); 
    finally 
     EndUpdateResource(Handle, False); 
    end; 
    finally 
    Stream.Free; 
    end; 
end; 
+0

非常感謝你的詳細解釋:)我得到它的工作和編輯,以我的喜好。我現在就繼續接受你的回答,男人我不能夠感謝你!非常感激 :) – TheBitmasterXor 2014-09-28 20:22:45

相關問題