2009-09-30 42 views
2

如何在以下代碼中修改buffer然後保存可執行文件資源中的更改?我正在尋找類似SetString(handle,index,buffer,size)的東西。修改exe文件資源中的字符串

var 
    hExe : Cardinal; 
    buffer : array [0..4097] of ansichar; 
begin 
    hExe:=LoadLibraryEx(PAnsiChar(Edit2.Text),0,LOAD_LIBRARY_AS_DATAFILE); 
    LoadString(hExe,65300,buffer,SizeOf(buffer)); 
    ShowMessage(buffer); 
    //need to modify buffer here then I'll unload the resources.. 
end; 

更新:這是我在UpdateResource

var 
    hEXE: DWORD; 
    pData: PAnsiChar; 
begin 
    pData := PAnsiChar(Edit1.Text); 
    hEXE := BeginUpdateResource(pchar(edit2.text), FALSE); 
    if hEXE <> 0 then 
    begin 
    UpdateResource(hEXE, RT_string, MAKEINTRESOURCE(4082), LANG_NEUTRAL, 
     @pData, Length(pData)); //if i change 4082 to 65300 it creates another key like 4082 
    EndUpdateResource(hEXE, FALSE); 
    end; 

嘗試此代碼打亂了整個4082的內容。問題是RT_STRING中名爲4082的項目是一組字符串。當我打開一個資源編輯器中的exe文件,單擊字符串表,然後4082的結果是:

STRINGTABLE 
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 
{ 
65296, "Unicode" 
65297, "Big Endian Unicode" 
65298, "UTF-8" 
65299, "UTF-7" 
65300, "ABCDE12345" 
} 

所以我要麼需要解析字符串組或者我需要一個API來設置修改字符串中的索引65300組。有任何想法嗎?

回答

6

我使用Google找到了the answer。 (English translation from Chinese)謝謝大家!

procedure UpdateResString(AFileName, ANewString: string; AStringIdent: Integer); 
    procedure WriteToArray(AArray: TByteDynArray; AData: Word; var APos: Integer); 
    begin 
    AArray[APos] := Lo(AData); 
    AArray[APos + 1] := Hi(AData); 
    Inc(APos, 2); 
    end; 

    function ReadFromArray(AArray: TByteDynArray; APos: Integer): Word; 
    begin 
    Result := AArray[APos] + AArray[APos + 1] * 16; 
    end; 

var 
    hModule, hResInfo, hUpdate: THandle; 
    ResData, TempData: TByteDynArray; 
    wsNewString: WideString; 
    iSection, iIndexInSection: Integer; 
    i, iLen, iSkip, iPos: Integer; 
begin 
    hModule := LoadLibrary(PChar(AFileName)); 
    if hModule = 0 then 
    raise Exception.CreateFmt('file %s failed to load.', [AFileName]); 

    // Calculate the resource string area and the string index in that area 
    iSection := AStringIdent div 16 + 1; 
    iIndexInSection := AStringIdent mod 16; 

    // If the resource already exists, then read it out of the original data 
    hResInfo := FindResource(hModule, MakeIntResource(iSection), RT_STRING); 
    if hResInfo <> 0 then 
    begin 
    iLen := SizeOfResource(hModule, hResInfo); 
    SetLength(ResData, iLen); 
    CopyMemory(ResData, LockResource(LoadResource(hModule, hResInfo)), iLen); 
    end; 
    // Should first close the file, and then update 
    FreeLibrary(hModule); 
    // Calculate the new data is written to location 
    wsNewString := WideString(ANewString); 
    iLen := Length(wsNewString); 
    iPos := 0; 
    for i := 0 to iIndexInSection do 
    begin 
    if iPos > High(ResData) then 
     SetLength(ResData, iPos + 2); 
    if i <> iIndexInSection then 
    begin 
     iSkip := (ReadFromArray(ResData, iPos) + 1) * 2; 
     Inc(iPos, iSkip); 
    end; 
    end; 

    // Delete the original data and the data behind the temporary 
    // storage of data to be added 
    iSkip := (ReadFromArray(ResData, iPos) + 1) * 2; 
    TempData := Copy(ResData, iPos + iSkip, Length(ResData) - iSkip); 
    SetLength(ResData, iPos); 
    SetLength(ResData, iPos + (iLen + 1) * 2 + Length(TempData)); 

    // Write new data 
    WriteToArray(ResData, iLen, iPos); 
    for i := 1 to iLen do 
    WriteToArray(ResData, Ord(wsNewString[i]), iPos); 
    // Write back to the original data 
    for i := 0 to High(TempData) do 
    ResData[iPos + i] := TempData[i]; 

    // Write the data back to file 
    hUpdate := BeginUpdateResource(PChar(AFileName), False); 
    if hUpdate = 0 then 
    raise Exception.CreateFmt(
     'cannot write file %s. Please check whether it is open or set read-only.', 
     [AFileName]); 

    UpdateResource(hUpdate, RT_STRING, MakeIntResource(iSection), LANG_NEUTRAL, 
    ResData, Length(ResData)); 
    EndUpdateResource(hUpdate, False); 
end; 
+0

一個評論聲望太低的用戶發佈了一個回答,說「結果:= AArray [APos] + AArray [APos + 1] * 16;'應該是結果:= AArray [APos] + AArray [APos + 1 ] * 16;'。我不知道這是否正確;只是把它放在那裏給你看。 – 2013-06-05 15:39:01

3

你可以看到XN Resource Editorsource code (Delphi 2006)(是一個免費的,功能強大的,功能齊全的資源編輯器和用於Windows 98,Windows 2000和Windows XP的PE模塊瀏覽器)。

除此之外,您還應該檢查以下功能

再見。

+0

XN資源編輯器的要求不能用D2009編譯(給左側無法分配錯誤 - pngimage.pas ln 1845)。我已經嘗試過使用UpdateResource,但我一直在搞亂其他字符串在同一類別。 – 2009-09-30 15:29:24

+0

你不需要編譯你的項目,你可以直接分析代碼。 – RRUZ 2009-09-30 15:35:02

+0

Google是您的朋友http://www.google.com/#hl=zh-CN&safe=off&q=BeginUpdateResource++UpdateResource+EndUpdateResource+delphi+&aq=&aqi=&aq=f&aqi=&oq=BeginUpdateResource++UpdateResource+EndUpdateResource+delphi+ &fp = 3b1e5986dcbf14e4 – RRUZ 2009-09-30 15:39:57

1

我相信你需要使用包含您的修改版本來替代整個組。這並不難解析,你可以採取一些快捷方式。將所有內容加載到tStringlist中,然後循環播放列表,直到字符串以'65300開始'。執行替換並將字符串列表的文本部分保存爲替換資源。