如何更改存储在.exe文件中的StringTable值 [英] How to Change StringTable Values stored in a .exe file

查看:166
本文介绍了如何更改存储在.exe文件中的StringTable值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