首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何更改存储在StringTable文件中的.exe值

如何更改存储在StringTable文件中的.exe值
EN

Stack Overflow用户
提问于 2014-09-28 17:46:45
回答 1查看 1.8K关注 0票数 0

我编写了两个程序,它们都是编译的,都包含通过.rc文件添加的"STRINGTABLES“资源。

因此,让我们将App #1称为"app1.exe“,将App #2称为"app2.exe”。

这是我的问题。在app2.exe中,我有一个字符串表,如下所示:

代码语言:javascript
复制
STRINGTABLE
{
1000, "Hello"
1001, "There"
}

当我运行app1.exe时,我试图通过Win32 API UpdateResource()函数更新app2.exe中存储的资源。

我可以使用Delphi的LoadStr()函数从字符串中加载字符串,非常好。

我的问题是,我需要了解如何使用UpdateResource(),以便只更改该字符串中的字符串。因此,例如,我希望app1.exe将app2.exe的字符串表从上面看到的更改为:

代码语言:javascript
复制
STRINGTABLE
{
1000, "Thank"
1001, "You!"
}

我很抱歉,我没有任何源代码,但我是从零开始,似乎无法理解这一点。

我正在使用XE7。

如果你们还需要做更多的事情,只要说出来,我会尽可能多地更新,但是就像我说过的,我只是刚开始学习TResourceStream和所有这些资源,所以我没有什么可展示的。我能告诉你的是,我对编程并不陌生。我很快就明白了。我已经创建了一个THandle,并获得了app1.exe来查看app2.exe的资源。我可以添加一些内容,但是当我尝试从一个StringTMemo组件中添加TEdit数据时,它会显示为app2.exe资源中一些奇怪的奇怪的中文字母。因此,我想知道如何格式化这些字符串,以便它们在资源和东西中正确地显示出来。

为了进一步了解这一点,当我运行app1.exe并尝试将字符串"Hello"输入app2.exe的可字符串时,它提供了以下内容:

代码语言:javascript
复制
00230BF8  00 00 00 00                                       ••••

有什么线索吗?

运行程序后,我使用一个名为“资源黑客”的应用程序来检查资源。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-28 19:56:36

字符串表资源存储在16块中,每一项都用一个字长标记编写,UTF-16编码字符紧随其后。如果块中的项没有在原始RC文件中显式定义,那么它仍然存在于编译的资源中,但长度为0。

因此,让我们假设您已经仔细地选择了您的ID在同一个16组中。我将继续使用您提供的ID,并假设您希望在与EXE相同的目录中更新一个名为TestLib.dll的DLL;我还将假设我自己的地区(英式英语)--您需要根据需要更改MAKELANGID参数:

代码语言:javascript
复制
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;
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26087756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档