Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi DeleteFile und die Datei ist immer noch da (https://www.delphipraxis.net/190101-deletefile-und-die-datei-ist-immer-noch-da.html)

fs999 30. Aug 2016 16:32


DeleteFile und die Datei ist immer noch da
 
Hallo,

Mit ein Delphi 2006 geschriebenes Programm erstelle ich eine Datei im ProgramData Verzeichnis und lade die über eine Internetseite mit dem TEmbeddedWB.
Das erste mal ist alles in Ordnung, die Datei wird richtig auf der Internetseite angezeigt.
Doch wenn ich noch eine Datei (mit selben Namen) lösche, dann neu erstelle, bekomme ich keine Fehlermeldung aber auf die Internetseite wird immer die erste Datei geladen.
Erst wenn ich das Programm schließe verschwindet die Datei.
Was komisch ist DeleteFile('name') gibt True zurück und TFileStream.Create('name', fmCreate) meldet kein Fehler.
Wenn das Programm läuft kann ich nicht diese Datei öffnen, sogar als Administrator komme ich nicht in den Eigenschaften an die Security ran...

Zacherl 30. Aug 2016 16:41

AW: DeleteFile und die Datei ist immer noch da
 
Du hast wohl in deinem Programm noch ein exklusives Handle auf die Datei offen. Freest du deinen FileStream nach dem Erstellen auch korrekt?

fs999 30. Aug 2016 16:47

AW: DeleteFile und die Datei ist immer noch da
 
Ja mit fs.Free;

Luckie 30. Aug 2016 22:08

AW: DeleteFile und die Datei ist immer noch da
 
Fehlerbehandlung irgendwie?

nahpets 30. Aug 2016 22:38

AW: DeleteFile und die Datei ist immer noch da
 
Der TEmbeddedWB kapselt doch den IE und der guckt erstmal in den Cache. Könnte es sein, dass Du deshalb nicht die veränderte Seite zu sehen bekommst?

Nach 'nem Programmneustart weiß der dann nicht mehr, dass er die Datei schonmal angezeigt hat, zeigt sie daher neu an, wozu er die aktuelle Datei nutzt.

Wäre zumindest mal 'ne Prüfung wert, ob da so ein Effekt vorhanden sein könnte.

t.roller 31. Aug 2016 07:23

AW: DeleteFile und die Datei ist immer noch da
 
Delphi-Quellcode:
procedure TForm.ButtonClick(Sender: TObject);
var Flags: OLEVariant;

begin
  Flags:=4; //NavNoReadFromCache
  WebBrowser1.Navigate('http://www.xxxxx.com/', Flags);
end;

fs999 31. Aug 2016 08:00

AW: DeleteFile und die Datei ist immer noch da
 
Zitat:

Zitat von Luckie (Beitrag 1346250)
Fehlerbehandlung irgendwie?

Keine Fehler.
Zitat:

Zitat von nahpets (Beitrag 1346255)
Der TEmbeddedWB kapselt doch den IE und der guckt erstmal in den Cache. Könnte es sein, dass Du deshalb nicht die veränderte Seite zu sehen bekommst?

Es ist nicht auf der Internetseite wo ich das sehe, aber im Windows Explorer. Und die Internetseite uploaded die Datei ja, sie kann nicht im Cache sein.

Ich habe vergessen zu sagen dass das nur auf Windows 10 vorkommt, nicht auf Windows 7.
Ist es möglich dass das Programm in eine Virtual Machine läuft ohne das man es weiß ?

Luckie 31. Aug 2016 10:05

AW: DeleteFile und die Datei ist immer noch da
 
Ich wollte wissen, ob du eine Fehlerbehandlung in deinem Code hast. Zum Beispiel ob der Rückgabewert von 8i]delteFile[/i] geprüft wird und wenn es fehlschlägt, was als Fehlermeldung ausgegeben wird.

Pixel 31. Aug 2016 11:34

AW: DeleteFile und die Datei ist immer noch da
 
Also um das was Luckie gefragt hat nochmals zu verdeutlichen:

Delphi-Quellcode:
procedure checkErrorDeleteFile(const path : string);
begin
  SetLastError(0);
  DeleteFile(path);
  ShowMessage(IntToStr(GetLastError));
end;
Anschließend kannst du hier nach dem Errorcode der in der Messagebox angezeigt wurde suchen, dann weißt du was das Problem ist in der Regel.

himitsu 31. Aug 2016 11:47

AW: DeleteFile und die Datei ist immer noch da
 
Ähhhhh, FALSCH und FALSCH.

