2010-03-15 67 views
0

It seems like FileSystem.GetFiles()无法从UnauthorizedAccessException异常中恢复,当尝试访问非限制目录时.Net触发。FileSystem.GetFiles()+ 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 

回答

1

将您的try catch语句放入您的For each filepate in filelist循环中。因为现在,当你赶上UnauthorizedAccessException时,你跳过filelist项目的其余部分。

编辑

你是对的。当抛出异常时,try-catch的代价很高,通常你想在抛出异常之前尝试检测这种情况。在这种情况下做到这一点的一种方法是在做任何事情之前检查文件的访问权限。

对于目录,有this GetAccessControl函数。文件有is a similar function

您可能必须打破您的GetFiles函数才能初始获取目录,然后循环遍历每个目录,每个目录和文件都会递归地循环调用GetAccessControl

+0

感谢您的提示,但我读到Try/Catch是昂贵的,不应该放在一个循环。如何使用Try/Catch来填充FileSystem.GetFiles()数组? – Gulbahar 2010-03-16 11:07:27

+0

谢谢,我会检查出GetAccessControl,这样我可以恢复以防止这个目录被禁止。 – Gulbahar 2010-03-25 12:08:26

0

对于那些有兴趣,我发现了以下工作方案:(。 “MYFILES *” EG)

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

如果你想搜索过滤器给定类型的文件,改变

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.*") 
0

我用个以下功能可以搜索位于系统中的所有驱动器以查找特定文件,并且在'GetFiles'命令执行时不会中断。这是通过使用'GetDirectories'执行顶级搜索来完成的,该GetDirectories将为您提供一个基本级目录列表,如果它不会执行某个执行,则会执行该目录的所有子目录的'GetFiles'搜索,如果执行是然后点击'GetDirectories'目录,并且过程继续。在由'GetFiles'执行的每次成功搜索之后,包含搜索文件的目录都存储在列表中。一旦所有位于系统上的现有驱动器都被搜索完毕,主函数通过返回已添加到列表中的数据来结束操作。

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 
相关问题