Kbase P26014: How to detect that a file is in use?
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  6/10/2003 |
|
Status: Unverified
GOAL:
How to detect that a file is in use?
FACT(s) (Environment):
Windows NT 32 Intel/Windows 2000
FACT(s) (Environment):
Windows 32 Intel
FIX:
You can use a code like this:
&SCOPED-DEFINE FILE_SHARE_READ 1
&SCOPED-DEFINE FILE_SHARE_WRITE 2
&SCOPED-DEFINE FILE_SHARE_READ_OR_WRITE 3
&SCOPED-DEFINE GENERIC_READ 2147483648
&SCOPED-DEFINE GENERIC_WRITE 1073741824
&SCOPED-DEFINE GENERIC_READ_OR_WRITE 3221225472
&SCOPED-DEFINE OPEN_EXISTING 3
/*Possible return Error values (multiplied by -1) this is left just for the reference */
&SCOPED-DEFINE INVALID_FILE_HANDLE -1
&SCOPED-DEFINE ERROR_FILE_NOT_FOUND 2
&SCOPED-DEFINE ERROR_PATH_NOT_FOUND 3
&SCOPED-DEFINE ERROR_ACCESS_DENIED 5
&SCOPED-DEFINE ERROR_INVALID_DRIVE 15
&SCOPED-DEFINE ERROR_DEVICE_NOT_READY 21
&SCOPED-DEFINE ERROR_SHARING_VIOLATION 32
&SCOPED-DEFINE ERROR_LOCK_VIOLATION 33
&SCOPED-DEFINE ERROR_NETWORK_UNREACHABLE 1231
PROCEDURE CreateFileA EXTERNAL "kernel32":
DEFINE INPUT PARAMETER lpFileName AS CHARACTER.
DEFINE INPUT PARAMETER dwDesiredAccess AS LONG.
DEFINE INPUT PARAMETER dwShareMode AS LONG.
DEFINE INPUT PARAMETER lpSecurityAttributes AS LONG.
DEFINE INPUT PARAMETER dwCreationDisposition AS LONG.
DEFINE INPUT PARAMETER dwFlagsAndAttributes AS LONG.
DEFINE INPUT PARAMETER hTemplateFile AS LONG.
DEFINE RETURN PARAMETER RetResult AS LONG.
END.
PROCEDURE CloseHandle EXTERNAL "kernel32":
DEFINE INPUT PARAMETER hObject AS LONG.
DEFINE RETURN PARAMETER RetResult AS LONG.
END.
PROCEDURE CheckFile :
DEFINE INPUT PARAMETER cFileName AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER ChkType AS INTEGER NO-UNDO.
DEFINE VARIABLE hFileHandle AS INTEGER NO-UNDO.
DEFINE VARIABLE RetResult AS INTEGER NO-UNDO.
DEFINE VARIABLE iStatus AS INTEGER NO-UNDO.
DEFINE VARIABLE RetValue AS CHARACTER NO-UNDO.
CASE ChkType:
WHEN 1 THEN DO:
/*Simple check for existance, no read-write desired */
RUN CreateFileA (cFileName, 0, 0, 0, {&OPEN_EXISTING}, 0, 0, OUTPUT RetResult).
END.
WHEN 2 THEN DO:
/* Check whether file lock if available write desired, file lock required */
RUN CreateFileA (cFileName, {&GENERIC_WRITE},
0, 0, {&OPEN_EXISTING}, 0, 0, OUTPUT RetResult).
END.
WHEN 3 THEN DO:
/* Should be 'Read-write desired, share allowed'
however this doesn't work so we set 0 as 4GL complains if
we use other than 0 or 1073741824 */
RUN CreateFileA (cFileName, /*{&GENERIC_READ_OR_WRITE}*/ 0,
/*{&FILE_SHARE_READ_OR_WRITE}*/ 0,
0, {&OPEN_EXISTING}, 0, 0, OUTPUT RetResult).
END.
END CASE.
IF RetResult = -1 THEN RetValue = "NO" .
ELSE RetValue = "YES" .
/* The code bellow can't be used as we can't get the dll error for
the use in the 4GL, so we commented out */
/* IF RetResult <> -1 THEN */
/* CASE RetResult: */
/* WHEN {&INVALID_FILE_HANDLE} THEN RetValue = "INVALID_FILE_HANDLE" . */
/* WHEN {&ERROR_FILE_NOT_FOUND} THEN RetValue = "ERROR_FILE_NOT_FOUND". */
/* WHEN {&ERROR_PATH_NOT_FOUND} THEN RetValue = "ERROR_PATH_NOT_FOUND". */
/* WHEN {&ERROR_ACCESS_DENIED} THEN RetValue = "ERROR_ACCESS_DENIED". */
/* WHEN {&ERROR_INVALID_DRIVE} THEN RetValue = "ERROR_INVALID_DRIVE". */
/* WHEN {&ERROR_DEVICE_NOT_READY} THEN RetValue = "ERROR_DEVICE_NOT_READY". */
/* WHEN {&ERROR_SHARING_VIOLATION} THEN RetValue = "ERROR_SHARING_VIOLATION". */
/* WHEN {&ERROR_LOCK_VIOLATION} THEN RetValue = "ERROR_LOCK_VIOLATION". */
/* WHEN {&ERROR_NETWORK_UNREACHABLE} THEN RetValue = "ERROR_NETWORK_UNREACHABLE". */
/* END CASE. */
/* ELSE RetValue = "File does not exist". . */
IF RetResult <> -1 THEN RUN CloseHandle (RetResult, OUTPUT iStatus) .
RETURN RetValue .
END PROCEDURE.
MAIN_BLOCK:
DO:
/* First check if the file exists */
RUN checkFile ("C:\myFile.txt", 1) .
MESSAGE "File Exist: " RETURN-VALUE
VIEW-AS ALERT-BOX INFO BUTTONS OK.
/* Now check if the file is locked */
RUN checkFile ("C:\myFile.txt", 2) .
IF RETURN-VALUE = "NO" THEN
MESSAGE "File in use"
VIEW-AS ALERT-BOX INFO BUTTONS OK.
ELSE
MESSAGE "File not in use"
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END.
.