Vorsicht bei FileExists() und Schattenkopien unter Windows Server
- af0815
- Lazarusforum e. V.
- Beiträge: 6848
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
Ich würde trotzdem einen Bugreport machen, weil es sein kann, das dieses Verhalten nicht gewünscht ist. Speziell wäre die Frage, ob es in Delphi korrekt funktionier, weil wenn es dort geht, ist es definitiv ein Bug.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
- Jorg3000
- Lazarusforum e. V.
- Beiträge: 385
- Registriert: So 10. Okt 2021, 10:24
- OS, Lazarus, FPC: Win64
- Wohnort: NRW
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
Gute Idee.
Da ich auch Delphi 11 habe, habe ich dort gerade in den Quellcode von FileExists() geguckt (das hätte ich ja auch eher machen können).
Und siehe da, in Delphi wird es bei FollowLink=TRUE ganz anders gehandhabt, nämlich so: Wenn das Attribut faSymLink gesetzt ist, wird nicht etwa die Link-Ziel-Adresse nachverfolgt wie in FreePascal, sondern es wird einfach versucht die Datei mit dem übergebenen Dateinamen zum Lesen zu öffnen. Und das klappt auch bei Schattenkopien problemlos! Somit funktioniert es in Delphi wie erwartet, in FreePascal jedoch nicht immer.
... nämlich bei Schattenkopien nicht, weil man auf jenen System-Ordner keine direkte Zugriffserlaubnis hat.
Da ich auch Delphi 11 habe, habe ich dort gerade in den Quellcode von FileExists() geguckt (das hätte ich ja auch eher machen können).
Und siehe da, in Delphi wird es bei FollowLink=TRUE ganz anders gehandhabt, nämlich so: Wenn das Attribut faSymLink gesetzt ist, wird nicht etwa die Link-Ziel-Adresse nachverfolgt wie in FreePascal, sondern es wird einfach versucht die Datei mit dem übergebenen Dateinamen zum Lesen zu öffnen. Und das klappt auch bei Schattenkopien problemlos! Somit funktioniert es in Delphi wie erwartet, in FreePascal jedoch nicht immer.

