Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   IsFileInUse mit CreateFile (https://www.delphipraxis.net/194254-isfileinuse-mit-createfile.html)

omp 3. Nov 2017 10:35

IsFileInUse mit CreateFile
 
Hallo. Um zu prüfen, ob eine Datei geöffnet ist, verwendet man gerne
Code:
function IsFileInUse(const AFileName: string; ANeedWriteAccess: boolean): boolean;
var LFileRes: HFILE;
    LAccess : DWord;
begin
  if ANeedWriteAccess then
    LAccess := GENERIC_READ or GENERIC_WRITE
  else
    LAccess := GENERIC_READ;
  LFileRes := CreateFile(pchar(AFileName),
                         LAccess, 0, nil,
                         OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0);
  result := (LFileRes = INVALID_HANDLE_VALUE);
  if not result then
    CloseHandle(LFileRes);
end;
Der Code wird in diversen Foren und auf Tipp-Seite genannt und er funktionierte auch seit Jahren, dachte ich.

Als Win32-Application ist alles ok.

Als Win64 kompiliert und die .exe ausgeführt: Es wird nicht erkannt, dass die Datei geöffnet ist. Es gibt keine Exception.

Als Win64 im Delphi-Debugger ausgeführt verhält dich das Programm anders:
1. "Im Projekt .. ist eine Exception der Klasse $C0000008 mit der Meldung 'c0000008 INVALID_HANDLE' aufgetreten."
2. Dann die Fehlermeldung im Programm "Externe Exception C0000008". Diese kommt aber nicht, wenn ohne Debugger ausgeführt.
Tritt bei CloseHandle auf. LFileRes ist ein großer Integerwert, also <> INVALID_HANDLE_VALUE.

Habe auch ein neues Delphi-Projekt (10.2 Tokyo) angelegt und konnte es auch damit nachvollziehen.

Jetzt habe ich ein Fragezeichen auf dem Kopf.

jbg 3. Nov 2017 11:06

AW: IsFileInUse mit CreateFile
 
Ersetze mal HFILE durch THandle (der eigentliche Rückgabetyp von CreateFile). HFILE ist nur 32-Bit groß, THandle 64-Bit.

HFILE gehört zu OpenFile() und das stammt aus der 16-Bit Windows Welt.

himitsu 3. Nov 2017 11:50

AW: IsFileInUse mit CreateFile
 
Und Exceptions gibt es hier standardmäßig auch keine.
Darum wird bei solchen Funktionen auch gern auf einen Ressourcenschutzblock verzichtet. (Try-Finally)

Willst du wirklich Gründe für das nichtfunktionieren wissen, muß due die Results und GetLastError bei den WinAPIs (CreateFile und CloseHandle) auswerten.
Da wäre dann auch aufgefallen, wenn die Hälfte vom Wert "INVALID_HANDLE_VALUE" aka HANDLE(-1) fehlt.

Windows HANDLE = Delphi THandle

omp 3. Nov 2017 11:51

AW: IsFileInUse mit CreateFile
 
Zitat:

Zitat von jbg (Beitrag 1384922)
Ersetze mal HFILE durch THandle

Einfach. Schnell. Kompetent.
Danke Dir.

Glados 3. Nov 2017 11:52

AW: IsFileInUse mit CreateFile
 
Probier es mal so. Sollte funktionieren. Wurde bei Google zusammengesucht

Delphi-Quellcode:

{$IFDEF WIN32}

function IsFileInUse(const FileName: string): Boolean;
asm
 push ebx
 push 0
 push 0
 push OPEN_EXISTING
 push 0{nil}
 push 0
 push GENERIC_READ
 push &FileName
 call CreateFile
 cmp eax, INVALID_HANDLE_VALUE
 setz bl
 push eax
 call CloseHandle
 mov al, bl
 pop ebx
end;

{$ELSE}

function IsFileInUse(const FileName: string): Boolean;
var
 h: THandle;
begin
 h := CreateFile(PChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0);
 Result := h = INVALID_HANDLE_VALUE;
 CloseHandle(h);
end;

{$ENDIF}

p80286 3. Nov 2017 12:48

AW: IsFileInUse mit CreateFile
 
Und das funktioniert auch wenn der Frager keine Leserechte besitzt?

Gruß
K-H

Glados 3. Nov 2017 12:55

AW: IsFileInUse mit CreateFile
 
Hab ich nicht getestet, keine Ahnung.
Aber wenn man keine Leserechte hat, ist doch eh Hopfen und Malz verloren oder nicht?

Für das simple Auslesen sollte es aber reichen.

omp 3. Nov 2017 13:01

AW: IsFileInUse mit CreateFile
 
Danke für die Hinweise. Mein Fehler lag an HFILE. Das geht unter Win64 nicht mehr. Also bitte THandle verwenden.

Zitat:

Zitat von p80286 (Beitrag 1384954)
Und das funktioniert auch wenn der Frager keine Leserechte besitzt?

Tatsächlich gibt es bei der Prüfung noch einiges zu beachten. Beispielsweise beim Aufruf mit ANeedWriteAccess:
CreateFile mit "GENERIC_READ or GENERIC_WRITE" scheitert auch, wenn das ReadOnly-Attribut gesetzt ist.

Gruß und Dank.

Zacherl 3. Nov 2017 15:21

AW: IsFileInUse mit CreateFile
 
Solche Funktionen sind ehrlich gesagt fast immer Schwachsinn (ähnlich wie vor bestimmten Aktionen zu prüfen, ob der Benutzer Adminrechte besitzt). Die Problematik mit den Zugriffsrechten wurde ja schon genannt. Warum nicht einfach zu dem Zeitpunkt, an dem man versucht die Datei zu öffnen auf entsprechende Fehler reagieren?


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