siehe MSDN-Library durchsuchenDeleteFile

Delphi-Quellcode:
procedure checkErrorDeleteFile(const path : string);
begin
  //SetLastError(0); // das heißt LAST-Error und nicht THIS-Error
  is not DeleteFile(PChar(path)) then // rate mal, warum der Wert von GetLASTError nur "definitert" ist, wenn es einen Fehler gab :roll:
    //ShowMessage(IntToStr(GetLastError)); //ShorMessage als Fehlerbehandlung?
    RaiseLastOSError; // aka raise Exception.Create(SysErrorMessage(GetLastError));
end;
Sorry, es gibt zwar viele Wege, um nach Rom zu kommen, aber man sollte niemals nach links gehn, wenn dort ein Schild "rechts" steht.

Erdbär 31. Aug 2016 11:57

AW: DeleteFile und die Datei ist immer noch da
 
Wie wäre es, wenn Du vor dem Hochladen der (neuen) Datei die (alte) Datei auf dem Server löschen lassen würdest und dann ein paar Sekunden warten würdest, damit der Server den Löschbefehl auch ausführen kann?

fs999 31. Aug 2016 14:07

AW: DeleteFile und die Datei ist immer noch da
 
Zitat:

Zitat von Luckie (Beitrag 1346311)
Ich wollte wissen, ob du eine Fehlerbehandlung in deinem Code hast. Zum Beispiel ob der Rückgabewert von 8i]delteFile[/i] geprüft wird und wenn es fehlschlägt, was als Fehlermeldung ausgegeben wird.

Ja.
Delphi-Quellcode:
if not DeleteFile(s) then
begin
  ShowMessage('Datei konnte nicht gelöscht werden !');
  Abort;
end;
Zitat:

Zitat von Erdbär (Beitrag 1346331)
Wie wäre es, wenn Du vor dem Hochladen der (neuen) Datei die (alte) Datei auf dem Server löschen lassen würdest und dann ein paar Sekunden warten würdest, damit der Server den Löschbefehl auch ausführen kann?

Welchen Server ? Die Datei wird in C:\ProgramData\xxx unterlegt.

Pixel 21. Sep 2016 13:55

AW: DeleteFile und die Datei ist immer noch da
 
Zitat:

Zitat von himitsu (Beitrag 1346329)
Ähhhhh, FALSCH und FALSCH.

siehe MSDN-Library durchsuchenDeleteFile

Delphi-Quellcode:
procedure checkErrorDeleteFile(const path : string);
begin
  //SetLastError(0); // das heißt LAST-Error und nicht THIS-Error
  is not DeleteFile(PChar(path)) then // rate mal, warum der Wert von GetLASTError nur "definitert" ist, wenn es einen Fehler gab :roll:
    //ShowMessage(IntToStr(GetLastError)); //ShorMessage als Fehlerbehandlung?
    RaiseLastOSError; // aka raise Exception.Create(SysErrorMessage(GetLastError));
end;
Sorry, es gibt zwar viele Wege, um nach Rom zu kommen, aber man sollte niemals nach links gehn, wenn dort ein Schild "rechts" steht.


FALSCH FALSCH FALSCH FALSCH FALSCH FALSCH FALSCH FALSCH FALSCH FALSCH FALSCH


Ich glaube du hast GetLasterror/SetLastError nicht so ganz verstanden.

SetLastError(0) setzt nur den Fehler auf 0 (ERROR_SUCCESS). Das ist beim Debugging einer Fehlerbehandlung empfehlenswert und manchmal sogar notwendig, denn sonst kann man nicht zu 100% sagen ob der Fehler dem nächsten Befehl zugeordet ist.

GetLastError "nur definiert wenn es einen Fehler gab": Wenn es keinen Fehler gab, dann ist GetLastError 0 (ERROR_SUCCESS). Einen Wert bekommst du immer zurück und wenn alles gut ging, dann eben 0.

Zitat aus MSDN: https://msdn.microsoft.com/de-de/lib...(v=vs.85).aspx
Zitat:

That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.
Beispiel:

WriteFile(x,x,x,x,x); SetLastError(5) -> ERROR_ACCESS_DENIED
deletefile(x); SetLastError(0) -> ERROR_SUCCESS
GetLastError(); Ausgabe: 0

Wenn GetastError() jetzt 0 (ERROR_SUCCESS) zurückliefert, dann würde der Anfänger meinen beide Funktionen seien erfolgreich durchlaufen, wobei hier in dem Fall deletefile einfach den Fehlercode "5" von writefile mit "0" überschrieben hat-


