AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Ini-Writes global abfangen?

Ein Thema von a.def · begonnen am 10. Apr 2017 · letzter Beitrag vom 12. Apr 2017
Antwort Antwort
Seite 3 von 4     123 4      
a.def
(Gast)

n/a Beiträge
 
#21

AW: Ini-Writes global abfangen?

  Alt 10. Apr 2017, 19:09
Meine finale Unit. Funktioniert im kompletten Projekt einwandfrei:

Delphi-Quellcode:
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.
Aufruf
Delphi-Quellcode:
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;
Sinn zusammengefasst damit es jeder versteht:
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:
---------------------------
Error
---------------------------
TeamSpeak 3 cannot write to the configuration file:
...settings.db

You can use TeamSpeak 3, but all settings will be lost!
---------------------------
Ignore Abort
---------------------------
Ein Klick auf Ignore setzt in diesem Fall eine Art AutoSave auf False (ganz grob ausgedrückt).

Geändert von a.def (10. Apr 2017 um 19:14 Uhr)
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.916 Beiträge
 
Delphi 12 Athens
 
#22

AW: Ini-Writes global abfangen?

  Alt 11. Apr 2017, 09:10
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
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#23

AW: Ini-Writes global abfangen?

  Alt 11. Apr 2017, 10:08
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:
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.
Implementation
Delphi-Quellcode:
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.
Factory
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.
Fritz Westermann
  Mit Zitat antworten Zitat
a.def
(Gast)

n/a Beiträge
 
#24

AW: Ini-Writes global abfangen?

  Alt 11. Apr 2017, 10:44
Zitat:
Warum nicht einen ganz anderen Ansatz?
Von Interfaces will ich mich eigentlich fernhalten denn ich verstehe die nicht und möchte die Funktionsweise momentan auch nicht erlernen
Aber ich gucke mir das trotzdem mal an!

Zitat:
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 ?
Beim ersten Start meines Programms kann der Nutzer entscheiden, wo Einstellungen und alles andere gespeichert werden sollen.
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.
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#25

AW: Ini-Writes global abfangen?

  Alt 11. Apr 2017, 21:30
Aufruf
Delphi-Quellcode:
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;
Hallo a.def, just versuche ich, Dein Projekt nachzuvollziehen, doch ich verstehe es nicht recht. Ich nahm an, daß <irgendeine-boolsche-variable> dazu da ist, um festzustellen (zu "messen"), ob die Ini-Datei erstellt werden kann. Ergo müßte es egal sein, mit welchem booleschen Wert sie in diesen Konstruktor "eintaucht" (was allerdings mit der "const"-Deklaration keinen Sinn ergibt). Doch behält diese <irgendeine-boolsche-variable> ihren Wert nach dem Konstruktor "Create" unabhängig davon, ob in dieses Verzeichnis (die Ini-Datei) geschrieben werden kann oder nicht.

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.

Geändert von Delphi-Laie (11. Apr 2017 um 22:14 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.542 Beiträge
 
Delphi 11 Alexandria
 
#26

AW: Ini-Writes global abfangen?

  Alt 11. Apr 2017, 22:03
Das ist ein Parameter, der angibt, ob gespeichert werden soll und nicht, ob gespeichert werden kann.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#27

AW: Ini-Writes global abfangen?

  Alt 11. Apr 2017, 22:11
Das ist ein Parameter, der angibt, ob gespeichert werden soll und nicht, ob gespeichert werden kann.
Danke, Detlef! Das erhellt.

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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Ini-Writes global abfangen?

  Alt 12. Apr 2017, 06:55
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 try ... except end; im Code
und später heult dann jemand rum "mein Programm macht nie das, was ich will und ich weiß nicht warum ".
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.733 Beiträge
 
Delphi 6 Enterprise
 
#29

AW: Ini-Writes global abfangen?

  Alt 12. Apr 2017, 07:25
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 If IniBeschreibbar then Ini.WriteString(...) 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.
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Ini-Writes global abfangen?

  Alt 12. Apr 2017, 07:38
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;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (12. Apr 2017 um 07:41 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


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 16:28 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