开发者

To learn numbers of resources

Delphi Xe, Win7x64

To request a string resource with known number:

Function GuGetSt开发者_JAVA百科rRes(Fn:string;Nom:integer):string;
var 
  h:THandle;
  buffer:array [0..255] of Char;
begin
  Result:='';
  if fileexists(Fn)=false then 
    exit;
  Try
    h:=LoadLibraryEx(pchar(Fn),0,LOAD_LIBRARY_AS_DATAFILE);
    if h=0 then 
      exit;
    if LoadString(h, Nom, buffer, SizeOf(buffer)) > 0 then 
      Result:=string(buffer);
    FreeLibrary(h);
  Except
    Try 
      if h<>0 then 
        FreeLibrary(h);
    except 

    end;
  End;
End;

// Use
Showmessage(GuGetStrRes('c:\windows\system32\shell32.dll',4200));

Question: how to learn ALL numbers of 'string' resources in DLL? For example to receive a array: 11,22,23,24,40000 and so on (they can go not one after another)

Tried so:

...
var 
  dllname, str:string;
begin
  dllname: ='c:\windows\system32\shell32.dll'; 
  str: = ";
  For i: = 0 to 10000 do 
  begin
    str: = GuGetStrRes (dllname, i);
    if str <> " then 
      memo1.lines.add (inttostr (i) + ' - ' +str);
  end;
end;

But for some reason it causes an error (even the design try-except does not help), when i: = 4201 :( When i=0..4200 and >4210, all is OK.


To enumerate the resources strings you must use the EnumResourceNames function passing the RT_STRING type.

check this sample.

{$APPTYPE CONSOLE}

uses
  Classes,
  Windows,
  SysUtils;

function EnumResNameProc(hModule : THandle; lpszType, lpszName : PChar; lParam : longint) : boolean; stdcall;
var
  Id       : LongInt;
  Min      : Integer;
  Max      : Integer;
  Index    : Integer;
  Buffer   : PWChar;
  Stream   : TResourceStream;
  Len      : Word;
begin
 if Longint(lpszName)<65535 then
 begin
    Id:= longint(lpszName);
    Writeln(Format('RT_STRING ID %d',[Id]));
    Min:=(Id - 1) * 16;
    Max:=(Id * 16) - 1;
    Stream:=TResourceStream.CreateFromID(hModule,Id,RT_STRING);
    try
        Buffer:=Stream.Memory;
        for Index:=Min to Max do
        begin
           //determine the length of the string
           Len:=Word(Buffer^);
           if Len>0 then
           begin
             Writeln(Format('  String ID %d',[Index]));
             Inc(Buffer,Len+1);
           end
           else
             Inc(Buffer);
        end;
    finally
       Stream.Free;
    end;
 end
 else
    Writeln(string(lpszName));
  Result := true;
end;


procedure  EnumerateStringResources(const FileName:string);
var
  hModule : Thandle;
  restype : byte;
begin
  hModule := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
  if hModule=0 then exit
  else
  try
     EnumResourceNames(hModule, RT_STRING, @EnumResNameProc, 0);
  finally
     FreeLibrary(hModule);
  end;
end;


begin
  try
    EnumerateStringResources('YourApplication.exe');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  readln;
end.

and the output depending of your resources will be somehitng like this

RT_STRING ID 4080
  String ID 65264
  String ID 65265
  String ID 65266
  String ID 65267
  String ID 65268
  String ID 65269
  String ID 65270
  String ID 65271
  String ID 65272
  String ID 65273
  String ID 65274
  String ID 65275
  String ID 65276
  String ID 65277
  String ID 65278
  String ID 65279
RT_STRING ID 4081
  String ID 65280
  String ID 65281
  String ID 65282
  String ID 65283
  String ID 65284
  String ID 65285
  String ID 65286
  String ID 65287
  String ID 65288
  String ID 65289
  String ID 65290
  String ID 65291
  String ID 65292
  String ID 65293
  String ID 65294
  String ID 65295

UPDATE I updated the answer to reflect the strings id inside of the string table, the strings are grouped together in bundles of 16. So the first bundle contains strings 0 through 15, the second bundle contains strings 16 through 31, and so on. so the formula to calculate the strings id can be determined in this way

Min:=(Id - 1) * 16;
Max:=(Id * 16) - 1;

for more information you can read this article from Raymond Chen The format of string resources

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