views:

42

answers:

2

Hello,

It seems like FileSystem.GetFiles() is unable to recover from the UnauthorizedAccessException exception that .Net triggers when trying to access an off-limit directory.

In this case, does it mean this class/method isn't useful when scanning a whole drive and I should use some other solution (in which case: Which one?)?

Here's some code to show the issue:

Private Sub bgrLongProcess_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgrLongProcess.DoWork
    Dim drive As DriveInfo
    Dim filelist As Collections.ObjectModel.ReadOnlyCollection(Of String)
    Dim filepath As String

    'Scan all fixed-drives for MyFiles.*
    For Each drive In DriveInfo.GetDrives()
        If drive.DriveType = DriveType.Fixed Then
            Try
                'How to handle "Access to the path 'C:\System Volume Information' is denied." error?
                filelist = My.Computer.FileSystem.GetFiles(drive.ToString, FileIO.SearchOption.SearchAllSubDirectories, "MyFiles.*")
                For Each filepath In filelist
                  DataGridView1.Rows.Add(filepath.ToString, "temp")
                  'Trigger ProgressChanged() event
                  bgrLongProcess.ReportProgress(0, filepath)
                Next filepath
            Catch Ex As UnauthorizedAccessException
                'How to ignore this directory and move on?
            End Try
        End If
    Next drive
End Sub

Thank you.


Edit: What about using a Try/Catch just to have GetFiles() fill the array, ignore the exception and just resume?

Private Sub bgrLongProcess_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgrLongProcess.DoWork
    'Do lengthy stuff here
    Dim filelist As Collections.ObjectModel.ReadOnlyCollection(Of String)
    Dim filepath As String

    filelist = Nothing
    Try
        filelist = My.Computer.FileSystem.GetFiles("C:\", FileIO.SearchOption.SearchAllSubDirectories, "MyFiles.*")
    Catch ex As UnauthorizedAccessException
        'How to just ignore this off-limit directory and resume searching?
    End Try

    'Object reference not set to an instance of an object
    For Each filepath In filelist
        bgrLongProcess.ReportProgress(0, filepath)
    Next filepath
End Sub
+1  A: 

Put your try catch statement within your For each filepate in filelist loop. Because right now, when you catch UnauthorizedAccessException, you skip out on the rest of the filelist items.

Edit

You are right. A try-catch is expensive when an exception is thrown, and usually you want to try and detect that situation before the exception is thrown. One way to do that in this situation, is to check for Access to the file, before doing anything with it.

For directories, there is this GetAccessControl function. There is a similar function for Files.

You may have to break your GetFiles function to only get Directories initially, then loop through each directory recursively always calling GetAccessControl for each directory and file.

mlsteeves
Thanks for the tip, but I read that a Try/Catch is costly and shouldn't be put in a loop. What about using a Try/Catch just to fill an array with FileSystem.GetFiles()?
OverTheRainbow
Thanks, I'll check out GetAccessControl so I can resume in case this directory is off-limit.
OverTheRainbow
A: 

For those interested, I found the following working solution:

http://dotnetperls.com/recursive-file-directory-vbnet

If you want to filter the search to a given type of files (eg. "MyFiles.*"), change

Public Shared Function GetFilesRecursive(ByVal initial As String, ByVal extension As String) As List(Of String)

... so you can call it this way:

Dim list As List(Of String) = FileHelper.GetFilesRecursive("C:\", "MyFiles.*")
OverTheRainbow