AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Alle resourcestrings der aktuellen Exe auflisten
Thema durchsuchen
Ansicht
Themen-Optionen

Alle resourcestrings der aktuellen Exe auflisten

Ein Thema von ImpactMG · begonnen am 13. Jul 2007 · letzter Beitrag vom 17. Jul 2007
Antwort Antwort
Seite 1 von 2  1 2      
ImpactMG

Registriert seit: 11. Jul 2007
16 Beiträge
 
#1

Alle resourcestrings der aktuellen Exe auflisten

  Alt 13. Jul 2007, 15:15
Hallo,

Ist es irgendwie möglich die Liste aller Resourcestrings die im Sourcecode angeführt sind zu bekommen?

Meine Idee: Alle Fehlermeldungen im Programm werden mittels Resourcestring deklariert (damit schön mit SiSulizer übersetzbar). Der Benutzer bekommt vom Exceptionhandler den Identifier des Resourcestrings als Fehlernummer angezeigt. Ich brauche jetzt ein Mapping von allen Resourcestrings auf die Identifier (und/oder zurück), damit ich von der Fehlernummer aus erkennen kann welcher Resourcestring es war, und welche Stelle im Sourcecode betroffen ist.

Gibt es dafür eine Lösung?

Danke und lg
Marius
  Mit Zitat antworten Zitat
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
ImpactMG

Registriert seit: 11. Jul 2007
16 Beiträge
 
#3

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 15. Jul 2007, 00:50
hallo,

wow, vielen dank für die ausführliche Antwort!

den code in den string einzuspeichern wäre eine idee, aber dann kann er auch lokalisiert werden, das möchte ich nicht dass der dolmetscher da was ändern kann

leider wird meine frage nicht beantwortet wie ich die liste aller Resourcestring-IDs meiner exe bekommen kann. sowas wie GetAllResourceStrings ist glaube ich nicht möglich.

das problem habe ich nun folgendermassen gelöst:
ich habe nun eine eigene Exceptionklasse implementiert die als Parameter einen Pointer auf einen Resourcestring überimmt.

Delphi-Quellcode:
constructor EResException.Create(const ResString: PResStringRec; const Postfix: String = '');
begin
  Message := LoadResString(ResString)+Postfix;
  Identifier := ResString.Identifier;
end;
der Exceptionhandler gibt den Identifier im Messagedialog aus.

inzwischen habe ich herausgefunden dass delphi entsprechend konfiguriert ein .drc file generiert. dort steht alles was ich brauche (Automatisch vergebener Identifier - für mich nun die Fehlernummer, resourcestringname, originalwert):

#define FHaupt_S_FHAUPT_OUTLOOK_KANN_NICHT_GESTARTET_WERDE N 64131
FHaupt_S_FHAUPT_OUTLOOK_KANN_NICHT_GESTARTET_WERDE N, "Outlook kann nicht gestartet werden"

zu einer exe kann ich also aus dem .drc file den zugehörigen resourcestring raussuchen, sowie die original-fehlermeldung

lg
marius
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 15. Jul 2007, 00:59
Zitat:
Delphi-Quellcode:
constructor EResException.Create(const ResString: PResStringRec; const Postfix: String = '');
begin
  Message := LoadResString(ResString)+Postfix;
  Identifier := ResString.Identifier;
end;
Das funktioniert so nicht. Dein "Identifier" mal typcasted nach Pointer(Identifier) ist gleich Pointer(Message); Dh. der Identifier eines PResStringRec ist beim allerersten Laden = Aufruf von LoadResString() die Resource-ID zum ResourceString. Sollte das der Fall sein so wird LoadResString() diesen String aus der Resource laden und dann in .Identifier zwischenspeichern.

Schau dir mal ResString.Identifier im Debugger mal VOR und NACH den Aufruf von LoadResString() an.

Gruß Hagen
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#5

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 15. Jul 2007, 08:35
Guten Morgen Marius,

Zitat von ImpactMG:
... Ist es irgendwie möglich die Liste aller Resourcestrings die im Sourcecode angeführt sind zu bekommen? ...
hast du dir schon mal das Projekt $(DELPHI)\Demos\ResXplor angeschaut?

Grüße vom marabu
  Mit Zitat antworten Zitat
ImpactMG

Registriert seit: 11. Jul 2007
16 Beiträge
 
#6

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 15. Jul 2007, 20:50
na bum

negaH: sorry, habe beim ersten Lesen nicht ganz verstanden. jetzt ist es mir klar

ResXplor würde mir helfen die resourcestrings aus der exe zu laden. Seht Ihr aber eine Möglichkeit in meiner Exceptionklasse irgendwie (auch nach dem ersten Zugriff) zu einem übergebenen PResStringRec auf den Identifier ranzukommen und damit die Exceptionklasse funktionsfähig zu machen?

Wenn ich irgendwie die Tabelle aller ResourceStrings hätte, könnte ich beim Programmstart mir die Identifier merken...

Ideen?
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 15. Jul 2007, 21:20
Du möchtest deine Strings mit einer immer absoluten ID vergeben, als Fehlernummer. Bau es in den String selber ein, setzte nach der Nummer ein Doppelpunkt, in deiner Exception Klasse entferntst du diese Nummer, wenn du es als unschön empfindest. Eine Zahl aus dem Deutschen ins Russische/Japanische/usw. übersetzt erbigt die gleiche Zahl.
Geschätzter Aufwand: 10 Minuten.

Es gibt für alles eine Lösung, aber bei den ResourceStrings keine einfache. Die IDs verändern sich ständig also muß man die *.DRC Datei parsen. Der Konstanten Name ist immer gleich aber nicht dessen ID.

Gruß Hagen
  Mit Zitat antworten Zitat
ImpactMG

Registriert seit: 11. Jul 2007
16 Beiträge
 
#8

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 16. Jul 2007, 10:33
die fehlernummern selbst zu vergeben möchte ich vermeiden. es geht um die umstellung eines grossen projekts. da ist der aufwand alles umzustellen und die fehlernummern zu verwalten recht gross. die lösung die intern vergebenen IDs der resourcestrings zu verwenden finde ich sehr elegant. dass sich damit die "fehlernummern" bei jeder release ändern stört mich nicht.
das einzige was fehlt ist immer zu einem resourcestring PResStringRec die entsprechende ID herausfinden zu können (auch beim zweiten aufruf des resourcestrings).

Zitat von negaH:
Es gibt für alles eine Lösung, aber bei den ResourceStrings keine einfache. Die IDs verändern sich ständig also muß man die *.DRC Datei parsen. Der Konstanten Name ist immer gleich aber nicht dessen ID.
gibt es einen anhaltspunkt für die nicht einfache lösung?

gruss
marius
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 16. Jul 2007, 10:42
Ich denk mal drüber nach, denke schon das man eine automatisierte Lösung finden kann.

Gruß Hagen
  Mit Zitat antworten Zitat
ImpactMG

Registriert seit: 11. Jul 2007
16 Beiträge
 
#10

Re: Alle resourcestrings der aktuellen Exe auflisten

  Alt 16. Jul 2007, 22:32
[quote="negaH"]
Zitat:
Schau dir mal ResString.Identifier im Debugger mal VOR und NACH den Aufruf von LoadResString() an.
das habe ich nun gemacht. es steht jedes mal gleicher wert drinnen! die information dass .identifier überschrieben wird scheint falsch zu sein

gruss
marius
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz