Reputation: 571
I want to get all files in a directory, so I have used For Each
loop.
but I got this error and stopped the loop.
System.UnauthorizedAccessException: 'Access to the path 'G:\$RECYCLE.BIN\S-1-5-18' is denied.'
The loop cannot access some of the files because of file permissions. I want to by-pass those files and move to the next file.
how can I do this,
Try
For Each filename As String In Directory.GetFiles(dir_path, pattern, sub_directory)
Console.WriteLine(filename.ToString)
Next filename
Catch ex As Exception
End Try
Upvotes: 2
Views: 570
Reputation: 54457
The loop is irrelevant. It's the call to GetFiles
that is the problem. There is no way to call GetFiles
with the recursive option and simply ignore inaccessible folders. You can only use that method when you know you can access every subfolder. Otherwise, you need to write your own recursive file search and explicitly catch those exceptions and ignore them. There are lots of examples of that on the web.
It should be noted that GetFiles
does the entire search first, creates an array containing all the file paths and returns it, so your loop can't even begin until that's done. Even if this could work, it would still generally be preferable to call EnumerateFiles
if you want to loop through the file paths on the spot. That's because EnumerateFiles
is an iterator, basically returning the file paths one by one. That means that, for instance, you can break out of the loop if a particular condition is met without completing the entire search. EnumerateFiles
will still throw an exception if it finds an inaccessible folder though, so it won't help here. If you do write your own method though, it would be nice to write an iterator if you plan to search big folders or you might not need to use all results.
EDIT:
Here's my home-spun versions. The first one does all the work first while the second is an iterator. Note that you may be able to make the first one more efficient by using a single external list to store all the file paths in rather than creating a new one in every recursive call.
Public Function GetFilesRecursively(path As String, searchPattern As String) As String()
Dim filePaths As New List(Of String)(Directory.GetFiles(path, searchPattern))
For Each folderPath In Directory.GetDirectories(path)
Try
filePaths.AddRange(GetFilesRecursively(folderPath, searchPattern))
Catch ex As UnauthorizedAccessException
'Ignore inaccessible folders
End Try
Next
Return filePaths.ToArray()
End Function
Public Iterator Function EnumerateFilesRecursively(path As String, searchPattern As String) As IEnumerable(Of String)
For Each filePath In Directory.EnumerateFiles(path, searchPattern)
Yield filePath
Next
For Each folderPath In Directory.EnumerateDirectories(path)
Try
For Each filePath In EnumerateFilesRecursively(folderPath, searchPattern)
Yield filePath
Next
Catch ex As UnauthorizedAccessException
'Ignore inaccessible folders
End Try
Next
End Function
Upvotes: 3