FileSystem.GetFiles()+ UnauthorizedAccessException错误?

时间:2010-03-15 19:00:48

标签: vb.net file error-handling find

seems like FileSystem.GetFiles()无法从尝试访问禁止目录时.Net触发的UnauthorizedAccessException异常中恢复。

在这种情况下,是否意味着这个类/方法在扫描整个驱动器时没用,我应该使用其他解决方案(在这种情况下:哪一个?)?

以下是一些显示问题的代码:

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

谢谢。


编辑:使用Try / Catch只是让GetFiles()填充数组,忽略异常并恢复?

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

3 个答案:

答案 0 :(得分:1)

将try catch语句放在For each filepate in filelist循环中。因为现在,当您抓住UnauthorizedAccessException时,您会跳过剩余的filelist项。

修改

你是对的。抛出异常时,try-catch是昂贵的,并且通常您希望在抛出异常之前尝试检测该情况。在这种情况下,一种方法是在执行任何操作之前检查文件的访问权限。

对于目录,有this GetAccessControl功能。文件有is a similar function

您可能必须先将GetFiles函数分解为仅初始化目录,然后递归遍历每个目录,并始终为每个目录和文件调用GetAccessControl

答案 1 :(得分:0)

对于那些感兴趣的人,我找到了以下工作解决方案:

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

如果要将搜索过滤到给定类型的文件(例如“MyFiles。*”),请更改

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

...所以你可以这样称呼它:

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

答案 2 :(得分:0)

我使用以下功能搜索位于系统上的所有驱动器以查找特定文件,并且当' GetFiles'击中一个execption。这是通过使用' GetDirectories'执行顶级搜索来完成的。这将为您提供一个基本级别的目录列表,如果它没有抛出一个execption' GetFiles'执行该目录的所有子目录的搜索,如果执行了一个execption,那么' GetDirectories'找到目录,然后继续该过程。每次成功搜索后,由GetFiles'包含搜索文件的目录存储在列表中。一旦搜索了系统上所有现有的驱动器,main函数就会通过返回已添加到列表中的数据来结束操作。

Public Function Left(ByVal TextString As String, ByVal LocateString As String) As String
    Try
        Left = Microsoft.VisualBasic.Left(TextString, InStrRev(TextString, LocateString) - 1)
    Catch ex As Exception
        Left = TextString
    End Try
End Function

Public Function GetExistingDrives() As List(Of String)
    Dim LocatedDrives As New List(Of String), DriveInformation As System.IO.DriveInfo() = System.IO.DriveInfo.GetDrives
    For Each FoundDrive As System.IO.DriveInfo In DriveInformation
        Try
            LocatedDrives.Add(UCase(Left(FoundDrive.Name, "\")))
        Catch ex As Exception
        End Try
    Next
    GetExistingDrives = LocatedDrives
End Function

Public Function LocateFiles(ByVal ParamArray SearchPattern As String()) As List(Of String)
    Dim LocatedDirectoriesList As New List(Of String), LocatedFilenameList As System.Collections.ObjectModel.ReadOnlyCollection(Of String)
    For Each DriveLetter In GetExistingDrives()
        Try
            For Each SearchDirectory As String In My.Computer.FileSystem.GetDirectories(DriveLetter, FileIO.SearchOption.SearchTopLevelOnly)
                Try
                    LocatedFilenameList = My.Computer.FileSystem.GetFiles(SearchDirectory, FileIO.SearchOption.SearchAllSubDirectories, SearchPattern)
                Catch ex As Exception
                End Try
                If (LocatedFilenameList.Count <> 0) Then
                    For Each LocatedFilename As String In LocatedFilenameList
                        Dim LocatedDirectory As String = Left(LocatedFilename, "\")
                        If (LocatedDirectoriesList.IndexOf(LocatedDirectory) = -1) Then LocatedDirectoriesList.Add(LocatedDirectory)
                    Next
                End If
            Next
        Catch ex As Exception
        End Try
    Next
    LocateFiles = LocatedDirectoriesList
End Function