我编写了2个程序,它们都已编译,并且都包含通过.rc文件添加的“STRINGTABLES”资源。
所以,让我们调用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()
来更改该字符串表中的 JUST THE STRINGS 。因此,例如,我希望app1.exe将app2.exe的字符串表从您上面看到的更改为:
STRINGTABLE
{
1000, "Thank"
1001, "You!"
}
对不起,我没有任何源代码,但是我从头开始,似乎无法解决这个问题。
我正在使用RAD Studio XE7。
如果你们还需要更多的话,那就说出来,我会尽可能地更新这个,但就像我说我刚刚开始学习TResourceStream
以及所有这些资源所以我不知道有很多东西要展示。我可以告诉你的是,我不是编程新手。我很快就抓住了东西。我已经创建了一个THandle
并获得了app1.exe以查看app2.exe的资源。我可以添加内容,但似乎当我尝试从String
或TEdit
组件添加TMemo
数据时,它会显示为app2.exe中的一些奇怪的中文字母资源。所以我想知道如何格式化这些字符串,以便它们在资源和内容中正确显示。
为了更多地了解这一点,当我运行app1.exe并尝试将字符串"Hello"
输入到app2.exe的字符串表中时,它给了我这个:
00230BF8 00 00 00 00 ••••
任何线索为什么?
我在运行程序后使用名为“Resource Hacker”的应用程序检查资源。
答案 0 :(得分:7)
字符串表资源以16个块的形式存储,每个项目使用字大小的长度标记和后面的UTF-16编码字符写入。如果块中的项目未在原始RC文件中明确定义,则它仍然在编译资源中,但长度为0。
所以,让我们假设你已经仔细选择了你的身份证明属于同一组16岁。我会坚持你已经给出的身份证,并假设你&#39 ;想要在与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;