![]() |
Warum kann ich die Eingaben nicht wieder auslesen
Hallo!
Ich habe folgende Unit erstellt, will wissen wie Windows intern Registrydaten speichert. Ob es Windows ganz genau so macht, weiß ich natürlich nicht, aber ich versuche mir vorzustellen, wie das Windows intern machen könnte.
Delphi-Quellcode:
Ich kann aber die Werte nach Füllen der Liste nicht wieder auslesen.
unit entries;
interface uses System.SysUtils, Classes, Windows, Contnrs; type PNode = ^TNode; //Ein voerheriger Versuch TNode = record Data: Pointer; next, prev: PNode; end; //So könnte Windows intern Registrydaten speichern TEntry = class(TObject) private FSubkey: AnsiString; //Unterschlüssel FSubkeyW: WideString; FKeyClass: AnsiString; //Schlüsselklasse FKeyClassW: WideString; FKeyValue: AnsiString; //Schlüsselwert FKeyValueW: WideString; FdwOptions: DWORD; //Optionen zur Erzeugung FsamDesired: REGSAM; //Optionen zum Zugriff auf den Schlüssel FDataType: LPDWORD; //Typ der Daten im Schlüsseleintrag FDataLen: DWORD; //Länge dieser Daten FData: LPBYTE; //Die Daten selber function GetData: LPBYTE; procedure SetData(const Value: LPBYTE); function GetNode: PNode; procedure SetNode(const Value: PNode); public constructor Create; constructor CreateAndInit( lpSubKey: AnsiString; lpClass: AnsiString; dwOptions: DWORD; samDesired: REGSAM; aDataType: LPDWORD=nil; aDataLen: DWORD=0; aData: LPBYTE=nil ); constructor CreateAndInitW( lpwSubKey: WideString; lpwClass: WideString; dwOptions: DWORD; samDesired: REGSAM; aDataType: LPDWORD=nil; aDataLen: DWORD=0; aData: LPBYTE=nil ); destructor Destroy; override; property Subkey: AnsiString read FSubKey write FSubkey; property KeyClass: AnsiString read FKeyClass write FKeyClass; property KeyValue: AnsiString read FKeyValue write FKeyValue; property dwOptions: DWORD read FdwOptions write FdwOptions; property samDesired: REGSAM read FSamDesired write FsamDesired; property DataType: LPDWORD read FDataType write FDataType; property DataLen: DWORD read FDataLen write FDataLen; property Data: LPBYTE read GetData write SetData; end; //Für jeden Subkey dann einen Registryeintrag TEntries = class(TObjectList) //Subkeys private function GetEntries(Index: Integer): TEntry; procedure SetEntries(Index: Integer; const Value: TEntry); public function FindSubKey(aSubKey: AnsiString; var Entry: TEntry): Integer; function FindClass(aClass: AnsiString; var Entry: TEntry): Integer; function FindValue(aValueName: AnsiString; var Entry: TEntry): Integer; property Entries[Index: Integer]: TEntry read GetEntries write SetEntries; default; end; //Wegen der vielen Subkeys diese Klasse TKey = class(TObject) private FKey: HKEY; //Key FKeys: TEntries; function GetEntries: TEntries; procedure SetEntries(const Value: TEntries); function GetKeys(Index: Integer): TEntry; procedure SetKeys(Index: Integer; const Value: TEntry); //Subkeys public constructor Create; destructor Destroy; override; property SubKeys[Index: Integer]: TEntry read GetKeys write SetKeys; property InThe: TEntries read FKeys write FKeys; property Key: HKEY read FKey write FKey; end; //Und endlich alle Keys uns Subkeys in einer Liste TKeys = class(TObjectList) private function GetKeys(Index: Integer): TKey; procedure SetKeys(Index: Integer; Value: TKey); public constructor Create; destructor Destroy; override; function AddEntry(Key: HKey; Entry: TEntry): Integer; //Neuen Key function AddKey(Key: TKey): Integer; //Subkey function AddSubKey(Key: HKey; Entry: TEntry): Integer; //wie AddEntry property Keys[Index: Integer]: TKey read GetKeys write SetKeys; end; implementation constructor TEntry.Create; begin inherited Create; end; constructor TEntry.CreateAndInit(lpSubKey, lpClass: AnsiString; dwOptions: DWORD; samDesired: REGSAM; aDataType: LPDWORD; aDataLen: DWORD; aData: LPBYTE); begin inherited Create; FSubkey := lpSubKey; FKeyClass := lpClass; FdwOptions := dwOptions; FsamDesired := samDesired; FDataType := aDataType; FDataLen := aDataLen; FData := aData; end; constructor TEntry.CreateAndInitW(lpwSubKey, lpwClass: WideString; dwOptions: DWORD; samDesired: REGSAM; aDataType: LPDWORD; aDataLen: DWORD; aData: LPBYTE); begin inherited Create; FSubkey := lpwSubKey; FKeyClass := lpwClass; FdwOptions := dwOptions; FsamDesired := samDesired; FDataType := aDataType; FDataLen := aDataLen; FData := aData; end; destructor TEntry.Destroy; begin freemem(FData,FDataLen); inherited; end; function TEntry.GetData: LPBYTE; begin Result := nil; { if FData <> nil then Result := FData else Result := nil; } end; function TEntry.GetNode: PNode; begin Result := nil; end; procedure TEntry.SetData(const Value: LPBYTE); begin FData := Value; end; procedure TEntry.SetNode(const Value: PNode); begin //War ein vorheriger Ansatz mit Nodeslist, //den ich aber verworfen habe end; { TEntries } function TEntries.FindClass(aClass: AnsiString; var Entry: TEntry): Integer; var Index: Integer; begin Index := 0; Result := -1; while Index < self.Count do begin if TEntry(Items[Index]).KeyClass = aClass then begin Entry := TEntry(Items[Index]); Result := Index; //Index := self.Count; break; //wieder break statt Index auf Count end; //(auch in meinem Delphi Code geändert) inc(Index); end; end; function TEntries.FindSubKey(aSubKey: AnsiString; var Entry: TEntry): Integer; var Index: Integer; begin Index := 0; Result := -1; while Index < self.Count do begin if TEntry(Items[Index]).Subkey = aSubKey then begin Entry := TEntry(Items[Index]); Result := Index; //Index := self.Count; break; //wieder break statt Index auf Count end; //(auch in meinem Delphi Code geändert) inc(Index); end; end; function TEntries.FindValue(aValueName: AnsiString; var Entry: TEntry): Integer; var Index: Integer; begin Index := 0; Result := -1; while Index < self.Count do begin if TEntry(Items[Index]).KeyValue = aValueName then begin Entry := TEntry(Items[Index]); Result := Index; //Index := self.Count; break; //wieder break statt Index auf Count end; //(auch in meinem Delphi Code geändert) inc(Index); end; end; function TEntries.GetEntries(Index: Integer): TEntry; begin if (Index >= 0) and (Index < Count) then Result := TEntry(Items[Index]) else Result := nil; end; procedure TEntries.SetEntries(Index: Integer; const Value: TEntry); begin Delete(Index); Insert(Index,Value); end; { TKeys } function TKeys.GetKeys(Index: Integer): TKey; begin Result := TKey(Items[Index]); end; procedure TKeys.SetKeys(Index: Integer; Value: TKey); begin Keys[Index] := Value; end; function TKeys.AddEntry(Key: HKEY; Entry: TEntry): Integer; begin Result := AddSubKey(Key, Entry); end; function TKeys.AddKey(Key: TKey): Integer; begin Result := inherited Add(Key); end; function TKeys.AddSubKey(Key: HKEY; Entry: TEntry): Integer; var Index,subix: Integer; begin Index := 0; Result := -1; //so jetzt ist Result auf jeden Fall definiert (auch in meinem Delphi Code geändert) while Index < Count do begin if TKey(Items[Index]).FKey = Key then begin TKey(Items[Index]).inThe.Add(Entry); Result := Index; Index := Count; break; end; Inc(Index); end; end; constructor TKeys.Create; begin inherited Create; end; destructor TKeys.Destroy; begin inherited; end; { TKey } constructor TKey.Create; begin inherited Create; end; destructor TKey.Destroy; begin inherited; end; function TKey.GetEntries: TEntries; begin Result := FKeys; end; function TKey.GetKeys(Index: Integer): TEntry; begin Result := FKeys.GetEntries(Index); end; procedure TKey.SetEntries(const Value: TEntries); begin FKeys.Assign(Value); end; procedure TKey.SetKeys(Index: Integer; const Value: TEntry); begin FKeys.SetEntries(Index,Value); end; end. Warum geht das nicht, ich sehr den Fehler nicht. Mein Testprogramm sieht so aus:
Delphi-Quellcode:
Bei der Ausgabe erhalte ich eine EAccessviolation, wohl wird mein Key nicht wiedergefunden, Entr hat den Wert NIL!
program EntryTest;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Windows, Entries; var AKey: TKey; Keys: TKeys; Entr: TEntry; begin try { TODO -oUser -cConsole Main : Code hier einfügen } Entr := TEntry.Create; Entr.Subkey := 'Erster Testschlüssle'; AKey := TKey.Create; AKey.Key := 1111; Keys := TKeys.Create; Keys.AddKey(AKey); Keys.AddEntry(1111,Entr); Writeln('Mein Ergebnis der Eingabe:'); TKey(Keys.Keys[0])..inThe.FindSubKey(Entr.Subkey, Entr); if Entr <> nil then Writeln('Gefundener Key: ', Entr.Subkey); Writeln('Zurück mit Enter ... '); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Der Delphi Debugger hält danach bei TList.Add() an Warum? . |
AW: Warum kann ich die Eingaben nicht wieder auslesen
Entr kann nicht nil sein, da du niemals Nil setzt.
Es wird ausschließlich das Result gesetzt, also ist deine Prüfung falsch,
Delphi-Quellcode:
oder in FindSubKey muß Entr auch auf Nil gesetzt werden.
X := TKey(Keys.Keys[0]).inThe.FindSubKey(Entr.Subkey, Entr);
//if X >= 0 then ... ja, nun rächt es sich, dass hier ein total unpraktisches Result "Count" rausgegeben wird, wenn nichts gefunden wurde if X < TKey(Keys.Keys[0]).inThe.Count then ... oder sowas Auf den ersten Blick seh ich auch nichts, aber rate mal wozu der Debugger da ist. |
AW: Warum kann ich die Eingaben nicht wieder auslesen
Danke erst mal für die Antwort. Ja, ich weiß, wozu ein Debugger gut ist. Da bin ich jetzt gerade drüber, habe aber noch keine Idee, woran es liegen könnte. Der Debugger sagt mit aber dass diese Anweisung in der TKeys.AddSubKey Methode nicht in Ordnung ist.
Delphi-Quellcode:
Mit Entr will ich meinen Subkey haben. Result gibt den Index in die KeyListe zurück, also der wievielte Key den Subkey enthält.
TKey(Items[Index]).inThe.Add(Entry);
TEntries enthlt meine Subkeys vom Typ TEntry TKeys enthält meine Keys vom Typ TKey, bestened aus dem numerischen Key und der TEntries Liste mit den zugehörigen Subkeys. Mit Result := Count will ich die Schleife beenden, Break hat in einem anderen Kontext wo ich die Unit getestet hatte das gesamte Programm verlassen. Obwohl break nur die aktuelle Schleife verlassen sollte. Kann aber break noch mal in diesem Kontext hier testen. |
AW: Warum kann ich die Eingaben nicht wieder auslesen
Bei AddSubKey seh ich grade, dass Result garnicht zugewiesen wird, wenn der Key nicht existiert.
Da sollte der Compiler eigentlich auch eine Warnung werfen und es wäre besser, wenn du diese Fehler erstmal beseitigst. Ich bin mir auch fast sicher, dass AddEntry/AddSubKey garnicht macht, weswegen man natürlich auch nichts finden kann und durch die fehlenden Indexprüfungen die nachfolgenden Zugriffe auch schön knallen dürfen. PS: In einem etwas aktuelleren Delphi (maximal 10 statt 18 Jahre alt), würden durch die Generics eventuelle Fehler durch falsche Casts entfallen. |
AW: Warum kann ich die Eingaben nicht wieder auslesen
Da guck ich dann morgen. Jetzt schlaf ich erst mal darüber, vielleicht kommt mir dann morgen noch eine Idee. Soweit erst mal Danke für die Tipps. Da geh ich den Result Zuweisungsfehler noch an und überlege mir morgen ein besseres Design. Leider habe ich mit Generics noch gar keine Erfahrung. Mein Delphi ist inzwischen auch die brandneue Delphi 10.3.3 Community Edition, also weit unter 10 Jahre alt. Die letzte vorherige war Turbo Delphi.
|
AW: Warum kann ich die Eingaben nicht wieder auslesen
Zitat:
Vielleicht auch ich, habe keine Ahnung wie der Debugger sagen kann, dass eine Methode nicht in Ordnung sei. Wenn das Problem bei "TKey(Items[Index]).inThe.Add(Entry);" liegt dann a) lass Dir doch die Werte anzeigen. Z.B. Zuerst von "Index", dann von "Items[Index])", dann "TKey(Items[Index])" usw. b) Zerlege den komplizierten Ausdruck in einfachere. |
AW: Warum kann ich die Eingaben nicht wieder auslesen
Hab ich jetzt auch gemacht, die Zeile lautet jetzt
TKey(Items[Index]).AddEntry(Entry); Wobei ich diese Methode in TKey hinzugefügt habe.
Delphi-Quellcode:
So funktioniert nun auch das Einfügen von Keys.
function TKey.AddEntry(AEntry): Integer;
begin Result := -1; if Assigned(FKeys) then Result := FKeys.Add(AEntry); end; Uns so lese ich aus
Delphi-Quellcode:
for KeyIdx := 0 to Keys.Count-1 do
for SubIdx := 0 to Keys.Keys[KeyIdx].InThe.Count-1 do begin Entr := nil; Entr := Keys.Keys[KeyIdx].SubKeys[SubIdx]; //Keys.Keys[KeyIdx].InThe.FindSubKey('Zweiter Testschlüssel',Entr); if Entr <> nil then Writeln('Gefundener Key: ', Entr.Subkey); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:54 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 by Thomas Breitkreuz