Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wie feststellen, ob eine Datei gelesen werden kann? (https://www.delphipraxis.net/188881-wie-feststellen-ob-eine-datei-gelesen-werden-kann.html)

PeterPanino 15. Apr 2016 19:12

Delphi-Version: 10 Seattle

Wie feststellen, ob eine Datei gelesen werden kann?
 
Hallo!

Ich möchte einen Text aus einer HTML-Datei auslesen:

Delphi-Quellcode:
ThisHTMLStr := Trim(TFile.ReadAllText(AHTMLFile));


Da diese Datei aber gerade in MS Word 2010 geöffnet ist, erhalte ich hier folgende Fehlermeldung:

Zitat:

Project xyz.exe raised exception class EFOpenError with message 'Cannot open file "F:\document.htm". Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird'.

Wie kann ich aber nun schon VORAB prüfen, ob diese Datei lesbar ist (und nicht in MS Word geöffnet ist)?

Der schöne Günther 15. Apr 2016 19:19

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Ich persönlich finde das so richtig. Die EFOpenError-Exception behandeln heißt: Geht nüscht, kann nicht lesen. Ist wohl jemand anderes exklusiv drauf.

Wenn du auf der Exception anhälst siehst du auch dass der auch nur CreateFile(..) aus der WinApi aufgerufen und
Delphi-Quellcode:
INVALID_HANDLE_VALUE
zurückbekommen hat. Das kannst du natürlich auch noch einmal von hand machen, aber was hat man dadurch gewonnen?

Und von der theoretischen Möglichkeit dass sich jemand die Datei zwischen deiner Überprüfung und dem Versuch die Datei dann tatsächlich zu öffnen dann schnappt wollen wir erst gar nicht sprechen ;-)

PeterPanino 15. Apr 2016 19:31

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Danke. Aber wie kann ich das VORAB feststellen? Also etwa:

Delphi-Quellcode:
if IsFileReadable(AHTMLFile) then
  ThisHTMLStr := Trim(TFile.ReadAllText(AHTMLFile))
else
  LogThisError;

Der schöne Günther 15. Apr 2016 19:36

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Beispiele findest du zuhauf hier:
http://www.delphipraxis.net/dp_searc...Datei geöffnet .

Aber wie gesagt, was hat das für einen Vorteil gegenüber keine Extra Methode schreiben und einfach

Delphi-Quellcode:
try
   ThisHTMLStr := Trim(TFile.ReadAllText(AHTMLFile))
except
   LogThisError();
end;

Helmi 15. Apr 2016 20:11

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Hallo,

hilft dir dieser, vielleicht einer etwas in die Jahre gekommener, Tipp der Schweizer weiter?

PeterPanino 15. Apr 2016 20:22

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Mit diesem Code kann ich den Fehler bei einer geöffneten Datei umgehen:

Delphi-Quellcode:
function MyTempCopyFile(const AFile: string): string;
// Kopiert eine Datei in den Temp-Ordner und gibt den Namen der Kopie zurück (wenn erfolgreich)
var
  ThisTempFile: string;
begin
  Result := '';
  try
    ThisTempFile := TPath.GetTempFileName;
  except
    // Todo: Fehler loggen
    EXIT;
  end;
  try
    TFile.Copy(AFile, ThisTempFile, True);
  except
    // Todo: Fehler loggen
    EXIT;
  end;
  Result := ThisTempFile;
end;

// Fehler vermeiden, wenn die Datei etwa in MS Word geöffnet ist:
try
  ThisHTMLStr := Trim(TFile.ReadAllText(AHTMLFile));
except
  TempCopy := MyTempCopyFile(AHTMLFile);
  if TempCopy <> '' then
    ThisHTMLStr := Trim(TFile.ReadAllText(TempCopy));
end;

PeterPanino 15. Apr 2016 20:45

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von Helmi (Beitrag 1335716)
Hallo,

hilft dir dieser, vielleicht einer etwas in die Jahre gekommener, Tipp der Schweizer weiter?

Ja, das ist ein guter Tipp. Da ich die Datei aber nur zum LESEN öffnen möchte: Sind
Delphi-Quellcode:
GENERIC_READ or GENERIC_WRITE
für diesen Fall die richtigen Flags?

p80286 16. Apr 2016 00:34

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
im Prinzip gibt es zwei Gründe warum eine Datei nicht gelesen werden kann
a) sie ist exclusiv von einem anderen Prozess geöffnet
b) der aufrufende Prozess hat keine Leseberechtigung

Das Resultat ist in beiden Fällen das gleiche, die Datei kann nicht geöffnet werden.
interessant wird es wenn man wissen will, warum?

Gruß
k-H

PeterPanino 16. Apr 2016 08:58

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von p80286 (Beitrag 1335734)
im Prinzip gibt es zwei Gründe warum eine Datei nicht gelesen werden kann
a) sie ist exclusiv von einem anderen Prozess geöffnet
b) der aufrufende Prozess hat keine Leseberechtigung

Das Resultat ist in beiden Fällen das gleiche, die Datei kann nicht geöffnet werden.
interessant wird es wenn man wissen will, warum?

