Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   ini file manchmal zerstört (https://www.delphipraxis.net/173488-ini-file-manchmal-zerstoert.html)

surfer007 27. Feb 2013 22:44

Delphi-Version: 7

ini file manchmal zerstört
 
Hallo,

ich benutze eine ini Datei um Einstellungen zu speichern (TMemIni). Das ganze klappt auch soweit. Hier ein Beispiel, ich arbeite mit try/except und try/finally da TMemIni. Da ich schon den Fehler hatte "kann nicht erzeugt werden da von einem anderen Prozess benutzt" noch die FileInUse Abfrage.
Delphi-Quellcode:
procedure TForm1.CheckBoxSwichResolutionClick(Sender: TObject);
var
  s : String;
  myIni : TMemIniFile;
begin
  if bStartMerker then Exit;
  if CheckBoxSwichResolution.Checked then s := 'TRUE' else s := 'FALSE';
  WaitIfIniFileLocked;
  try
    myIni := TMemIniFile.Create(sPath + 'my.ini');
    try
      myIni.WriteString('DATA', 'SWITCHRESOLUTION', s);
      myIni.UpdateFile;
    finally
      MyIni.Free;
    end;
  except
    MyLogAdd('ERROR' + ',' + 'E=22', False);
  end;
end;

function FileInUse(FileName: string): Boolean;
var hFileRes: HFILE;
begin
  Result := false;
  hFileRes := 0;
  if NOT FileExists(FileName) then Exit;
  try
    hFileRes := CreateFile(PChar(FileName),
                                    GENERIC_READ or GENERIC_WRITE or GENERIC_EXECUTE,
                                    0,
                                    nil,
                                    OPEN_EXISTING,
                                    FILE_ATTRIBUTE_NORMAL,
                                    0);
    Result := (hFileRes = INVALID_HANDLE_VALUE);
  finally
    if NOT Result then CloseHandle(hFileRes);
  end;
end;

procedure TForm1.WaitIfIniFileLocked;
var
  i : Integer;
begin
  for i := 1 to 50 do begin
    Application.ProcessMessages;
    try
      if FileInUse(sPath + 'my.ini') then begin
        MyDelay(100);
      end else begin
        Exit;
      end;
    except
      MyLogAdd('Error WaitIfIniFileLocked', False);
    end;
  end;
end;
Nun habe ich einen Kunden bei dem ca. alle 2 Wochen die INI Datei zerschossen ist. D.h. die INI ist normalerweise ca. 30 KB gross, und im Fehlerfall dann nur noch 100 Byte und der Rest an Daten fehlt einfach. Da bei Programmstart die Einstellungen aus der INI geladen werden, gibt es dann natürlich Probleme, da Variablen nicht vorhanden sind. Normalerweise passiert sowas ja nur, wenn z.B. während des Schreibvorganges der Strom ausfällt, dann ist klar das der Rest weg ist.

Irgendwelche Tips zu dem Thema kaputte INI? Warum passiert das "manchmal" (mein Lieblings Wort wenn es um bugs geht).

Luckie 27. Feb 2013 23:55

AW: ini file manchmal zerstört
 
Wie kann denn die Ini Datei von einem anderen Prozess noch benutzt werden? Oder haben zwei Programme darauf zugriff? Wenn es nur ein ist, dann kann das nur passieren, wenn nach der Benutzung das handle nicht geschlossen wird. Und hier wäre das ein Freigeben des Ini-Objektes. Kann also der Fall eintreten, dass das Objekt nicht ordnungsgemäß wieder frei gegeben wird?

Popov 28. Feb 2013 00:25

AW: ini file manchmal zerstört
 
Nun, ich selbst arbeite, wenn es die Ini ist, eher mit der TIniFile, so dass ich die Eigenarten der TMemIni nicht kenne. Ist TMemIni die TMemIniFile? Ok, die TIniFile leitet sich inzwischen von der TMemIniFile ab, hat sie aber früher nicht gemacht. Obwohl, bei 30 KB ist TMemIni wohl die bessere Wahl.

Woraus ich hinaus will. Kann es sein, dass dem Kunden alle 2 Wochen der Rechner abschmiert, noch bevor die Ini korrekt upgedatet wurde?

Bjoerk 28. Feb 2013 00:33

AW: ini file manchmal zerstört
 
TMemIniFie ist soweit schon in Ordnung. Vermute mal, daß eher mehrere Prozesse gleichzeitig auf die selbe ini zugreifen wollen? Sonst vielleicht einfach irgendwo free oder UpdateFile vergessen?

Popov 28. Feb 2013 00:46

AW: ini file manchmal zerstört
 
Wie ich schon sagte, ich hab mich bisher wenig mit der TMemIni beschäftigt, aber

Delphi-Quellcode:
    try
      myIni.WriteString('DATA', 'SWITCHRESOLUTION', s);
      myIni.UpdateFile;
    finally
      MyIni.Free;
    end;
Wenn es hier einen Fehler gibt, dann sollte eigentlich keine Fehlermeldung kommen, d. h. man kriegt es gar nicht mit.

Gehen wir man davon aus, dass der Fehler hier in dem Beispiel bei WriteString passiert, wird doch UpdateFile nicht ausgeführt. Somit stellt sich die Frage ob UpdateFile nicht besser im Finally Block aufgehoben wäre?

Obwohl das nicht der Fehler sein kann, da in dem Fall nur die Liste nicht aktualisiert würde.

Bjoerk 28. Feb 2013 01:12

AW: ini file manchmal zerstört
 
Würd‘ ich nich' machen, UpdateFile produziert ja hier die Exception. TMemInfIle arbeitet intern mit einer StringList. WriteString fügt den Wert nur in diese Stringliste ein. Erst bei UpdateFile erfolgt ein List.SaveToFile. TMemIniFile.WriteString kann im Gegensatz zu IniFiles keinen IO-Fehler produzieren.

Vielleicht so? (ungetestet):
Delphi-Quellcode:
function CanUseIniFile(const Filename: string): boolean;
  procedure Wait200;
  var
    ATime: Cardinal;
  begin
    ATime := GetTickCount;
    repeat
    until GetTickCount - ATime > 200;
    Application.ProcessMessages;
  end;
var
  N, IO: integer;
  F: TextFile;
begin
  Result := true;
  if (FileName <> '') and FileExists(FileName) then
  begin
    AssignFile(F, FileName);
    N := 0;
    repeat
      {$I-} Reset(F); {$I+}
      IO := IOResult;
      if IO <> 0 then
      begin
        Wait200;
        Inc(N);
      end;
    until (IO = 0) or (N = 20);
    Result := (IO = 0);
    if not Result then
      MessageDlg(SysErrorMessage(IO), mtWarning, [mbOK], 0)
    else
      CloseFile(F);
  end;
end;
Edit: Muß 2 mal geprüft werden
Delphi-Quellcode:
    if CanUseIniFile(sPath + 'my.ini') then
    begin
      myIni := TMemIniFile.Create(sPath + 'my.ini');
      try
        myIni.WriteString('DATA', 'SWITCHRESOLUTION', s);
        if CanUseIniFile(sPath + 'my.ini') then
          myIni.UpdateFile;
      finally
        MyIni.Free;
      end;
    end;

Sir Rufo 28. Feb 2013 01:54

AW: ini file manchmal zerstört
 
Zitat:

Zitat von Popov (Beitrag 1205335)
Wie ich schon sagte, ich hab mich bisher wenig mit der TMemIni beschäftigt, aber

Delphi-Quellcode:
    try
      myIni.WriteString('DATA', 'SWITCHRESOLUTION', s);
      myIni.UpdateFile;
    finally
      MyIni.Free;
    end;
Wenn es hier einen Fehler gibt, dann sollte eigentlich keine Fehlermeldung kommen, d. h. man kriegt es gar nicht mit.

Gehen wir man davon aus, dass der Fehler hier in dem Beispiel bei WriteString passiert, wird doch UpdateFile nicht ausgeführt. Somit stellt sich die Frage ob UpdateFile nicht besser im Finally Block aufgehoben wäre?

Obwohl das nicht der Fehler sein kann, da in dem Fall nur die Liste nicht aktualisiert würde.

Wenn innerhalb von
Delphi-Quellcode:
try..finally
eine Exception ausgelöst wird, dann wird der
Delphi-Quellcode:
finally
Teil noch abgearbeitet aber die Exception rauscht weiter, bis diese gefangen oder aber aufpoppt.

Uwe Raabe 28. Feb 2013 08:53

AW: ini file manchmal zerstört
 
Wenn die Ini-Datei nur für das eine Programm zuständig ist, sollte eigentlich kein Zugriff eines anderen Prozesses darauf möglich sein. Die Tatsache, daß die Datei manchmal von einem anderen Prozess geöffnet ist, wäre für mich schon mal der erste Ansatzpunkt.

TMemIniFile list die Datei beim Create und schreibt Sie beim UpdateFile. Zwischendrin kann alles mögliche passieren. Auch die vorherige Abfrage, ob die Datei in Benutzung ist, verhindert keine konkurrierenden Zugriffe, da kein Locking verwendet wird.

Mit den ganzen Überprüfungen bekämpfst du nur die Symptome aber nicht die Ursache.

Bjoerk 28. Feb 2013 10:30

AW: ini file manchmal zerstört
 
Daß in der Millisekunde von Create bis UpdaeFile die Datei sonst wo benutzt wird? Klar, kann passieren, aber eher unwahrscheinlich. Wenn auf die Datei aber wirklich so wild unstrukturiert zugegriffen wird, dann würd' ich aus der IniFile eine TextFile machen. Dann weiß man wenigstens, daß von Reset/Rewrite/Append bis CloseFile kein anderer Prozess auf die Datei zugreifen kann. Ggf. ein kleiner IniFileParser schreiben der so arbeitet.

Bjoerk 28. Feb 2013 11:00

AW: ini file manchmal zerstört
 
Hab' eben auch mal mein function getestet. Ist Nonsens. Reset kann auch auf bereits geöffnete Dateien angewendet werden.:oops:

surfer007 28. Feb 2013 13:20

AW: ini file manchmal zerstört
 
Danke für die Antworten! Ich hatte mal ein Testprogramm geschrieben das relativ häufig via Timer eine INI öffnet und einen Wert schreibt. Dann die EXE zwei mal gestartet und parallel laufen lassen. Funktioniert problemlos, d.h. die INI hält selbst gleichzeitige Zugriffe von zwei verschiedenen Anwendungen durch.

Dann hatte ich nochmals ein Testprogramm gemacht, jeweils einen Button INI öffnen, INI lesen, INI schreiben, INI schliessen. Gleicher Test mit 2x die EXE starten. EXE1 INI öffnen, dann INI lesen, ist ok. Dann EXE2 INI öffnen (INI ist noch von EXE1 offen), klappt, INI lesen klappt, INI schreiben klappt auch. Selbst mit EXE1 wieder lesen zeigt den Wert den EXE2 geschrieben hat, und beide EXE haben die INI noch offen!

Warum also "manchmal" die INI zerschossen wird ist mir ein Rätsel, da INI ja scheinbar einiges mit macht. Vielleicht doch irgendwo ein Free untergegangen?!

Uwe Raabe 28. Feb 2013 13:42

AW: ini file manchmal zerstört
 
Dein Test beweist nur, daß es manchmal, vielleicht auch häufig funktioniert. Als Test, ob konkurrierende Zugriffe sicher abgefangen werden, taugt er nicht.

Uwe Raabe 28. Feb 2013 13:44

AW: ini file manchmal zerstört
 
Zitat:

Zitat von surfer007 (Beitrag 1205419)
Dann EXE2 INI öffnen (INI ist noch von EXE1 offen), klappt, INI lesen klappt, INI schreiben klappt auch. Selbst mit EXE1 wieder lesen zeigt den Wert den EXE2 geschrieben hat, und beide EXE haben die INI noch offen!

Was meinst du mit "noch offen"? Bei TMemInifile erfolgen die Zugriffe auf die Datei nur innerhalb von Create und UpdateFile. Insofern kannst du über TMemInifile die Datei gar nicht offen halten.

surfer007 28. Feb 2013 14:58

AW: ini file manchmal zerstört
 
Zitat:

Was meinst du mit "noch offen"?
nur
MyIni := TMemIniFile.Create(ExtractFilePath(Application.Exe Name) + 'my.ini');

ohne
MyIni.Free;

DeddyH 28. Feb 2013 15:01

AW: ini file manchmal zerstört
 
Da ist nix offen, lediglich die TMemIniFile-Instanz ist noch da und hat die komplette Ini im Speicher. Die Datei selbst ist aber dadurch nicht geöffnet.

Popov 28. Feb 2013 15:22

AW: ini file manchmal zerstört
 
Als ich kenne das nicht von der Ini, aber schon mal bei anderen Dateien gesehen, dass die nicht komplett gespeichert wurden. Also früher, vor DSL, konnte man ein Bild zerstören, wenn man es gerade zur Hälfte geladen hat und schon auf speichern klickte. Anscheinend habend die Browser nicht gewartet bis das Bild zu ende geladen wurde. Auch kenne ich zerstörte Dateien von Programm Abbrüchen und Windows Abstürzen.

Somit war die Frage von mir schon berechtigt, ob dem Kunden zufällig alle zwei Wochen der Rechner abschmiert. Sowas erzählen die Kunden i. d. R. nicht von alleine.

Furtbichler 28. Feb 2013 16:56

AW: ini file manchmal zerstört
 
Also ich würde einfach die Einstellungen in der INI vornehmen und dann um das Speichern ein Try-Except bauen. Im Fehlerfall auswerten und ggf. nochmals versuchen. Nach ein paar Versuchen die Datei entweder unter einem anderen Namen abspeichern, oder die angeblich geblockte Originaldatei umbenennen (das geht meistens) und dann den Speichervorgang wiederholen.

Weiterhin würde ich prüfen, ob die INI-Datei plötzlich kleiner geworden ist, nur um herauszufinden, wann das genau passiert.

hoika 28. Feb 2013 17:53

AW: ini file manchmal zerstört
 
Hallo,

wo liegt denn deine Ini-Datei ?


Heiko

sh17 28. Feb 2013 20:41

AW: ini file manchmal zerstört
 
Also ich kenne das Phänomen, eine Lösung haben wir aber noch nicht gefunden, weil es nicht nachvollziehbar ist. Wir haben in unserer Konstellation in der tat zwei Prozesse,die auf die selbe INI zugreifen. Der Witz ist aber, nicht gleichzeitig. Prozess 1 schreibt in die INI und wird beendet,ruft dabei Prozess 2.dieser oeffnet die Datei.manchmal fehlt das Ende,ein ziemlich großer teil.

Vielleicht ein cache-problem? Datei liegt auf Netz Laufwerk.

cookie22 28. Feb 2013 21:18

AW: ini file manchmal zerstört
 
Was heißt denn überhaupt zerschossen? Was bleibt denn da übrig?

Passiert das auch mit TIniFile oder nur mit TMemIniFile?

p80286 28. Feb 2013 22:15

AW: ini file manchmal zerstört
 
Ich kenne dieses Verhalten aus den guten alten TP-Zeiten wenn die Datei nicht mit
Delphi-Quellcode:
(file)close
geschlossen wurde.

könnte es sein, daß da irgendwie noch mit alten TP-Routinen auf die Ini-Datei zugegriffen wird?

Gruß
K-H

hoika 28. Feb 2013 22:45

AW: ini file manchmal zerstört
 
Hallo,

eine Ini-Datei auf einem Netzlaufwerk geht gar nicht !!!
Windows cached die Zugriffe, ob man will oder nicht (UpdateXXX bringt überhaupt nichts).

Nach dem IniFile.Free ist der Datei-Inhalt noch lange nicht auf der Platte !


Ich hatte vor ein paar Jahren auch das Problem und schreibe die Daten
jetzt in die DB selber.

Das Dumme ist, es trat nur beim Kunden ein.
Ich hatte Tests bei uns laufen:
Zugriff auf Inifile im Netz mit mehreren Rechnern gleichzeitig,
nie Probleme.


Heiko

sh17 1. Mär 2013 05:08

AW: ini file manchmal zerstört
 
Zitat:

Zitat von cookie22 (Beitrag 1205517)
Was heißt denn überhaupt zerschossen? Was bleibt denn da übrig?

Das Ende wird undefiniert abgeschnitten, irgend wo.

Zitat:

Zitat von cookie22 (Beitrag 1205517)
Passiert das auch mit TIniFile oder nur mit TMemIniFile?

Beide. Delphi 6


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:33 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