Delphi How can i find a resource name from resourc

2019-01-20 15:48发布

问题:

The situation is:

unit abc;

interface

resourcestring
  aabbcc = 'my text here';

implementation

end.

From my application I received error code 'aabbcc'. Is possible to access with error code the resource name aabbcc ?

回答1:

I imagine you're asking for a function with the following signature and behavior:

function GetNamedResourceString(const Name: string): string;

Assert(GetNamedResourceString('aabbcc') = 'my text here');

Resource strings are stored in your program in a string-table resource, where each string has a numeric index. The named identifier you use in your program is not kept anywhere at run time. Therefore, there is no built-in way to take the text 'aabbcc' and discover which string resource it's associated with.

However, there is a way to take the Delphi resourcestring identifier in your code and discover its numeric ID. Type-cast the expression @aabbcc to PResStringRec, and then read its Identifier field. Look at LoadResString in System.pas to see how the RTL uses this information.

You could use the PResStringRec values to build a TDictionary<string, PResStringRec> at run time, and then use that dictionary in implementing the hypothetical GetNamedResourceString function outlined above.

NamedResources := TDictionary<string, PResStringRec>.Create;
NamedResources.Add('aabbcc', PResStringRec(@aabbcc));

function GetNamedResourceString(const Name: string): string;
begin
  Result := LoadResString(NamedResources[Name]);
end;

If I were doing this for a real project, I would probably use a pre-build script to parse an input file to automatically generate the calls to NamedResources.Add from the corresponding resourcestring declarations.



回答2:

Your resourcestring is compiled into a string table resource. These are identified by a numeric identifier. The compiler maintains a map between your declared resourcestring instances, and the numeric identifiers. When you access a resourcestring the compiler knows the numeric identifier, and emits code that uses that identifier. Essentially what you are hoping to do is to be able to map from the name of your resourcestring and the numeric identifier. Unfortunately that map only exists during compilation. It is not contained in the executable.

Your only other hope would be for the compiler to generate RTTI information for resource strings. However, it does not do this, unless I am very much mistaken.

Given these constraints you are going to need to come up with your own mechanism to map between names and resource strings. One possibility is to avoid using the built-in resourcestring, and manage the string table resources, and their identifiers, by your own mechanisms.