Meine Funktion diente nur zum debugging und funktioniert wunderbar. Klar, das SetLastError() kann man auch weglassen und dann mit "is not deletefile()" arbeiten ich finde es eben anders besser, es könnte ja rein theoretisch sein, dass LastError schon einen Fehlerwert hat bevor deletefile aufgerufen wird und dann obwohl deletefile fehlschlägt lasterror nicht updated/überschrieben wird. Ist zwar praktisch so gut wie unmöglich aber allein dass es theoretisch so sein könnte hält mich davon ab bei sowas SetLastError(0) wegzulassen.

"Sorry, es gibt zwar viele Wege, um nach Rom zu kommen, aber man sollte niemals nach links gehn, wenn dort ein Schild "rechts" steht." Vor allem sollte man erst mal das richtige Schild suchen https://msdn.microsoft.com/de-de/lib...(v=vs.85).aspx und dann das Schild lesen bevor man los geht.

himitsu 21. Sep 2016 14:34

AW: DeleteFile und die Datei ist immer noch da
 
Liste der Anhänge anzeigen (Anzahl: 1)
GetLastError gibt per Definition den letzten Fehler zurück,
aber da ständig irgenwelche Trottel mit SetLastError rumpfuschen und solche arbeiten auch bei Microsoft selber, stimmt das eben nicht immer.

Und mit SetLastError setzt man einen "neuen" Fehlercode, womit er dann der Letzte ist.

PS: 0 ist auch ein "Fehler Code", weswegen es auch einen beliebten Fehler in der Fehlerbehandlung gibt. :stupid:
Anhang 45860



Auch kann eine Unterfunktion, einen Fehler auslösen, selbst wenn die Hauptfunktion letztendlich korrekt durchlief.

Beispiel Anhand einer imaginären Dateikopierfunktion ala CopyFile:
Zuerst mal mit GetMem großen Speicher anfragen,
wenn nicht genug RAM frei, dann nochmal nach kleinerem Speicher fragen (das ging jetzt)
dann über dem Speicher kopieren und fertig.

GetMem sagte nun einmal Fehler, womit der Fehlercode gesetzt wurde
aber CopyFile sagt dennoch TRUE, da ja doch noch kopiert werden konnte.
Vorher SetLastError(0) würde also garnichts bringen.


Somit ist, laut MSDN für MSDN-Library durchsuchenDeleteFile folgender Code falsch
Delphi-Quellcode:
SetLastError(0);
DeleteFile(...);
DeleteFile(...);
DeleteFile(...);
DeleteFile(...);
if GetLastError <> 0 then
  ZeigeFehler(GetLastError);
Denn GetLastError kann auch ungleich 0 sein, selbst wenn alles erfogreich war
und wenn DeleteFile oder eine Unterfunktion intern auch mit SetLastError(0) rumpfuscht, dann würde ein nachfolgendes DeleteFile den Fehler des Vorherrigen verdecken.

Delphi-Quellcode:
B := DeleteFile(...);
B := B and DeleteFile(...);
B := B and DeleteFile(...);
B := B and DeleteFile(...);
if not B then
  ZeigeFehler(GetLastError);
GetLastError wird nur ausgewertet, wenn mindestens ein Result FALSE sagte
und nachfolgende DeleteFile werden nicht aufgerufen, wenn vorher was schief lief, denn DeleteFile sagt in der Doku nicht, dass vorherriger ErrorCode erhalten bleibt, im Erfolgsfall.

Pixel 21. Sep 2016 15:41

AW: DeleteFile und die Datei ist immer noch da
 
Ja du hast im Prinzip das wiederholt was ich schong gesagt hatte:

Zitat:

SetLastError(0);
DeleteFile(...);
DeleteFile(...);
DeleteFile(...);
DeleteFile(...);
if GetLastError <> 0 then
ZeigeFehler(GetLastError);
In dem Fall bringt SetLastError(0) LOGISCHERWEISE rein gar nichts. Das ist das gleiche wie bei meinem Beispiel wo ich erst WriteFile() und dann DeleteFile() aufrufe.

Es macht keinen Sinn SetLastError auf 0 zu setzen wenn man daraufhin mehrere Funktionen called und am Ende dann den LastError prüft. Jeder DeleteFile call ruft schließlich SetLastError() auf und somit ist das Ergebnis von GetLastError der Fehlercode des letzten calls von DeleteFile.

Fazit: Praktisch ist es unnötig gewesen von mir SetLastError(0) aufzurufen, da man nur eine einzelne Funktion aufruft die intern SetLasterror() called und somit LastError sowieso auf diese bezogen ist. Deine Aussage ist dennoch etwas widersprüchlich.

