AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Warum kann ich die Eingaben nicht wieder auslesen

Ein Thema von delphifan2004 · begonnen am 24. Okt 2020 · letzter Beitrag vom 26. Okt 2020
Antwort Antwort
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
266 Beiträge
 
Delphi 10.3 Rio
 
#1

Warum kann ich die Eingaben nicht wieder auslesen

  Alt 24. Okt 2020, 20:09
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:
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.
Ich kann aber die Werte nach Füllen der Liste nicht wieder auslesen.

Warum geht das nicht, ich sehr den Fehler nicht.

Mein Testprogramm sieht so aus:

Delphi-Quellcode:
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.
Bei der Ausgabe erhalte ich eine EAccessviolation, wohl wird mein Key nicht wiedergefunden, Entr hat den Wert NIL!

Der Delphi Debugger hält danach bei TList.Add() an

Warum?

.

Geändert von delphifan2004 (25. Okt 2020 um 00:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.016 Beiträge
 
Delphi 12 Athens
 
#2

AW: Warum kann ich die Eingaben nicht wieder auslesen

  Alt 24. Okt 2020, 22:42
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:
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
oder in FindSubKey muß Entr auch auf Nil gesetzt werden.

Auf den ersten Blick seh ich auch nichts,
aber rate mal wozu der Debugger da ist.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (24. Okt 2020 um 22:47 Uhr)
  Mit Zitat antworten Zitat
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
266 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Warum kann ich die Eingaben nicht wieder auslesen

  Alt 24. Okt 2020, 23:01
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.

TKey(Items[Index]).inThe.Add(Entry); Mit Entr will ich meinen Subkey haben. Result gibt den Index in die KeyListe zurück, also der wievielte Key den Subkey enthält.

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.

Geändert von delphifan2004 (24. Okt 2020 um 23:08 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.016 Beiträge
 
Delphi 12 Athens
 
#4

AW: Warum kann ich die Eingaben nicht wieder auslesen

  Alt 24. Okt 2020, 23:14
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
266 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Warum kann ich die Eingaben nicht wieder auslesen

  Alt 24. Okt 2020, 23:52
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.
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.377 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Warum kann ich die Eingaben nicht wieder auslesen

  Alt 26. Okt 2020, 08:12
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.

TKey(Items[Index]).inThe.Add(Entry);
Offensichtlich weisst du nur teilweise wozu ein Debugger da ist.
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.

Geändert von freimatz (26. Okt 2020 um 17:16 Uhr)
  Mit Zitat antworten Zitat
delphifan2004

Registriert seit: 26. Nov 2004
Ort: Dresden
266 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Warum kann ich die Eingaben nicht wieder auslesen

  Alt 26. Okt 2020, 10:58
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:
function TKey.AddEntry(AEntry): Integer;
begin
  Result := -1;
  if Assigned(FKeys) then Result := FKeys.Add(AEntry);
end;
So funktioniert nun auch das Einfügen von Keys.

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;
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 18:00 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