![]() |
AW: Ini-Writes global abfangen?
Meine finale Unit. Funktioniert im kompletten Projekt einwandfrei:
Delphi-Quellcode:
Aufruf
unit classIni;
interface uses SysUtils, IniFiles; type TMemIniFile = class(IniFiles.TMemIniFile) private FAutoSave: Boolean; public constructor Create(const FileName: string; const AutoSave: Boolean = True); overload; procedure UpdateFile; override; end; implementation {TMemIniFile} constructor TMemIniFile.Create(const FileName: string; const AutoSave: Boolean = True); begin inherited Create(FileName); FAutoSave := AutoSave; end; procedure TMemIniFile.UpdateFile; begin if FAutoSave then inherited; end; end.
Delphi-Quellcode:
Sinn zusammengefasst damit es jeder versteht:
procedure TForm1.Button2Click(Sender: TObject);
var IniF: TMemIniFile; begin IniF := TMemIniFile.Create(....., <irgendeine-boolsche-variable>); try IniF.WriteString('section', 'ident', 'value'); finally IniF.UpdateFile; // wird nur wirklich ausgeführt, wenn die irgendeine-boolsche-variable true ist IniF.Free; end; end; das hier ist dasselbe wie der AutoSave-Parameter ab Berlin. Mit diesem Code verhindere ich Fehler wenn mein Programm in einem UAC-geschütztem Verzeichnis gestartet wird. Teamspeak macht es ähnlich. Bei Programmstart kommt in einem UAC-geschützten Verzeichnis die Meldung Zitat:
|
AW: Ini-Writes global abfangen?
Wo schreibst du deine Daten denn hin ?
Wäre es nicht besser bei geschützem Verzeichnis in das User-Documents-Verzeichnis, oder direkt immer in das User-Documents-Verzeichnis mit evtl. weiteren Unterverzeichnisse zu schreiben ? Ich habe mittlerweile schreibende Zugriffe fast nur dort erlaubt, weil es woanders mal geht und mal nicht. Obwohl shared oder common kann man nicht immer darauf zugreifen, insbesondere auf verschiedenen Platformen. Vermutlich geht es dir um die gleiche Problematik. Der Vorteil wäre: es geht immer. Der Nachteil: es gibt Steuerdateien im User-Documents-Verzeichnis, die der mal löschen könnte. Das Thema Sicherheit spielt bei meinen Anwendungen keine Rolle, das könnte natürlich auch noch so ein Punkt sein. Rollo |
AW: Ini-Writes global abfangen?
Warum nicht einen ganz anderen Ansatz?
nur mal so schnell getippt als Anregung: Das ganze über Interfaces realisieren. Stichwort testbar etc.... 3 Units: Interface
Delphi-Quellcode:
Implementation
unit my.ini.interfaces;
interface type // Hier alles rein was im Prog tatsäclich benötigt wird iIniReadWriter = interface ['{AE9CC6E5-F0B8-4D39-8F6C-799423C60A37}'] function ReadString(const Section, Ident, Default: string): string; procedure WriteString(const Section, Ident, Value: String); end; implementation end.
Delphi-Quellcode:
Factory
unit my.ini.implementations;
interface uses System.SysUtils, System.IniFiles, my.ini.interfaces; type tiniReadWriterFile = class(TInterfacedObject, iIniReadWriter) private fchanged : boolean; fautosave: boolean; fini : TMemIniFile; private // iIniReadWriter implementations function ReadString(const Section, Ident, Default: string): string; procedure WriteString(const Section, Ident, Value: String); public constructor Create(const FileName: string; const autosave: boolean = true); overload; constructor Create(const FileName: string; const Encoding: TEncoding; const autosave: boolean = true); overload; destructor Destroy; override; end; implementation constructor tiniReadWriterFile.Create(const FileName: string; const Encoding: TEncoding; const autosave: boolean = true); begin inherited Create; fini := TMemIniFile.Create(FileName, Encoding); fautosave := autosave; end; constructor tiniReadWriterFile.Create(const FileName: string; const autosave: boolean = true); begin inherited Create; fini := TMemIniFile.Create(FileName); fautosave := autosave; end; destructor tiniReadWriterFile.Destroy; begin if fautosave and fchanged then fini.UpdateFile; fini.free; inherited; end; function tiniReadWriterFile.ReadString(const Section, Ident, Default: string): string; begin result := fini.ReadString(Section, Ident, Default); end; procedure tiniReadWriterFile.WriteString(const Section, Ident, Value: String); begin fini.WriteString(Section, Ident, Value); fchanged := true; end; end.
Delphi-Quellcode:
unit my.ini.factory;
interface uses my.ini.interfaces; type tIniReadWriterTypes = (tirwFileWrite, tirReadonly, tirwLogging) ; function CreateIniReadWriterFactory(aType : tIniReadWriterTypes; const Filename : String): iIniReadWriter; implementation uses my.ini.implementations; function CreateIniReadWriterFactory(aType : tIniReadWriterTypes; const Filename : String): iIniReadWriter; begin case aType of tirwFileWrite: result := tiniReadWriterFile.Create(Filename, true); tirReadonly :Result := tiniReadWriterFile.Create(Filename, false); // tirwLogging: result := tiniReadWriterLogger.Create(Filename); end; end; end.
Delphi-Quellcode:
unit my.useini;
interface uses my.ini.interfaces; type tuseini = class private public procedure SaveSettings(Writer : iIniReadWriter); end; implementation { tuseini } procedure tuseini.SaveSettings(Writer: iIniReadWriter); begin assert(Writer <> nil, 'Writer must be set'); Writer.WriteString('Test', 'Dummy', 'Default'); end; end. TestProjekt
Delphi-Quellcode:
program Project13;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, my.ini.implementations in 'my.ini.implementations.pas', my.ini.interfaces in 'my.ini.interfaces.pas', my.ini.factory in 'my.ini.factory.pas', my.useini in 'my.useini.pas'; const aFile : String = 'c:\test\Test.ini'; procedure Test; Var UseIni : tuseini; begin Useini := tuseini.create; Writeln('Test Readonly') ; Useini.SaveSettings(CreateIniReadWriterFactory(tirReadonly, aFile)); Writeln('Readonly Done'); Useini.SaveSettings(CreateIniReadWriterFactory(tirwFileWrite, aFile)); Writeln('Write Ini Done') ; Useini.free; end; begin try Test; Writeln('Sucess'); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; readln; end. |
AW: Ini-Writes global abfangen?
Zitat:
Aber ich gucke mir das trotzdem mal an! Zitat:
Er, der Benutzer, hat dabei die Möglichkeit zu wählen, ob die Anwendung portabel einsetzbar sein soll. Heißt also, es kann im programm-eigenen-Verzeichnis und in AppData\Programmname gespeichert werden. Die von mir bezogene Änderung bezieht sich nur auf die Variante, wenn Einstellungen im programm-eigenen-Verzeichnis gespeichert werden sollen, es aber wegen fehlender Rechte nicht funktioniert. |
AW: Ini-Writes global abfangen?
Zitat:
Wann wird denn <irgendeine-boolsche-variable> mit einem sinnvollen Wert gefüllt? Danke und Gruß Edit: Der Einwand mit dem const-Parameter war Unfug, ich nehme ihn zurück. |
AW: Ini-Writes global abfangen?
Das ist ein Parameter, der angibt, ob gespeichert werden soll und nicht, ob gespeichert werden kann.
|
AW: Ini-Writes global abfangen?
Zitat:
Gibt für mich zwar spontan keinen Sinn, denn Ini-Dateien sollen doch (eigentlich) immer gespeichert werden, sonst wären es doch keine (echten) Dateien, ohne Datenträger maximal noch Memory-Dateien, aber sei's drum, ich werde mich weiter damit beschäftigen. |
AW: Ini-Writes global abfangen?
soll: es soll automatisch (bpätestens beim Free/Close gespeichert werden
kann: es sagt nicht aus, dass nicht dennoch später noch gespeichert werden könnte (Update) Und was einen Sinn betrifft. Wenn nichts gespeichert werden soll, warum werden dann überhaupt die Write-Funktionen aufgerufen, wenn doch eh nicht gespeichert werden soll? Eingaben "wortlos" einfach so zu verwerfen ist eines der größten Fehlerpotentiale, die man in eine Komponente einbauen kann. siehe TStrings.Objects ... ständigt wundert sich jemand, dass die Werte verschwinden, obwohl etwas zugewiesen wurde. Eine Exception ala "Speichern/Objects nicht implementiert" hätte da sofort den Fehler aufgezeigt. für mich ist soein Verhalten fast genauso schlimm wie ein
Delphi-Quellcode:
im Code
try ... except end;
und später heult dann jemand rum "mein Programm macht nie das, was ich will und ich weiß nicht warum :cry:". |
AW: Ini-Writes global abfangen?
Er hat das doch schon ausführlich erklärt, dass es Konstellationen gibt, bei dem die INI-Datei schreibgeschützt ist und dann sollen die Werte halt nicht (zurück)geschrieben werden und anstatt jetzt an 23.345 Stellen im Code zu sagen
Delphi-Quellcode:
wird das schreiben so an einer zentralen Stelle verhindert. Im Hinterkopf behalten: Es geht um TMemIni, d.h. das schreiben an sich funktioniert ja (in die In-Memory Ini), diese wird am Ende ggf. nur nicht wieder als Datei zurück geschrieben.
If IniBeschreibbar then Ini.WriteString(...)
|
AW: Ini-Writes global abfangen?
Dann sollte die INI das aber auch sagen, wenn sie es nicht will.
Delphi-Quellcode:
uses
SysUtils, IniFiles; type TAccessIniFile = class(TMemIniFile) private FReadOnly: Boolean; procedure SetReadOnly(Value: Boolean); public constructor Create(const FileName: string; ReadOnly: Boolean=False); overload; procedure WriteString(const Section, Ident, Value: String); override; procedure DeleteKey(const Section, Ident: String); override; procedure EraseSection(const Section: string); override; procedure UpdateFile; override; property ReadOnly: Boolean read FReadOnly write SetReadOnly; end; { TAccessIniFile } constructor TAccessIniFile.Create(const FileName: string; ReadOnly: Boolean); begin inherited Create(FileName); FReadOnly := ReadOnly; end; procedure TAccessIniFile.DeleteKey(const Section, Ident: String); begin if FReadOnly then raise Exception.Create('ReadOnly'); inherited; end; procedure TAccessIniFile.EraseSection(const Section: string); begin if FReadOnly then raise Exception.Create('ReadOnly'); inherited; end; procedure TAccessIniFile.SetReadOnly(Value: Boolean); begin if not FReadOnly and (FReadOnly <> ReadOnly) then UpdateFile; FReadOnly := ReadOnly; end; procedure TAccessIniFile.UpdateFile; begin //if csDestroying in ComponentState then // Exit; //if FReadOnly then // raise Exception.Create('ReadOnly'); //inherited; if not FReadOnly then inherited; end; procedure TAccessIniFile.WriteString(const Section, Ident, Value: String); begin if FReadOnly then raise Exception.Create('ReadOnly'); inherited; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:38 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