Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#2

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 13. Jul 2007, 15:31
Nein geht nicht direkt.

Die einfachste Lösung ist es am Anfang des Strings selber eine Nummer zu speichern. Also so

Delphi-Quellcode:
resourcestring
  sFehler = '123: Fehler bei XYZ aufgetreten';
Bei jedem Zugriff auf einen Resourcestring ist der String ein normaler LongString. Also zum Zeitpunkt wenn die Exception diesen String übergeben bekommt ist es ein LongString und es existiert keine Verbindung mehr zu einer Resource. Das "Laden" der Resourcestrings macht der Laufzeitcode vollständig transparent. Also schon während der Laufzeit wurden die Resourcestring in LongString quasi geladen und konvertiert. Das macht der RTL Code auf Anlass des Compilers zum Zeitpunk der Initialisierung einer Unit, also bevor die Initialization Sektion der Unit aufgerufen wird. Egal ob im Source auch Initialization steht oder nicht, eine Unit hat diese "Initialization Funktion" immer. Und davor werden die Resourcestring real geladen in LongStrings.

Davon abgesehen gilt folgendes: Jeder String der als Resource gespeichert wurde bekommt eine eindeutige ID. Die Vergabe dieser ID macht der Linker vollständig transparent für uns. Dh. jedesmal nach der Deklaration eines neuen Resourcestrings ändern sich ALLE IDs dieser Strings in der Resource. Ein Resourcestring hat also aus Sicht des Programmieres in Delphi keine vorhersagebare und immer gleiche ID in der String-Resource der EXE.

Es gibt einen Weg, definitiv, aber der würde nahe an einem Hack liegen. Der RTL Code der einen Resourcestring lädt muß ja selber wissen welche Resource-ID in der String-Resource der EXE diesem zugeordnet ist. Dazu speichert der Linker eine Tabelle zum Resourcestring ab in der eine Basis-ID drinnensteht. Man kann über Zeigerarithmetik an diese "Tabelle" rankommen und so auch an die IDs der Resourcestrings. Damit weist DU aber eben noch nicht welcher reale String, eg. Text, sich hinter dieser ID verbirgt. Kompiliert man neu so kann es durchaus sein das sich diese ID zum Text ändert.

[edit]
Schau mal in Unit System.pas, da findest du

Delphi-Quellcode:
type
  PResStringRec = ^TResStringRec;
  TResStringRec = packed record
    Module: ^Longint;
    Identifier: Integer;
  end;

procedure Test;
resourcestring
  sTest = 'Test String Resource';
var
  Msg: PResStringRec;
begin
  Msg := @sTest;
  
  ShowMessage(LoadResString(Msg));
end;
Der Resourcestring wird also als Zeiger vom Typ PResStringRec angesprochen, eg. konvertiert. Das Member .Indetifier enthält entwerder die reale Resource ID des zugehörigen Strings aus der Resource der EXE oder den LongString selber. Sollte .Identifier < $10000 sein, sprich das höherwertige Word des Cardinals = 0 sein, so ist es eine Resource ID. Der String muß dann aus der EXE geladen werden. Danach wird .Identifier aber als Zeiger eines LongString abgesprochen. Dh. beim Zugriff auf einen Resourcestring wird nur beim 1. mal der String aus der EXE geladen, danach steht er fertig im Speicher und wird nicht mehr nachgeladen.

Schau dir die Implementierung in Unit System.pas von LoadResString() genauer an.

[/edit]

Gruß Hagen
  Mit Zitat antworten Zitat