![]() |
Exception beim Createn eines IniFiles
Hi,
sorry dass ich schonwieder Frage (ich fühl mich schon ganz schlecht hier immer so dumme Fragen zu stellen :-|) aber ich such den Fehler in diesem Programm seid mehreren Stunden (und hab auch schon 10 Minuten nachgedacht :-P) aber ich finds einfach nicht. Alle relevanten Sachen:
Delphi-Quellcode:
uses
IniFiles, SysUtils, Classes, Dialogs; type TBasicControl = class(TObject) private {} public procedure ReadAllIn; end; TLanguageFile = class(TIniFile) private {} public {} end; var LanguageFiles: Array of TLanguageFile; BasicControl: TBasicControl; procedure TBasicControl.ReadAllIn; var SR: TSearchRec; x: integer; begin x := 0; if FindFirst(ExtractFilePath(ParamStr(0)) + 'Language\*.ini', faAnyFile, SR) = 0 then begin repeat if (SR.Attr <> faDirectory) then begin x := x + 1; SetLength(LanguageFiles, x + 1); LanguageFiles[x].Create(ExtractFilePath(ParamStr(0)) + 'Language\' + sr.Name); end; until FindNext(SR) <> 0; FindClose(SR); end; end; Die Exception tritt beim Createn auf. Der Pfad wird richtig ausgegeben, das habe ich schon überprüft. Zum prüfen habe ich eine Test.ini benutzt. Ich weiss nicht woher der Fehler kommt... Im Prinzip sollen einfach alle .ini Dateien im Ordner (Pfad)/Languages im dynamischen Array gespeichert werden. All dies befindet sich auf einer Unit ohne Form. Danke! mfg fortuneNext Woher könnte sie kommen? |
Re: Exception beim Createn eines IniFiles
Hi,
so kannst Du das nicht createn
Delphi-Quellcode:
mach mal lieber so
LanguageFiles[x].Create(ExtractFilePath(ParamStr(0)) + 'Language\' + sr.Name);
Delphi-Quellcode:
Gruss
LanguageFiles[x] := tLanguageFile.Create(ExtractFilePath(ParamStr(0)) + 'Language\' + sr.Name);
|
Re: Exception beim Createn eines IniFiles
Hi,
Delphi-Quellcode:
Es gibt mehrere Arten, einen Konstruktor aufzurufen. Du hast die falsche genommen (so arbeitet er wie eine normale Methode auf einem schon existierenden Objekt, aber du willst es erst noch rzeugen, daher musst du es so sches so machen, wie ich es geschrieben habe.
LanguageFilex[x] := TLanguageFile.Create(...)
Mfg FAlter |
Re: Exception beim Createn eines IniFiles
Ojaaaa... danke! :) :) Warum mache ich eigentlich immer wieder diesen verdammten Fehler? Ich sollte mir mal ein Programm schreiben, das bei jeder Exception erstmal ne Message zeigt die mich an diesen Fehler erinnert :oops:
danke sehr! |
Re: Exception beim Createn eines IniFiles
Hallo.
[Antwort kommt leider wegen temp. Netzwerkproblem zu spät. Ich poste trotzdem meinen Entwurf:]
Delphi-Quellcode:
Dein Array müsste bei Index=1 anfangen und dann immer um 1 erweitert werden. Und was ist mit dem nullten (0.) Element? Initialisiere doch mal x mit x := -1;
x := x + 1;
SetLength(LanguageFiles, x + 1); LanguageFiles[x].Create(ExtractFilePath(ParamStr(0)) + 'Language\' + sr.Name); (Anmerkung: Verwende doch inc(x) statt x := x+1, sieht schöner aus) Außerdem wäre hier sinnvoll, zu wissen wie dein TLanguageFile funktioniert. Wie ist der Code von Create()? Teste bitte auch deinen Code genau, in dem du per F7 Schrittweiße den Code so lange ausführst und kontrollierst, bis die Exception erscheint. Dann weißt du schonmal die exakte Zeile, in der der Fehler auftritt. (Bitte Code posten und ein "// EXCEPTION" dahinter). Gruß blackdrake |
Re: Exception beim Createn eines IniFiles
Die Frage ist zwar schon geklärt, aber ich antworte trotzdem nochmal auf Daniels Post :-)
1. Ich habe mir angewöhnt, Eintrag 0 eines Arrays immer leer zu lassen bzw. für irgendwelche Sonderoptionen offen zu lassen, und die eigentliche Zählung erst beim 1. Element beginnen zu lassen. In 0 schreibe ich dann z.B. öfters mal die Gesamtzahl der Elemente, das fand ich immer sehr praktisch :-) 2. Inc(x) -> das kannt ich noch nicht, danke ;D 3. Den TLanguageFile hatte ich gepostet - ist quasi ein normales IniFile mit einer Zusatzfunktion. Das habe ich allerdings gerade auch geändert, sodass die LanguageFile Variablen TIniFiles sind. 4. Mit F7 arbeite ich IMMER ;-) sehr nützlich. Ich hatte auch geschrieben wo genau die Exception auftritt, aber gut, ich kanns auch kommentieren :-) Da ich grad aber schonwieder eine Exception habe :firejump: probier ichs doch gleich mal aus... diesmal habe ich nicht den gleichen Fehler gemacht (hoffe ich) :-D UNIT 1: mLeer (eine leere Testform enthalten) Relevante Teile:
Delphi-Quellcode:
UNIT 2: mBase (keine Form und auch sonst nichts)
procedure TfTest.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); begin BasicControl.OpenFile('test'); fTest.Caption := BasicControl.ReadEntry('fTestCaption'); //Exception end; Relevante Teile (hauptsächlich die function TBasicControl.ReadEntry, ich habe aber auch mal die Erstellung gepostet, man kann ja nie wissen):
Delphi-Quellcode:
uses
IniFiles, SysUtils, Classes, Dialogs; type TBasicControl = class(TObject) private {} public procedure OpenFile(LanguageName: string); procedure FreeIni; function ReadEntry(Entry:string):string; end; var LanguageFiles: Array of TIniFile; UsedLanguageFile: TIniFile; UsedLanguageFilePath: String; BasicControl: TBasicControl; procedure TBasicControl.OpenFile(LanguageName: string); var SR: TSearchRec; x: integer; begin x := 0; if FindFirst(ExtractFilePath(ParamStr(0)) + 'Language\*.ini', faAnyFile, SR) = 0 then begin repeat if (SR.Attr <> faDirectory) then begin x := x + 1; SetLength(LanguageFiles, x + 1); LanguageFiles[x] := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Language\' + sr.Name); end; until FindNext(SR) <> 0; FindClose(SR); end; x := 0; for x := 1 to high(LanguageFiles) do begin if ExtractFileName(LanguageFiles[x].FileName) = LanguageName + '.ini' then begin UsedLanguageFile := LanguageFiles[x]; UsedLanguageFilePath := UsedLanguageFile.FileName; end; LanguageFiles[x].Free; end; end; function TGBasicControl.ReadEntry(Entry:string):String; begin Result := UsedLanguageFile.ReadString('words', Entry, 'missing'); //Exception end; end. Wie man sieht, muss ich noch viel üben... ich mache wohl einfach noch zu viele dumme Anfängerfehler, die eigentlich völlig unnötig sind, und auf die ich dann auch einfach nicht komme... Naja. Da man in der Schule leider nichts vernünftiges lernt, ist man als Wissensquelle eben auf Tutorials, Denken und Forenhilfe angewiesen :coder2: Ich finde die Hilfe hier richtig gut muss ich sagen. Schnell, gut erklärt und kein "man bist du dumm!!!". Da versteht mans direkt und machts (meistens) nächstes Mal besser. mfg fortuneNext |
Re: Exception beim Createn eines IniFiles
Delphi-Quellcode:
Hallo.
function TGBasicControl.ReadEntry(Entry:string):String;
begin Result := UsedLanguageFile.ReadString('words', Entry, 'missing'); //Exception end; Um Ressourcen zu sparen, würde ich UsedLanguageFile nicht als TIniFile machen, sondern als Integer! Ich würde also
Delphi-Quellcode:
verwenden. Dies verhindert auch, dass UsedLanguageFile und LanguageFiles[4] sich gegenseitig blockieren. Vielleicht ist hier schon der Grund zu suchen. Du hättest das INI-File 2 Mal geöffnet, einmal als LanguageFiles[4] und einmal als UsedLanguageFile.
Result := LanguageFiles[UsedLanguageFile].ReadString(...);
Ansonsten würde ich bei ReadEntry() noch prüfen, ob überhaupt eine Sprachdatei geöffnet ist. (Vielleicht mit deinem 0ten Eintrag?)
Delphi-Quellcode:
Gruß
function TGBasicControl.ReadEntry(Entry:string):String;
begin if UsedLanguageFile <> 0 then begin Result := LanguageFiles[UsedLanguageFile].ReadString('words', Entry, 'missing'); end else begin // Keine Sprachdatei öffen result := ':-/'; end; end; blackdrake |
Re: Exception beim Createn eines IniFiles
sag mal, welche exception kommt denn?
und bist dir sicher, dass deine instanz (auf tInifile) zum aufruf bereits existiert... :glaskugel: |
Re: Exception beim Createn eines IniFiles
Zitat:
1. mit UsedLanguageFile = Integer arbeitest 2. die Sprachpakete direkt beim Programmstart geladen werden sollte LanguageFiles[UsedLanguageFile] immer Assign'ed sein. |
Re: Exception beim Createn eines IniFiles
> Naja, ich hatte das Used Ding eigentlich eben wegen der Ressourcen eingesetzt; je nachdem, wieviele Files da später sind, würde sich das ja nicht rentieren, die alle offen zu halten. Daher werden sie ja nach Erstellen des UsedLanguageFile schonwieder ge .free d, während das UsedlanguageFile offen bleibt. Lieber 1 offene Datei als ein unbegrenzt großer DynArray, oder? Da kann wohl auch nicht der Fehler liegen, da die DynArray Files ja eben schon zu sind...
> Das mit der Überprüfung ist allerdings ein guter Vorschlag :-) Da hatte ich garnicht dran gedacht :D kann ja immer mal was sein... einfach DAU-fest machen ;-) > Es kommt die übliche EAccessViolation! > Naja, ich habe ja geschrieben wie der Ablauf ist! OpenFile ist gleich das erste was passiert, dort wird alles erstellt, geladen etc.. Danach kommt (unit mLeer) dann der Aufruf der function. Tante Edith sagt: > Mir ist aber gerade aufgefallen, ich könnte auch statt der Extra-Variable UsedLanguageFile einfach LanguageFiles[0] nehmen ^^ wieder eine Variable gespart :-] |
Re: Exception beim Createn eines IniFiles
Also irgendwie ist dein Code grotesk, nicht?
Delphi-Quellcode:
Wenn ich das richtig verstehe, listest du alle Files, lädst diese in einen dyn. Array und dann gehst du diesen Array ab und suchst nach Sprachdatei "Deutsch.ini", diese lädst du dann in UsedLanguageFile und den Rest gibst du frei.
procedure TBasicControl.OpenFile(LanguageName: string);
var SR: TSearchRec; x: integer; begin x := 0; if FindFirst(ExtractFilePath(ParamStr(0)) + 'Language\*.ini', faAnyFile, SR) = 0 then begin repeat if (SR.Attr <> faDirectory) then begin x := x + 1; SetLength(LanguageFiles, x + 1); LanguageFiles[x] := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Language\' + sr.Name); end; until FindNext(SR) <> 0; FindClose(SR); end; x := 0; for x := 1 to high(LanguageFiles) do begin if ExtractFileName(LanguageFiles[x].FileName) = LanguageName + '.ini' then begin UsedLanguageFile := LanguageFiles[x]; UsedLanguageFilePath := UsedLanguageFile.FileName; end; LanguageFiles[x].Free; end; end; (Was übrigens trotzdem fehlt, ist, dass du den LanguageFiles-Array wieder auf Größe 0 herunterfährst.) Aber wieso lädst du nicht sofort die Datei LanguageName + '.ini' in dein UsedLanguageFile? Wieso der Umstand mit der Auflistung der Sprachen?
Delphi-Quellcode:
Ich hoffe, dass ich deinen Code nicht verplant habe.
function TBasicControl.OpenFile(LanguageName: string): boolean;
begin if FileExists(ExtractFilePath(ParamStr(0)) + 'Language\' + LanguageName + '.ini') then begin UsedLanguageFile := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Language\' + LanguageName + '.ini'); UsedLanguageFilePath := UsedLanguageFile.FileName; result := true; end else begin showmessage('Language file "'+LanguageName + '.ini" not found!'); result := false; // Programm soll in diesem Fall beendet werden! end; end; Gruß blackdrake |
Re: Exception beim Createn eines IniFiles
Okay danke, das ist mir echt eine Hilfe :-)
Ich habe meinen Quelltext über die Nacht und gerade noch einmal überarbeitet und etwas neu strukturiert.
Delphi-Quellcode:
Aufgerufen wird das so (in einer anderen Unit):
unit mFNAGBase;
interface uses IniFiles, SysUtils, Classes, Dialogs; type TFNAGBasicControl = class(TObject) private {} public UsedLanguageFilePath: String; //Damit das File problemlos wieder geöffnet werden kann LanguageFiles: Array of TIniFile; //Ist jetzt in TFNAGBasicControl procedure ReadAllIn; procedure OpenFile(LanguageName: string); procedure FreeUsed; procedure FreeUnused; function ReadEntry(Entry:string):string; end; var FNAGBasicControl: TFNAGBas #icControl; implementation procedure TFNAGBasicControl.ReadAllIn; var SR: TSearchRec; x: integer; begin x := 0; if FindFirst(ExtractFilePath(ParamStr(0)) + 'Language\*.ini', faAnyFile, SR) = 0 then begin repeat if (SR.Attr <> faDirectory) then begin inc(x); SetLength(FNAGBasicControl.LanguageFiles, x + 1); //An dieser Stelle gibt es merkwürdiger weise eine AccessViolation mit Abbruch FNAGBasicControl.LanguageFiles[x] := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Language\' + sr.Name); end; until FindNext(SR) <> 0; FindClose(SR); end; end; procedure TFNAGBasicControl.OpenFile(LanguageName: string); var x: integer; begin x := 0; for x := 1 to high(FNAGBasicControl.LanguageFiles) do begin if ExtractFileName(FNAGBasicControl.LanguageFiles[x].FileName) = LanguageName + '.ini' then begin FNAGBasicControl.LanguageFiles[0] := LanguageFiles[x]; FNAGBasicControl.UsedLanguageFilePath := FNAGBasicControl.LanguageFiles[0].FileName; end; end; end; procedure TFNAGBasicControl.FreeUsed; begin FNAGBasicControl.LanguageFiles[0].Free; end; procedure TFNAGBasicControl.FreeUnused; var x: integer; begin x := 0; for x := 1 to high(FNAGBasicControl.LanguageFiles) do FNAGBasicControl.LanguageFiles[x].Free; SetLength(FNAGBasicControl.LanguageFiles, 1); end; function TFNAGBasicControl.ReadEntry(Entry:string):String; begin If FNAGBasicControl.LanguageFiles[0] <> nil then Result := FNAGBasicControl.LanguageFiles[0].ReadString('words', Entry, 'missing') // hier gab es bisher immer eine Accessviolation Else if FNAGBasicControl.LanguageFiles[0] = nil then ShowMessage('No Languagefile opened.'); end; end.
Delphi-Quellcode:
Ich hoffe das ist jetzt alles ein wenig performanter und logischer gedacht. Habe UsedLanguageFile unter LanguageFiles[0] eingefügt und sie alle statt Global als Teil der BasiCControl eingefügt.
procedure TfTest.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); begin FNAGBasicControl.ReadAllIn; //hier könnte dann die Liste der Files benutzt werden, z.B. in eine Liste zum auswählen FNAGBasicControl.OpenFile('test'); fTest.Caption := FNAGBasicControl.ReadEntry('fTestCaption'); //diese funktion hat bisher ja die exception ausgelöst FNAGBasicControl.FreeUnused; //hier nach wäre dann noch eine weitere interaktion mit der used möglich FNAGBasicControl.FreeUsed; end; Außerdem habe ich wieder ReadAllIn von OpenFile und einzelner Free-Prozeduren getrennt, damit man zwischendurch besser damit interagieren kann. Aber wieso kommt denn plötzlich eine neue Exception? Ich habe ja eigentlich nichts verändert... Die OpenFile function werde ich später auch noch nach deinem Vorschlag verbessern. Nur möchte ich zuerst, dass ich mal keine Exception kriege bevor ich eine neue Baustelle aufmache ;-) Danke für die Hilfe! mfg fortuneNext |
Re: Exception beim Createn eines IniFiles
was machst denn hier:
Delphi-Quellcode:
dachte
repeat
if (SR.Attr <> faDirectory) then begin inc(x); SetLength(FNAGBasicControl.LanguageFiles, x + 1); //An dieser S
Delphi-Quellcode:
ist bei dir ein objekt und kein array...
type
TFNAGBasicControl = class(TObject) das kansnt du so nicht initialisieren oder gar die grösse verändern... |
Re: Exception beim Createn eines IniFiles
FNAGBasicControl.LanguageFiles ist aber doch ein Array? :-/
Siehe auch hier:
Delphi-Quellcode:
Oder seh ich das falsch?
TFNAGBasicControl = class(TObject)
private {} public UsedLanguageFilePath: String; LanguageFiles: Array of TIniFile; //HIER procedure ReadAllIn; procedure OpenFile(LanguageName: string); procedure FreeUsed; procedure FreeUnused; function ReadEntry(Entry:string):string; end; |
Re: Exception beim Createn eines IniFiles
so, hier mal 'n bischen code
Delphi-Quellcode:
der sollte eigentlich deinen bisherigen code abdecken...
PROGRAM Project1;
{$APPTYPE CONSOLE} USES SysUtils, Classes, inifiles; TYPE TFiles = CLASS(TStringList) strict private fDirName: string; public PROCEDURE LoadFiles; PROCEDURE LoadIni(aIdx: integer); END; { TFiles } PROCEDURE TFiles.LoadFiles; VAR sr: tsearchRec; BEGIN fDirName := ExtractName(ParamStr(0)); Clear; IF FindFirst(fDirName + '*.ini', faAnyFile, sr) = 0 THEN BEGIN REPEAT Add(sr.Name); UNTIL FindNext(sr) <> 0; FindClose(sr); END; END; PROCEDURE TFiles.LoadIni(aIdx: integer); VAR aIni: tinifile; BEGIN IF aIdx <= Count THEN BEGIN aIni := TIniFile.Create(fDirName + Strings[aIdx]); TRY Clear; //hier die daten laden FINALLY aIni.Free; END; END; END; VAR fTFiles: TFiles; BEGIN fTFiles := TFiles.Create; TRY fTFiles.loadFiles; //hier selktieren und laden fTFiles.LoadIni(fTFiles.IndexOf('test') {aIndex}); FINALLY fTFiles.Free; END; readln; END. mit loadfiles lädst du die liste der *.inis in deine klasse, über indexof wählst du die datei aus und in loadini, lädst du dann deine daten aus der ini... jetzt brauchst du dann nur noch auf die einzelnen einträge zugreifen, und schon hast du alle deine daten... <HTH> GG |
Re: Exception beim Createn eines IniFiles
ersetz das mal ...
Delphi-Quellcode:
gegen das...
inc(x);
SetLength(FNAGBasicControl.LanguageFiles, x + 1); //An dieser Stelle gibt es merkwürdiger weise eine AccessViolation mit Abbruch
Delphi-Quellcode:
du greifst hier auf eine instanz zu, welche ausserhalb deines zugriffsbereiches ist...
inc(x);
SetLength(LanguageFiles, x + 1); //An dieser Stelle gibt es merkwürdiger weise eine AccessViolation mit Abbruch |
Re: Exception beim Createn eines IniFiles
Hi,
danke für den längeren Code :-) Ich werd ihn zwar nicht komplett kopieren (schon weil es eine Konsolenanwendung ist), aber einige Ideen und Prinzipien werden sicher in mein Projekt mit einfließen :-] Das Weglassen von FNAGControlUnit. hilft übrigens leider nicht. Wieso sollte das denn außerhalb meines Zugriffsbereichs liegen? Klappt bei den ganzen anderen procedures doch auch? |
Re: Exception beim Createn eines IniFiles
Delphi-Quellcode:
Hast du FNAGBasicControl mit
procedure TfTest.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); begin FNAGBasicControl.ReadAllIn; //hier könnte dann die Liste der Files benutzt werden, z.B. in eine Liste zum auswählen FNAGBasicControl.OpenFile('test'); fTest.Caption := FNAGBasicControl.ReadEntry('fTestCaption'); //diese funktion hat bisher ja die exception ausgelöst FNAGBasicControl.FreeUnused; //hier nach wäre dann noch eine weitere interaktion mit der used möglich FNAGBasicControl.FreeUsed; end;
Delphi-Quellcode:
initialisiert?
FNAGBasicControl := TFNAGBasicControl.Create();
Und wieso listest du weiterhin alle Language-Files auf anstelle direkt eine zu laden? Hat das einen bestimmten Grund? Gruß blackdrake |
Re: Exception beim Createn eines IniFiles
Jau das hat einen Grund:
Zitat:
Und das Create... naja. Allerdings wenn ich das einfüge, bekomme ich plötzlich einen Fehler an der Stelle
Delphi-Quellcode:
FNAGBasicControl.LanguageFiles[0].Free;
> Wenn ich es in Delphi teste, eine normale AccessViolation. > Wenn ich mit F7 die Zeilen durchgehe, öffnet sich an der Stelle das CPU-Thread-Debugger Fenster. > Wenn ich die .exe starte, "Problembericht senden" bla bla. :-O Darf Eintrag 0 irgendwie nie geleert werden? mfg |
Re: Exception beim Createn eines IniFiles
Zitat:
Wenn du dann aber an irgend einer Stelle im Programm auf Element 0 zugreifst (z.B. weil du etwas mit der "TIniFile" machen willst), kommt es zur AV, da das TIniFile ja bereits freigegeben ist. Bitte kontrolliere deinen Code sehr genau: - Du darfst niemals auf ein Objekt zugreifen, das nicht initialisiert (Create) wurde! - Du darfst niemals auf ein Objekt zugreifen, das bereits freigegeben (und nicht wieder erstellt) wurde! - Du darfst nicht auf ein Array-Element zugreifen, das nicht existiert (durch SetLength) Gruß blackdrake |
Re: Exception beim Createn eines IniFiles
Ha... ok ich hab den Fehler gefunden. Auch das Objekt war wohl komischerweise nicht Created. Seltsam hieran aber ist wohl, dass sich Objekt 0 problemlos auf irgendetwas anderes setzen, auslesen etc ließ. Nur wenn man es freen wollte, gab es eine AV weil es nicht created war.
Damit wäre alles geklärt ;-) Ich danke allen für die gute Hilfe! :) mfg fortuneNext |
Re: Exception beim Createn eines IniFiles
Hier noch ein Tipp für dich bezüglich das Erstellen und Freigeben von Objekten:
Wenn ein Objekt deine gesamte Anwendung überleben soll und aber korrekt freigegeben werden soll:
Delphi-Quellcode:
Und wenn das Objekt nur in der Methode (Prozedur / Funktion) verwendet werden soll und danach unwichtig ist, bitte so lösen:
procedure TForm1.OnCreate(...)
begin MeinObjekt := TMeinObjekt.Create(); end; procedure TForm1.OnDestroy(...) begin // Optional: // if Assigned(MeinObjekt) then MeinObjekt.Free; end;
Delphi-Quellcode:
(og: "Ressourcenschutzblock" - finally wird immer aufgerufen, um sicherzustellen, dass die Ressource freigegeben wird)
procedure MeineProzedur();
var MeinObjekt: TMeinObjekt; begin MeinObjekt := TMeinObjekt.Create(); try MeinObjekt.MachWas(); finally // Optional: // if Assigned(MeinObjekt) then MeinObjekt.Free; end; end; Gruß blackdrake |
Re: Exception beim Createn eines IniFiles
Jep, das ist nützlich. Danke nochmal! 8)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 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