它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
答案 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