- Jorg3000
- Lazarusforum e. V.
- Beiträge: 385
- Registriert: So 10. Okt 2021, 10:24
- OS, Lazarus, FPC: Win64
- Wohnort: NRW
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
Moin!
Ich habe mich gerade bei Gitlab registriert und es als Bug gemeldet.
https://gitlab.com/freepascal.org/fpc/s ... sues/41150
Ich habe mich gerade bei Gitlab registriert und es als Bug gemeldet.
https://gitlab.com/freepascal.org/fpc/s ... sues/41150
-
- Beiträge: 174
- Registriert: Do 3. Mär 2011, 21:34
- OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
- CPU-Target: Intel 32/64Bit, ARM9
- Wohnort: Ulm
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
Hallo zusammen,
ich habe auf Windows Servern genau das gegenteilige Problem.
FileExists(FileName) liefert true aber beim Öffnen der wirklich vorhandenen Datei
gibt’s dann einen Fehler. Beim nächsten log in die csv-Datei läufts wieder ganz normal.
Es handelt sich bei dem Laufwerk um ein Netzwerklaufwerk. Der Server ist eine virtuelle Maschine.
Beim log in eine Datei die dabei auf C: liegt gibt’s keine Probleme.
Auf dem Netzlaufwerk hab ich mehrmals am Tag dieses Verhalten.
Es werden hier am Tag in Richtung 3000 Textzeilen geloggt.
Könnte es sein daß ich da mit den gleichen Schwierigkeiten zu kämpfen habe?
Dann würde ich den work around mal probieren. Unsere IT kann mir da nicht helfen,
das muß an der Software liegen.
Gruß
NoCee
ich habe auf Windows Servern genau das gegenteilige Problem.
FileExists(FileName) liefert true aber beim Öffnen der wirklich vorhandenen Datei
gibt’s dann einen Fehler. Beim nächsten log in die csv-Datei läufts wieder ganz normal.
Es handelt sich bei dem Laufwerk um ein Netzwerklaufwerk. Der Server ist eine virtuelle Maschine.
Beim log in eine Datei die dabei auf C: liegt gibt’s keine Probleme.
Auf dem Netzlaufwerk hab ich mehrmals am Tag dieses Verhalten.
Es werden hier am Tag in Richtung 3000 Textzeilen geloggt.
Könnte es sein daß ich da mit den gleichen Schwierigkeiten zu kämpfen habe?
Dann würde ich den work around mal probieren. Unsere IT kann mir da nicht helfen,
das muß an der Software liegen.
Gruß
NoCee
- Jorg3000
- Lazarusforum e. V.
- Beiträge: 385
- Registriert: So 10. Okt 2021, 10:24
- OS, Lazarus, FPC: Win64
- Wohnort: NRW
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
Hi NoCee!
Das wird eher ein Problem beim Öffnen der Datei sein.
Denn in deinem Fall liefert FileExists() ja das Richtige (true wenn Datei vorhanden), aber das Öffnen schlägt fehl.
Ich vermute es hat was mit dem FileMode oder FileShare-Attribut beim Öffnen zu tun.
Wie öffnest/lädst du die Datei?
Das wird eher ein Problem beim Öffnen der Datei sein.
Denn in deinem Fall liefert FileExists() ja das Richtige (true wenn Datei vorhanden), aber das Öffnen schlägt fehl.
Ich vermute es hat was mit dem FileMode oder FileShare-Attribut beim Öffnen zu tun.
Wie öffnest/lädst du die Datei?
-
- Beiträge: 174
- Registriert: Do 3. Mär 2011, 21:34
- OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
- CPU-Target: Intel 32/64Bit, ARM9
- Wohnort: Ulm
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
Hallo Jorg3000,
geöffnet wird in etwa so: if FileExists(logfile) then append(logfile)
das append in einem try block abgesichert sonst schmiert die ganze Software ab.
Hab ich früher ohne gehabt aber auf C: da ist nie was passiert, nur auf dem Netzlaufwerk.
Das Textfile wird morgens immer neu erstellt und dann den ganzen Tag genutzt.
Ich behelfe mir da indem ich den String im Ram halte. Beim nächsten String der kommt,
werden beide gespeichert. Und das funktioniert dann. Es sind noch nie mehr als 1 String im Ram
gesichert worden. Damit ich das sehe hab ich da mal einen Zähler eingebaut.
Jetzt hab ich gehofft, daß das mit dem Thema Schattendatei zu tun haben könnte.
Aber da hört es bei mir schon lange auf. Schattendatei hab ich noch nicht mal gehört.
Vielen Dank für deine Unterstützung
Gruß
NoCee
geöffnet wird in etwa so: if FileExists(logfile) then append(logfile)
das append in einem try block abgesichert sonst schmiert die ganze Software ab.
Hab ich früher ohne gehabt aber auf C: da ist nie was passiert, nur auf dem Netzlaufwerk.
Das Textfile wird morgens immer neu erstellt und dann den ganzen Tag genutzt.
Ich behelfe mir da indem ich den String im Ram halte. Beim nächsten String der kommt,
werden beide gespeichert. Und das funktioniert dann. Es sind noch nie mehr als 1 String im Ram
gesichert worden. Damit ich das sehe hab ich da mal einen Zähler eingebaut.
Jetzt hab ich gehofft, daß das mit dem Thema Schattendatei zu tun haben könnte.
Aber da hört es bei mir schon lange auf. Schattendatei hab ich noch nicht mal gehört.
Vielen Dank für deine Unterstützung
Gruß
NoCee
- Jorg3000
- Lazarusforum e. V.
- Beiträge: 385
- Registriert: So 10. Okt 2021, 10:24
- OS, Lazarus, FPC: Win64
- Wohnort: NRW
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
Moin!
Folgendes ist mein Vorschlag für eine Append-Funktion, die ohne FileExists() auskommt.
Aber auch hier gibt es eine Race Condition zwischen einem fehlschlagenden Append() und einem ersatzweisen Rewrite().
Hat jemand einen besseren Vorschlag auf Append/Rewrite-Basis?
Dann sollten wir es anschließend für folgende Seite vorschlagen: https://wiki.freepascal.org/File_Handling_In_Pascal
... denn das dortige Beispiel finde ich schlecht, weil es sich gar nicht um eine nicht existierende Datei kümmert.
Grüße, Jörg
Folgendes ist mein Vorschlag für eine Append-Funktion, die ohne FileExists() auskommt.
Aber auch hier gibt es eine Race Condition zwischen einem fehlschlagenden Append() und einem ersatzweisen Rewrite().
Code: Alles auswählen
function AppendStringToFile(const FileName, FileHeader, Content: String): Boolean;
var
LogFile: Text;
begin
Result:=false;
AssignFile(LogFile, FileName);
try
Append(LogFile);
except
on E: EInOutError do
begin
if E.ErrorCode<>2 then Exit; // Runtime Error 2 = Datei existiert nicht
try
Rewrite(LogFile);
if FileHeader<>'' then WriteLn(LogFile,FileHeader);
except
CloseFile(LogFile);
Exit;
end;
end;
end;
try
WriteLn(LogFile,Content);
Result:=true;
finally
CloseFile(LogFile);
end;
end;
Dann sollten wir es anschließend für folgende Seite vorschlagen: https://wiki.freepascal.org/File_Handling_In_Pascal
... denn das dortige Beispiel finde ich schlecht, weil es sich gar nicht um eine nicht existierende Datei kümmert.
Grüße, Jörg
- Jorg3000
- Lazarusforum e. V.
- Beiträge: 385
- Registriert: So 10. Okt 2021, 10:24
- OS, Lazarus, FPC: Win64
- Wohnort: NRW
Re: Vorsicht bei FileExists() und Schattenkopien unter Windows Server
NoCee, in deinem Fall könnte es vielleicht sein, dass die Datei von einem anderen Process vorübergehend gesperrt ist.
Mit folgender Funktion könnte man es z.B. 3x versuchen, bevor es endgültig scheitert.
Mit folgender Funktion könnte man es z.B. 3x versuchen, bevor es endgültig scheitert.
Code: Alles auswählen
function RetryAppendStringToFile(const Filename, Header, Content: String; MaxRetries: Integer = 3): Boolean;
var
Attempt: Integer;
begin
Result := False;
// evtl. hier vorab prüfen, ob der Filename leer oder zulässig ist
for Attempt := 1 to MaxRetries do
begin
if AppendStringToFile(Filename, Header, Content) then Exit(true);
Sleep(500); // 500 Millisekunden vor dem nächsten Versuch warten
end;
end;