如何更改存储在.exe文件中的StringTable值 [英] How to Change StringTable Values stored in a .exe file
问题描述
我已经编写了2个程序,它们均已编译,并且都包含通过.rc文件添加的 STRINGTABLES资源。
I have written 2 programs, they are both compiled, and both contain "STRINGTABLES" resources added via .rc files.
因此,我们将其称为App#1 appp.exe和App#2 app2.exe。
So, let's call App #1 "app1.exe" and App #2 "app2.exe".
这是我的问题。在app2.exe中,我有一个字符串表,如下所示:
Here is my issue. In app2.exe, I have a string table that looks like this:
STRINGTABLE
{
1000, "Hello"
1001, "There"
}
当我跑步时app1.exe,我试图通过Win32 API UpdateResource()
函数更新app2.exe中存储的资源。
When I run app1.exe, I am attempting to update resources stored in app2.exe via the Win32 API UpdateResource()
function.
我可以使用Delphi的 LoadStr()
函数从字符串表中加载字符串。
I can use Delphi's LoadStr()
function to load the strings from the stringtable just fine.
我的问题我需要了解如何使用 UpdateResource()
来更改该字符串表中的 JUST THE STRINGS 。因此,例如,我希望app1.exe将app2.exe的字符串表从上面看到的更改为此:
My problem is I need to understand how to use UpdateResource()
in order to change JUST THE STRINGS in that stringtable. So, for example, I want app1.exe to change app2.exe's string table from what you see above to this:
STRINGTABLE
{
1000, "Thank"
1001, "You!"
}
对不起,我没有任何源代码,但是我开始
I am sorry that I do not have any source code, however I am starting from scratch and cannot seem to figure this out.
我正在使用RAD Studio XE7。
I am using RAD Studio XE7.
如果你们需要更多操作,请这样说,我将尽可能地对此进行更新,但是就像我说的那样,我刚开始学习有关 TResourceStream
和所有这些资源的东西,因此我没什么可显示的。我只能告诉你的是,我对编程并不陌生。我很快就掌握了东西。我已经创建了一个 THandle
,并获取了app1.exe来研究app2.exe的资源。我可以向其中添加内容,但似乎当我尝试从 TEdit
或<$添加 String
数据时c $ c> TMemo 组件,它在app2.exe的资源中显示为一些奇怪的奇怪的中文字母。因此,我想知道如何格式化这些字符串,以便它们在资源和内容中正确显示。
If you guys need more to go on, just say so and I will update this as much as possible, but like I said I am just starting out learning about TResourceStream
and all this resource stuff so I don't have much to show. All I can tell you is that I am not new to programming. I catch on to stuff very quickly. I have already created a THandle
and gotten the app1.exe to look into the app2.exe's resources. I can add stuff to it, but it seems that when I try to add String
data from a TEdit
or TMemo
component it shows up as some weird strange Chinese lettering inside the app2.exe's resources. So I am wondering how to format these strings so that they show up properly inside the resources and stuff.
要在运行app1.exe时对此进行更多说明并尝试将字符串 Hello
输入到app2.exe的字符串表中,它为我提供了以下内容:
To shed some more light on this, when I run app1.exe and attempt to enter the string "Hello"
into app2.exe's stringtable, it gives me this:
00230BF8 00 00 00 00 ••••
任何线索为何?
运行程序后,我正在使用一个名为 Resource Hacker的应用程序来检查资源。
I am using an app called "Resource Hacker" to check the resources after I run the programs.
推荐答案
字符串表资源存储在16个块中,每个项目都写有一个字长的长度标记和随后的UTF-16编码字符。如果块中的某个项目没有在原始RC文件中明确定义,则该项目仍在已编译资源中,但是长度为0。
String table resources are stored in blocks of 16, each item written with a word-sized length marker and the UTF-16 encoded characters following on. If an item in a block isn't explicitly defined in the original RC file, then it's still there in the compiled resource, but with a length of 0.
因此,假设您已经仔细选择了ID,以将其包含在同一组16中。我将继续使用您提供的ID,并假设您要在与该目录相同的目录中更新一个名为TestLib.dll的DLL。可执行程序;我还将假设自己的语言环境(英语)-您需要根据需要更改 MAKELANGID
参数:
So, let's assume you've carefully chosen your IDs to be in the same group of 16. I'll stick with the IDs you've given, and assume you're wanting to update a DLL called TestLib.dll in the same directory as the EXE; I'll also assume my own locale (British English) - you'll need to change the MAKELANGID
arguments as necessary:
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;
这篇关于如何更改存储在.exe文件中的StringTable值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!