Gruß
k-H

In meinem Beitrag #6 habe ich gezeigt, wie man eine von einem anderen Programm exclusiv geöffnete Datei trotzdem lesen kann: Indem man sie kopiert.

Sir Rufo 16. Apr 2016 09:07

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von PeterPanino (Beitrag 1335742)
Zitat:

Zitat von p80286 (Beitrag 1335734)
im Prinzip gibt es zwei Gründe warum eine Datei nicht gelesen werden kann
a) sie ist exclusiv von einem anderen Prozess geöffnet
b) der aufrufende Prozess hat keine Leseberechtigung

Das Resultat ist in beiden Fällen das gleiche, die Datei kann nicht geöffnet werden.
interessant wird es wenn man wissen will, warum?

Gruß
k-H

In meinem Beitrag #6 habe ich gezeigt, wie man eine von einem anderen Programm exclusiv geöffnete Datei trotzdem lesen kann: Indem man sie kopiert.

Was aber auch nur dann geht, wenn du auch Leserechte hast ... darauf wollte p80286 nur hinweisen

PeterPanino 16. Apr 2016 11:16

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Welche Art von User sollte keine Leserechte haben?

Fritzew 16. Apr 2016 13:00

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Wenn die Datei in einem anderen Process exklusiv oder zum schreiben geöffnet ist geht das nicht

PeterPanino 16. Apr 2016 14:11

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von Fritzew (Beitrag 1335752)
Wenn die Datei in einem anderen Process exklusiv oder zum schreiben geöffnet ist geht das nicht

Was geht nicht?

Zacherl 16. Apr 2016 14:20

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von PeterPanino (Beitrag 1335762)
Zitat:

Zitat von Fritzew (Beitrag 1335752)
Wenn die Datei in einem anderen Process exklusiv oder zum schreiben geöffnet ist geht das nicht

Was geht nicht?

Wenn die Datei nicht mit mindestens FILE_SHARE_READ geöffnet wurde, ist auch nix mit Kopieren, da man zum Kopieren logischerweise Leserechte benötigt. Und ohne besagtes Flag, hat die Anwendung, die momentan das Handle geöffnet hat, eben exklusiven Lesezugriff.

PeterPanino 16. Apr 2016 14:32

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Also bei mir geht das Kopieren wie in Beitrag #6 demonstriert, wenn die Datei in MS Word geöffnet ist. Besser gesagt es läuft. :wink:

Zacherl 16. Apr 2016 15:29

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von PeterPanino (Beitrag 1335767)
Also bei mir geht das Kopieren wie in Beitrag #6 demonstriert, wenn die Datei in MS Word geöffnet ist. Besser gesagt es läuft. :wink:

Für MS Word mag das ja stimmen, aber den anderen Leuten ging es wohl um eine allgemeingültige Lösung. Word wird das FILE_SHARE_READ Flag verwenden. Für Anwendungen, die das nicht tun, funktioniert deine Funktion aber entsprechend auch nicht.

PeterPanino 16. Apr 2016 15:38

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Natürlich, das ist doch klar. Wenn's gar nicht geht, muss wohl ggf. eine Meldung an den Benutzer ausgegeben werden, dass er das blockierende Programm schließen soll. Aber mit meiner Lösung aus Beitrag #6 ist sichergestellt, dass es in einer höheren Anzahl von Fällen funktioniert als ohne diese Lösung.

jaenicke 16. Apr 2016 17:21

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Du kannst auch die Datei direkt öffnen und dabei FILE_SHARE_WRITE als Flag angeben, z.B. bei einem Filestream. Das sollte genauso oft klappen wie die Kopie.

PeterPanino 16. Apr 2016 18:45

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Da wäre eine Routine recht praktisch, mit der man (direkt, also nicht durch Rückschlüsse) herausfinden kann, mit welchen Flags eine Datei geöffnet ist. Gibt's denn sowas?

p80286 16. Apr 2016 23:15

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von PeterPanino (Beitrag 1335749)
Welche Art von User sollte keine Leserechte haben?

Na der, der diese Rechte nicht hat.
Wenn Du Dir die Eigenschaften einer Datei anschaut (Sicherheit) findest Da wahrscheinlich

Authentifizierte Benutzer
System
Administratoren
Benutzer

Wenn Du, falls Du die entsprechenden Rechte hast, die "Authentifizierte Benutzer" und "Benutzer" löschst, haben normale Benutzer ein echtes Problem diese Datei zu lesen, geschweige denn zu editieren.
Statt zu löschen kannst Du auch Rechte verweigern, was ich allerdings nicht empfehlen kann, da die Rechteverweigerung der schnellste Weg zur Erzeugung von Datei-Zombies ist.

Gruß
K-H

jfheins 17. Apr 2016 16:27

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von PeterPanino (Beitrag 1335783)
Da wäre eine Routine recht praktisch, mit der man (direkt, also nicht durch Rückschlüsse) herausfinden kann, mit welchen Flags eine Datei geöffnet ist. Gibt's denn sowas?

