![]() |
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 10:43 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