2010-03-15 71 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 
相關問題