Eventuell, aber wofür? Wenn du die Datei in einem Programm öffnen willst, wirst du ja schon sehr genau wissen, was due machen musst. (ALso ob der Bneutzer Öffnet oder speichert)

Und das einzige, was hier sinnvoll ist, ist die Aktion zu probieren. Und wenn es nicht ging, dann gab es wohl ein Problem und man kann eine Fehlermeldung anzeigen. Die Info, ob eine Datei schreibbar ist, ist ja in dem Moment schon veraltet (und damit nutzlos) in dem die sie bekommst. Stell dir eine Anwendung vor, die 10 Mal pro Sekunde eine Datei exklusiv zum schreiben öffnet, eine Zeile schreibt und wieder schließt. Doofes Programm, aber kann man machen. Und du versuchst, die gleiche Datei zu öffnen.
Wenn du dann sowas machst wie
Delphi-Quellcode:
if IsFileReadable(AHTMLFile) then
  ThisHTMLStr := TFile.ReadAllText(AHTMLFile)
else
  LogThisError;
Ist dein Programm instabil, weil es dennoch zu einer Exception kommen kann!
Denk' immer dran, dein Programm kann jederzeit unterbrochen werden. Und bevor du wieder drankommst können potenziell alle anderen Prozesse im System laufen.


Und dann bin ich gerade noch auf opportunistic locks gestoßen. EIn Programm kann damit eine Datei zum schreiben öffnen und wird benachrichtigt, wenn ein zweites Programm schreiben möchte um dann seinen Zugriff zu beenden.
Es könnte also sein, dass die Datei zwar in Verwendung ist, du aber den Schreibzugriff trotzdem bekommst, wenn du fragst ;-)

PeterPanino 19. Apr 2016 00:27

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von jfheins (Beitrag 1335810)
Zitat:

Zitat von PeterPanino (Beitrag 1335783)
Da wäre eine Routine recht praktisch, mit der man (direkt, also nicht durch Rückschlüsse) herausfinden kann, mit welchen Flags eine Datei geöffnet ist. Gibt's denn sowas?

Eventuell, aber wofür? Wenn du die Datei in einem Programm öffnen willst, wirst du ja schon sehr genau wissen, was due machen musst. (ALso ob der Bneutzer Öffnet oder speichert)

Und das einzige, was hier sinnvoll ist, ist die Aktion zu probieren. Und wenn es nicht ging, dann gab es wohl ein Problem und man kann eine Fehlermeldung anzeigen. Die Info, ob eine Datei schreibbar ist, ist ja in dem Moment schon veraltet (und damit nutzlos) in dem die sie bekommst. Stell dir eine Anwendung vor, die 10 Mal pro Sekunde eine Datei exklusiv zum schreiben öffnet, eine Zeile schreibt und wieder schließt. Doofes Programm, aber kann man machen. Und du versuchst, die gleiche Datei zu öffnen.
Wenn du dann sowas machst wie
Delphi-Quellcode:
if IsFileReadable(AHTMLFile) then
  ThisHTMLStr := TFile.ReadAllText(AHTMLFile)
else
  LogThisError;
Ist dein Programm instabil, weil es dennoch zu einer Exception kommen kann!
Denk' immer dran, dein Programm kann jederzeit unterbrochen werden. Und bevor du wieder drankommst können potenziell alle anderen Prozesse im System laufen.


Und dann bin ich gerade noch auf opportunistic locks gestoßen. EIn Programm kann damit eine Datei zum schreiben öffnen und wird benachrichtigt, wenn ein zweites Programm schreiben möchte um dann seinen Zugriff zu beenden.
Es könnte also sein, dass die Datei zwar in Verwendung ist, du aber den Schreibzugriff trotzdem bekommst, wenn du fragst ;-)

Danke für die Informationen!

PeterPanino 19. Apr 2016 00:30

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Wie ich jetzt entdeckt habe, entsteht seltsamerweise kein Fehler, wenn eine .DOC-Datei (also NICHT .DOCX) gelesen wird, während sie in MS Word 2010 geöffnet ist.

Seltsam!

mm1256 19. Apr 2016 05:36

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Wirklich seltsam. Bei mir (Windows 8.1, Word 2010, lokaler Zugriff, also kein Netzwerk) kann ich keinen Unterschied zwischen .doc und .docx feststellen. Beide können gelesen, aber natürlich nicht beschrieben werden, wenn sie in Word geöffnet sind.

jaenicke 19. Apr 2016 08:51

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Das kommt auf die Art und Weise an mit der der Zugriff erfolgt. Das Auslesen einer .doc geht auch ohne share write, weil diese für die neue Word Version konvertiert und nicht direkt geöffnet wird.
Die .docx wird hingegen direkt geöffnet und kann daher nur mit share write Flag geöffnet werden.

Neutral General 19. Apr 2016 09:49

AW: Wie feststellen, ob eine Datei gelesen werden kann?
 
Zitat:

Zitat von jfheins (Beitrag 1335810)
Und dann bin ich gerade noch auf opportunistic locks gestoßen.

Habe hier nur Delphi 7 und da fehlt der ganze Kram aus der WinIoCtl.h. Wie ist es bei den neueren Delphi Versionen?


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