Zitat:

GetLastError gibt per Definition den letzten Fehler zurück,
aber da ständig irgenwelche Trottel mit SetLastError rumpfuschen und solche arbeiten auch bei Microsoft selber, stimmt das eben nicht immer.
GetLastError gibt per Definition zwar den letzten Fehler zurück, nur ist 0 "ERROR_SUCCESS" eben auch als Fehler definiert, wie du ja mittlerweile auch erkannt hast.

Die prüfung mit "is not DeleteFile" halte ich daher für einen nicht notwendigen Indikator zum Aufruf von GetLastError da SetLastError eben auf 0 gesetzt wird wenn die Funktion Erfolg hatte.

OP wollte schließlich den Fehler von DeleteFile und eine Ausgabe, die bekommt er mit meinem Code immer und wenn 0 zurückkommt, dann weiß er dass alles gut gegangen ist.

himitsu 21. Sep 2016 16:12

AW: DeleteFile und die Datei ist immer noch da
 
Delphi-Quellcode:
SetLastError(0);
DeleteFile(...);
if GetLastError <> 0 then
  ZeigeFehler(GetLastError);
Auch da muß das Ergebnis nicht stimmen, selbst wenn es nur eine Funktion ist.

Es steht ja extra so in der Hilfe
Zitat:

Result=True wenn erfolgreich
und False wenn nicht. Für genauen Fehler dann bei GetLastError nachgucken.
Für Result=True ist LastError halt selten definiert, da es dann eben keinen Fehler gab ... soll heißen, es kann sein, dass DeleteFile den LastError unverändert lies, oder jetzt was Anderes drin steht.
Siehe das Beispiel mit dem CopyFile: Das Kopieren war erfolgreich, aber intern gab es einen "unbedeutenden" Fehler.

p80286 21. Sep 2016 16:49

AW: DeleteFile und die Datei ist immer noch da
 
Es gehörte mal zum "guten Ton" mit SetLastError die Fehlernummer vor zu belegen, damit man sicher war gegen Welchen Wert eine Fehlerprüfung vorgenommen werden konnte.

Gruß
K-H

Assarbad 22. Sep 2016 16:25

AW: DeleteFile und die Datei ist immer noch da
 
Zacherl hat schon recht. Ich würde auch auf ein offenes Handle tippen.

Zitat:

Zitat von fs999 (Beitrag 1346218)
Erst wenn ich das Programm schließe verschwindet die Datei.
Was komisch ist DeleteFile('name') gibt True zurück und TFileStream.Create('name', fmCreate) meldet kein Fehler.

Schonmal im Process Explorer oder gar mit ProcMon nachgeschaut? Da schwirrt mit ziemlicher Sicherheit noch irgendwo ein Handle auf die Datei rum. Ich behaupte ja nicht, daß es in deinem Prozeß ist, aber der Process Explorer könnte dies ohne weiteres aufdecken, so oder so.

Normalerweise ist das vermeintliche sofortige Löschen einer Datei ja erstmal nichts anders als das Setzen von DeleteFile in MSDN-Library durchsuchenFILE_DISPOSITION_INFORMATION mittels MSDN-Library durchsuchenZwSetInformationFile(hFile, ..., FileDispositionInformation, ...). Die Datei wird also zum Löschen vorgemerkt.

Und du darfst dir die Win32-API MSDN-Library durchsuchenDeleteFile als Hülle für den oben genannten Mechanismus vorstellen. Wenn du also eine Datei zum Löschen markierst, wird diese weiterexistieren, bis das letzte Handle weg ist:

Zitat:

A file marked for deletion is not actually deleted until all open handles for the file object have been closed and the link count for the file is zero.
Auf unixartigen Systemen ist dies übrigens ganz ähnlich, auch wenn die Datei aus dem Ursprungsverzeichnis sofort verschwindet. Mithilfe des /proc-Dateisystems kann man die Datei "wiederherstellen" indem man sie aus /proc wieder "herauskopiert", siehe hier.

Zitat:

Zitat von fs999 (Beitrag 1346218)
Wenn das Programm läuft kann ich nicht diese Datei öffnen, sogar als Administrator komme ich nicht in den Eigenschaften an die Security ran...

Ich empfehle die Lektüre von MSDN-Library durchsuchenCreateFile und dort im Besonderen von dwShareMode ;)

Übrigens könntest du als Admin mit dem aktivierten Backupprivileg doch Glück haben. Aber ist nur so eine Idee, hab's nicht getestet.


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