|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic File API Routines CreateFile: Test if a File is Open by Another Application |
|
Posted: | Thursday November 25, 2004 |
Updated: | Monday December 26, 2011 |
Applies to: | VB4-32, VB5, VB6 |
Developed with: | VB6, Windows XP |
OS restrictions: | None |
Author: | VBnet - Randy Birch |
Related: |
GetLogicalDriveStrings: An API 'DriveExists' Routine FindFirstFile: An API 'FileExists' Routine FindFirstFile: An API 'FolderExists' Routine |
Prerequisites |
None. |
|
Most
well-behaved applications open and lock files to prevent inadvertent or
deliberate changes to the file contents by other applications while the
file is being used. Others, like Notepad, open the file, read the data,
then close the file immediately without placing a lock on the file. This routine is for use with the former access method, and will return True if another application has the file open, or False if not. For files opened with apps like Notepad, it will always return false. For apps like WordPad, it will return True if both the file and app are on the local machine, but False if file is on a remote machine. (Some locks apparently are different than others, and the CreateFile and CreateFileEx APIs does have special flags that can be used by applications to indicate other apps can open files for joint access, both for read and write.) Assuming then that the application opening the file places a proper lock on the file, this routine will correctly detect if:
The remote file to be tested can be specified using either mapped drives (e.g. z:\filename.exe), UNC format (e.g \\server\share\filename.ext), machine name (e.g. \\vbnetdev\share\filename.ext), or IP address within the network (e.g \\192.168.1.102\share\filename.ext). The routine works by attempting to obtain a handle to the file using the GENERIC_READ and OPEN_EXISTING flags. If the function is unable to obtain a handle because of a file lock (hFile = -1) the IsFileInUse routine returns True. If a handle is obtained (hFile <> 0), the function returns False. If you have access to other machines to perform remote tests, use Word to open the app. If Word is not available see the Comments section below for some quick code that will lock a specified file. |
BAS Module Code |
None. |
|
Form Code |
Create a new project with a form containing one text box (Text1), one label (Label1) and a command button (Command1). Add the following code: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const GENERIC_READ As Long = &H80000000 Private Const INVALID_HANDLE_VALUE As Long = -1 Private Const OPEN_EXISTING As Long = 3 Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80 Private Const MAX_PATH As Long = 260 'Enum containing values representing 'the status of the file Private Enum IsFileResults FILE_IN_USE = -1 'True FILE_FREE = 0 'False FILE_DOESNT_EXIST = -999 'arbitrary number, other than 0 or -1 End Enum Private Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Private Type WIN32_FIND_DATA dwFileAttributes As Long ftCreationTime As FILETIME ftLastAccessTime As FILETIME ftLastWriteTime As FILETIME nFileSizeHigh As Long nFileSizeLow As Long dwReserved0 As Long dwReserved1 As Long cFileName As String * MAX_PATH cAlternate As String * 14 End Type Private Declare Function CreateFile Lib "kernel32" _ Alias "CreateFileA" _ (ByVal lpFileName As String, _ ByVal dwDesiredAccess As Long, _ ByVal dwShareMode As Long, _ ByVal lpSecurityAttributes As Long, _ ByVal dwCreationDisposition As Long, _ ByVal dwFlagsAndAttributes As Long, _ ByVal hTemplateFile As Long) As Long Private Declare Function CloseHandle Lib "kernel32" _ (ByVal hFile As Long) As Long Private Declare Function FindFirstFile Lib "kernel32" _ Alias "FindFirstFileA" _ (ByVal lpFileName As String, _ lpFindFileData As WIN32_FIND_DATA) As Long Private Declare Function FindClose Lib "kernel32" _ (ByVal hFindFile As Long) As Long Private Sub Form_Load() Command1.Caption = "IsFileInUse" Text1.Text = "d:\test.doc" Label1.Caption = "" End Sub Private Sub Command1_Click() Dim bResult As IsFileResults bResult = IsFileInUse(Text1.Text) Select Case bResult Case FILE_IN_USE Label1.Caption = "File in use" Case FILE_FREE Label1.Caption = "File is available" Case FILE_DOESNT_EXIST Label1.Caption = "File does not exist!" End Select Label1.Caption = Label1.Caption & " (" & bResult & ")" End Sub Private Function IsFileInUse(sFile As String) As IsFileResults Dim hFile As Long If FileExists(sFile) Then 'note that FILE_ATTRIBUTE_NORMAL (&H80) has 'a different value than VB's constant vbNormal (0)! hFile = CreateFile(sFile, _ GENERIC_READ, _ 0, 0, _ OPEN_EXISTING, _ FILE_ATTRIBUTE_NORMAL, 0&) 'this will evaluate to either '-1 (FILE_IN_USE) or 0 (FILE_FREE) IsFileInUse = hFile = INVALID_HANDLE_VALUE CloseHandle hFile Else 'the value of FILE_DOESNT_EXIST in the Enum 'is arbitrary, as long as it's not 0 or -1 IsFileInUse = FILE_DOESNT_EXIST End If End Function Private Function FileExists(sSource As String) As Boolean Dim WFD As WIN32_FIND_DATA Dim hFile As Long hFile = FindFirstFile(sSource, WFD) FileExists = hFile <> INVALID_HANDLE_VALUE Call FindClose(hFile) End Function |
Comments |
This will create a test app you can use to enter a file, remote or
local, and have the tool lock the file for testing the code above. Note
that the Open method used will create any mistyped filename, so check
for stray 0-length files after testing.
Private hFile As Long Private Sub Form_Load() Text1.Text = "" Me.Caption = "ready" End Sub Private Sub Command1_Click() On Local Error GoTo oops hFile = FreeFile Open Text1.Text For Binary Access Read Lock Read As #hFile Caption = "file handle: " & hFile oops_out: Exit Sub oops: MsgBox Err.Number & vbCrLf & Err.Description Resume oops_out End Sub Private Sub Command2_Click() Close hFile = 0 Me.Caption = "ready" End Sub |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |