9

Is there a method to verify that a file is open? The only thing I can think of is the Try/Catch to see if i can catch the file-open exception but I figured that a method be available to return true/false if file is open.

Currently using System.IO and the following code under class named Wallet.

    Private holdPath As String = "defaultLog.txt"
    Private _file As New FileStream(holdPath, FileMode.OpenOrCreate, FileAccess.ReadWrite)
    Private file As New StreamWriter(_file)

    Public Function Check(ByVal CheckNumber As Integer, ByVal CheckAmount As Decimal) As Decimal
        Try
            file.WriteLine("testing")
            file.Close()
        Catch e As IOException
          'Note sure if this is the proper way.
        End Try

        Return 0D
    End Function

Any pointers will be appreciated! Thank you!!

Dayan
  • 7,634
  • 11
  • 49
  • 76

3 Answers3

18
Private Sub IsFileOpen(ByVal file As FileInfo)
    Dim stream As FileStream = Nothing
    Try
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)
        stream.Close()
    Catch ex As Exception

        If TypeOf ex Is IOException AndAlso IsFileLocked(ex) Then
            ' do something here, either close the file if you have a handle, show a msgbox, retry  or as a last resort terminate the process - which could cause corruption and lose data
        End If
    End Try
End Sub

Private Shared Function IsFileLocked(exception As Exception) As Boolean
    Dim errorCode As Integer = Marshal.GetHRForException(exception) And ((1 << 16) - 1)
    Return errorCode = 32 OrElse errorCode = 33
End Function

Call it like this:

Call IsFileOpen(new FileInfo(filePath))
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • 3
    Great solution. I would just add that you need to be sure to stream.close() in case there is no exception, so the program can continue without a problem. – mlerley Nov 21 '12 at 01:42
  • It says Marshal is not declared. – Cary Bondoc Jul 03 '15 at 01:21
  • 3
    @CaryBondoc `Imports System.Runtime.InteropServices;` to fix the *Marshal is not declared* issue. **Tip:** `Marshal` will have a blue little underline, hover the mouse over this and it will give you a hint as to what is wrong! – Jeremy Thompson Jul 03 '15 at 01:23
  • Thanks! It worked. Could you please elaborate more on how to use the code @JeremyThompson. Now it says `Value of type 'String' cannot be converted to 'System.IO.FileInfo'.` – Cary Bondoc Jul 03 '15 at 02:11
  • 4
    `Call IsFileOpen(new FileInfo(filePath))` – Jeremy Thompson Jul 03 '15 at 02:38
  • 1
    What exactly is the bit-shifting check at the end of IsFileLocked() doing? – Rhurac Jun 19 '18 at 19:34
  • Can anyone please post an example of the above code in action? I have followed the above comments but I am unable to even get a file to open using this method. Really need to use this solution for a project that I am working on. Thank you! – Mark Oct 01 '18 at 19:53
  • I have the file open on my computer and I put a Console.WriteLine("File is open") in the "Catch ex As Exception" but it is not throwing. – Mark Oct 01 '18 at 20:36
  • @MarkS you need a process that will lock the file. You can use the code in this answer to lock a file with different `file.Open` parameters – Jeremy Thompson Oct 02 '18 at 08:02
  • I'm sorry, but it has been my experience that opening a file to see if a file is open is just a poor technique. For one, it's not a bulletproof solution since a file can open between the call to see if it is open and the call to do something after. Second, if an unforeseen error occurs during the file open check of opening the file and that error can't be handled, you might have just left a pointer to the file as open, therefore causing the problem you were looking for. The best solution is to simply error handle the action you're performing on the file and if it fails, handle accordingly. – Chase Feb 08 '22 at 13:33
  • Sorry, darn char limit. More often than not, proper and detailed error handling is not given as much attention as it deserves. – Chase Feb 08 '22 at 13:36
  • @Chase Exceptions are supposed to be used exceptionally, though if you've had a history of debugging Memory Dumps using WinDbg you might agree this is a perfectly good exception, see the history and note the dates... https://stackoverflow.com/q/876473/495455 – Jeremy Thompson Feb 08 '22 at 22:05
6

There is really no point using a 'is file in use check' function since you will still need to have try catch to handle the case that the file fails to open. The file open can fail for many more reasons than it just being already open.

Also using a function to do a check is no guarantee of success. The 'is file in use check' might return false only for the file open to fail with a file already open error, because in time between the check and trying to open the file it was opened by someone else.

jussij
  • 10,370
  • 1
  • 33
  • 49
2

It looks like the two suggestions from this MSDN forum posting both involve trying to open the file.

The first one is similar to what you are doing now, and the second involves using a Windows API function (CreateFile) and checking for a invalid handle signifying the file is in use. In both cases they are relying on an error condition to determine if the file is open or not. In short, in my opinion the method you are using is correct since there is not a System.IO.File.IsOpen property.

Mark Hall
  • 53,938
  • 9
  • 94
  • 111
  • 1
    Hi Mark, I'm sure your aware it's customary in StackOverflow answers to include a summary of the contents of a link or the highlights that specifically answer the question. The goal of SE sites is to become a resource of knowledge, of answers, for years to come. With a link-only answer, the op must dig through another resource to locate an answer he/she might not be sure about. Most importantly, if your link were to ever break, your answer is useless for anyone who visits this page in the future. Cheers for the link tho! – Jeremy Thompson Jul 02 '12 at 06:45
  • 1
    @JeremyThompson I aware of that and I do. In this case I made a **conscious** decision not to paste in any code. I was not trying to suggest that this was the proper way to go. I was trying to **reassure** the OP that the way that he was doing it was correct, IMHO. Suggesting that he use the WinApi was not what I was trying to do and in this case overkill. – Mark Hall Jul 02 '12 at 14:35
  • 1
    Thank you Mark, i appreciate your answer and i agree that it is overkill but it did give me a good outlook on the subject! Thanks again :) – Dayan Jul 03 '12 at 13:21