![]() |
Delphi-Version: 5
eingebunde Resourcen abfragen (RCDATA)
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
wie kann ich eingebunde Resourcen auslesen ? Der Typ ist RC_DATA. Ich kann sie übrigens mit dem "Resource Hacker" auslesen. Thomas |
AW: eingebunde Resourcen abfragen (RCDATA)
Stichwort: TResourceSteam.
|
AW: eingebunde Resourcen abfragen (RCDATA)
Zitat:
Delphi-Quellcode:
gibt leider die Fehlermeldung:
TResourceStream.Create(HINSTANCE, '99303', RT_RCDATA);
der angegebene ressourcentyp wurde nicht in der image-datei gefunden Ist die Syntax denn dem Screenshot zufolge richtig ?? |
AW: eingebunde Resourcen abfragen (RCDATA)
Nein, es muss heißen
Delphi-Quellcode:
, da du hier eine Ressource nach einer ID (=Nummer) und nicht nach einem Namen (=String) lädst. Ich persönlich bin ja eher ein Freund von benannten Ressourcen, aber wie du deine Ressourcen verwaltest, ist natürlich dir überlassen.
TResourceStream.CreateFromID(HINSTANCE, 99303, RT_RCDATA)
|
AW: eingebunde Resourcen abfragen (RCDATA)
Liste der Anhänge anzeigen (Anzahl: 1)
Leider funktioniert das auch nicht und gibt den selben Fehler aus.
Wie kommst du denn darauf, dass ich nach einer Nummer suche ? Dort, wo im Screenshot 99303 steht, könnte auch ein String stehen. Im Anhang habe ich noch ein Beispiel erstellt. Ist es denn sicher, dass man die Resourcen auslesen kann, wenn sie im "Resource Hacker" angezeigt werdne oder gibt es da noch Spezialfälle, die es zu unterscheiden gibt ? |
AW: eingebunde Resourcen abfragen (RCDATA)
Zitat:
Ist wirklich sicher, dass die Ressource auch in der Exe ist und du nicht mit Reshacker versehentlich die falsche Datei untersucht hast? |
AW: eingebunde Resourcen abfragen (RCDATA)
Wie hast du diese Resource erstellt?
|
AW: eingebunde Resourcen abfragen (RCDATA)
Liste der Anhänge anzeigen (Anzahl: 1)
Es ist sicher, dass ich die richtige Datei mit dem Resourcehacker geöffnet habe.
Zwei mögliche Probleme sehe ich: - Ich arbeite mit Lazarus, nicht mit Delphi. - Die Resource, die ich auslesen möchte, habe ich auch in die exe-Datei geschrieben (mit einem anderen Programm über UpdateResource). -> Es könnte also sein, dass die Resource nicht "ordentlich" reingeschrieben worden ist, obwohl ich sie mit dem reshacker sehen kann (daher auch die Frage, ob es da noch Unterschiede/Spezialfälle gibt) --> Wenn ich die Resource in die exe-Datei schreibe und diese starte, sieht das Design auch anders aus (siehe screenshot), es wurden also die Resourcen, die für das Design verantwortlich sind, entfernt? |
AW: eingebunde Resourcen abfragen (RCDATA)
Es kann sein, dass das Design des Programms aus der Ressource geladen wird und du mit deiner veränderung selbiger, diese irgendwie zerstörst. Er somit die benötigten Daten nicht mehr bekommt.
Ich kann dir nur dazu raten, dich vorher mit Tutorials zu dem Thema Ressourcen zu befassen. Google ist da dein Freund ;) |
AW: eingebunde Resourcen abfragen (RCDATA)
Ich habe mich in der Zwischenzeit mit dem Thema Resourcen sehr ausgiebig beschäftigt, trotzdem kann ich mir nicht erklären, warum die Resource nicht gefunden werden kann, aber mit einem anderen Programm (Resource Hacker) angezeigt werden kann.
Könnte jemand vielleicht mit Delphi folgenden Code compilen und die exe hier im Forum anhängen ?
Delphi-Quellcode:
mit folgenden Komponenten:
function TForm1.GetResValue(resname: string): string;
var RS: TResourceStream; begin try RS := TResourceStream.Create(hinstance, resname, RT_RCDATA); ShowMessage('(1)'); RS.Free; ShowMessage('(2)'); SetString(Result, RS.Memory, RS.Size); except ShowMessage(SysErrorMessage(GetLastError)); Result := ''; end; end; procedure TForm1.Button1Click(Sender: TObject); var s: string; begin s := GetResValue(Edit1.Text); if (s <> '') then ShowMessage(s); end; - Editfeld: "Edit1" - Button: "Button1" Dann könnte ich testen, ob es möglich ist, die Resource abzufragen, die ich in eine exe reinschreibe. Grüße |
AW: eingebunde Resourcen abfragen (RCDATA)
Zitat:
Delphi-Quellcode:
RS := TResourceStream.Create(hinstance, resname, RT_RCDATA);
ShowMessage('(1)'); RS.Free; // hier freigeben ShowMessage('(2)'); SetString(Result, RS.Memory, RS.Size); // und hier das nicht mehr existierende Objekt verwenden wollen? except |
AW: eingebunde Resourcen abfragen (RCDATA)
Ok, das war dumm von mir.
Der Fehler ist natürlich offensichtlich, ABER es wird ja noch nicht mal die ShowMessage (1) angezeigt. Mit Hilfe von try-except und den ShowMessages kann ich ja herausfinden, dass das Programm hier abstürzt:
Delphi-Quellcode:
Woran kann das dann liegen *ratlos!*
function TForm1.GetResValue(resname: string): string;
var RS: TResourceStream; begin try RS := TResourceStream.Create(hinstance, resname, RT_RCDATA); // ------------- ## CUT ## ------------------------------------------------- ShowMessage('(1)'); RS.Free; ShowMessage('(2)'); SetString(Result, RS.Memory, RS.Size); except ShowMessage(SysErrorMessage(GetLastError)); Result := ''; end; end; |
AW: eingebunde Resourcen abfragen (RCDATA)
Könnte bitte jemand den Code mit Delphi kompilieren, mir die exe zukommen lassen (z.B. per Anhang hier im Forum).
Dann könnte ich überprüfen, ob ich die Resource richtig in das Programm reinschreibe.
Delphi-Quellcode:
Vielen Dank
function TForm1.GetResValue(resname: string): string;
var RS: TResourceStream; begin try RS := TResourceStream.Create(hinstance, resname, RT_RCDATA); ShowMessage('(1)'); SetString(Result, RS.Memory, RS.Size); ShowMessage('(2)'); RS.Free; ShowMessage('(3)'); except ShowMessage(SysErrorMessage(GetLastError)); Result := ''; end; end; procedure TForm1.Button1Click(Sender: TObject); var s: string; begin s := GetResValue(Edit1.Text); if (s <> '') then ShowMessage(s); end; |
AW: eingebunde Resourcen abfragen (RCDATA)
Wie lautet denn GetLastError?
|
AW: eingebunde Resourcen abfragen (RCDATA)
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo,
die Fehlermeldung ist "Der angegebene Ressourcentyp wurde nicht in der Image-Datei gefunden". Was mich sehr wundert ist, dass das Design so komisch aussieht (siehe Screenshot 1). Zum Test habe ich mal die Resource in ein Programm geschriben, das nicht von mir stammt (in diesem Beispiel in eine Kopie des Windows Calculator) und das Design und alle Funktionalitäten blieben erhalten. Leider verrät er mir selbst nicht, ob dieResource auch drin ist; Resource Hacker hat es aber wieder bestätigt. (siehe Screenshot 2) Ich habe mir nun eine Function geschrieben, die mir ausgibt, welche Resourcetypen (RC_STRING, RC_ICON, ...) überhaupt gefunden werden:
Delphi-Quellcode:
Damit kann festgestellt werden, ob es an dem Typ liegt oder nur an dem Namen, warum die Resource nicht gefunden worden konnte.
function LetzterFehler: string; // Hilfsfunktion
begin Result := HintenEntfernen(SysErrorMessage(GetLastError), #13#10); end; function ResTypeExists(typeid: integer): boolean; begin Result := False; try TResourceStream.Create(hinstance, 'irgendwasblabla', MakeIntResource(typeid)); Result := True; except if isSubStr(LetzterFehler, 'name') then Result := True; end; end; Die Fehlermeldungen unterscheiden sich ja nur in folgendem:
...und dann
Delphi-Quellcode:
Es werden offensichtlich alle Resourcen vernichtet, wenn ich das Programm mit UpdateResource modifiziere.
procedure TForm1.Button2Click(Sender: TObject);
var i: integer; sl: TStringList; d: DWORD; begin d := GetTickCount; sl := TStringList.Create; for i := 0 to 1000 do if ResTypeExists(i) then sl.Add(IntToStr(i)); ShowMessage('Zeit: ' + IntToStr(GetTickCount - d) + sLineBreak + 'gefunden:' + sLineBreak + sl.Text); // Ausgabe im Original: 3,5,14,24 // Ausgabe nach Bearbeiten durch anderes Programm mittels UpdateResource: nichts mehr. // (Vergleich: siehe Screenshot 3) sl.Free; end; Aber ResourceHacker versichert mir, dass die Resource RT_RCDATA hinzugefügt worden ist und alles sonst beibehalten worden ist. |
AW: eingebunde Resourcen abfragen (RCDATA)
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
In einer Stringtable sind die enthaltenen Strings mit einem (beliebigen, aber unterschiedlichen) numerischen Wert indiziert. Ausschließlich nur über diesen Index kann ein String aus der Stringtable abgerufen werden. Liegt der String dagegen in einem als RCDATA eingebunden Textfile vor, muss diese Resource zuerst mit einem ResourceStream abgerufen werden, anschließend dieser ResourceStream in den Stream einer Stringlist übertragen werden und schließlich die Stringlist entsprechend der aktuellen Anforderung analysiert werden. Ein einzelner String kann nicht singulär als RCDATA (oder als TXT) in den Resourcen eingebunden werden. Das Vorgehen, einen einzelnen String aus den Resourcen unmittelbar mittels SetString(Result, RS.Memory, RS.Size) abzurufen, kann demnach nicht funktionieren (wobei es ansonsten ohnehin korrekt heißen müßte "pchar(RS.Memory)"). Wird nun eine RCDATA-Resource mit einem Namen aufgerufen, der aber gar nicht in den Resourcen existiert, dann führt das zu einer EResNotFound-Exception - eben wie ereignet.. Abhilfe: Binde die Unit Resources ein ( ![]() Prüfe dann mit Hilfe von ResourceExists() erst einmal, ob überhaupt entweder in einer Stringtable ein String unter dem genannten Index vorhanden ist oder eine RCDATA-Resource mit dem genannten Namen existiert. Erst wenn das erfolgreich bestätigt worden ist, rufe die entsprechenden Daten aus den Resourcen ab:
Code:
uses Resources;
// String in einer Stringtable function ResourceExists(index: integer): Boolean; overload; var buffer: array[0..255] of Char; s: string; begin result := false; try if LoadString(HInstance, index, buffer, SizeOf(buffer)) > 0 then s := string(buffer); result := s <> ''; except on e: exception do Showmessage('Error ' + e.message); end; end; // String in einer RCDATA-Resource function ResourceExists(ResName: string): Boolean; overload; var lpResource: TPEResource; resGroup: TPEResourceGroup; begin result := false; resGroup := TPEResourceGroup.Create(HInstance, RT_RCDATA); try lpResource := resGroup.Find(pchar(resname)); if lpResource <> nil then result:=true; finally if Assigned(resGroup) then FreeAndNil(resGroup); resGroup.Free; end; end; function TForm1.GetResValue(resname: string): string; var RS: TResourceStream; begin RS := nil; RS := TResourceStream.Create(hInstance, ResName, RT_RCDATA); try SetLength(result, RS.Size); RS.Read(result[1], Length(result)); finally RS.Free; end; end; procedure TForm1.Button1Click(Sender: TObject); var ResName: string; slResValue: TStringlist; begin ResName := 'liste'; // Name der RCDATA-Resource! if ResourceExists(ResName) then begin slResValue:=TStringlist.Create; try slResValue.text := GetResValue(ResName); Showmessage(format('Strings in der Resource "%s":'#13#10'%s', [ResName, slResValue.text])); // ... und Stringlist nach Bedarf analysieren finally slResValue.Free; end; end else ShowMessage(format('RCDATA-Resource "%s" gibt es nicht!', [ResName])); end; |
AW: eingebunde Resourcen abfragen (RCDATA)
Nochmal:
Wie erstellst du diese Resource? Langsam vergeht einem die Lust immer wieder jeden mehrmals erst nach dem Wichtigsten fragen zu müssen. Diese Frage hatte schließlich einen guten Grund. :? |
AW: eingebunde Resourcen abfragen (RCDATA)
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
entschuldige himitsu. (Ich habe die verstecke Nachricht übrigens auch gelesen). Du hast völlig recht, nach weiteren Versuchen konnte ich feststellen: das Problem liegt definitiv darin, wie die Resource in die Exe geschrieben wird. Dazu die Funktion:
Delphi-Quellcode:
// Rückgabewert ist immer True.
function SetRes(filename, resname, resvalue: string; langid: word;
delex: boolean): boolean; var hUpdate: THandle; Size: DWord; begin hUpdate := BeginUpdateResource(PChar(filename), delex); if (hUpdate <> 0) and (hUpdate <> INVALID_HANDLE_VALUE) then begin try Size := Succ(Length(resvalue)) * SizeOf(char); Result := UpdateResource(hUpdate, RT_RCDATA, PChar(resname), langid, PChar(resvalue), Size); finally EndUpdateResource(hUpdate, False); end; end; end; // Aufruf: SetRes(f2, Edit1.Text, Edit2.Text, StrToInt(Edit3.Text), CheckBox1.Checked) Beispiel: Edit1.text = TEST Edit2.text = Hallo Edit3.text = 0 checkbox1.checked = false --- Nun erhalte ich aber, wenn ich versuche die Datei zu öffnen, in die ich geschrieben habe, sofort die Fehlermeldung siehe Anhang. |
AW: eingebunde Resourcen abfragen (RCDATA)
Prüf mal, ob die LangID stimmt.
Diese Resource-Funktionen gehn immer nur auf eine Sprache los. Wenn also eine andere Sprache angegeben wurde, dann kann das natürlich nicht gefunden werden. |
AW: eingebunde Resourcen abfragen (RCDATA)
Liste der Anhänge anzeigen (Anzahl: 1)
Die Langid ist bei den anderen Resourcen 1033, deswegen habe ich die auch mal ausprobiert.
Leider hat es nicht funktioniert. Das folgende Problem tauch aber unabhängig davon immer auf: Nur ein Teil der ReadProcessMemory- oder WriteProcessMemory wurde abgeschlossen Und zwar sofort nachdem ich die modifizierte EXE starte. Es ist eine Windows-interne Fehlermeldung. (siehe Anhang letzten Posts von mir) Ich mache durch meine Funktion SetRes also die exe (hier: filename) kaputt, wie es scheint. Ich würde mich freuen, falls es doch noch möglich ist, das Problem zu lösen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz