admin管理员组

文章数量:1318570

I use [System.IO.Directory]::EnumerateDirectories() in PowerShell instead of get-child item mainly because it is faster. But I have noticed that on a System.UnauthorizedAccessException exception returns only the first exception.

Is that a bug, or am I doing something wrong?

I use [System.IO.Directory]::EnumerateDirectories() in PowerShell instead of get-child item mainly because it is faster. But I have noticed that on a System.UnauthorizedAccessException exception returns only the first exception.

Is that a bug, or am I doing something wrong?

Share Improve this question edited Jan 21 at 13:17 dthorbur 1,1013 gold badges13 silver badges26 bronze badges asked Jan 21 at 11:02 ZaverZaver 93 bronze badges 2
  • 2 Please, DO NOT post images of code, data, error messages, etc., see How do I ask a good question? – iRon Commented Jan 21 at 11:15
  • We pretty much NEVER want to see a screen shot of your terminal here. – Joel Coehoorn Commented Jan 21 at 15:43
Add a comment  | 

1 Answer 1

Reset to default 1

Not a bug, it's the expected behavior of a .NET class method, when there is an error it throws, thus ending the enumeration.

A very easy way to demo this without needing to compile C# code:

# NOTE: If you were to use the workaround shown for PowerShell 5.1
#       using the `while` loop you could enumerate this completely.

$enumerable = [System.Linq.Enumerable]::Select(
    [System.Linq.Enumerable]::Range(0, 10),
    [System.Func[int, int]] {
        if ($args[0] -ne 5) { return $args[0] }
        throw 'woops' })

foreach ($i in $enumerable) { $i }

The concept of a non-terminating error only exists for PowerShell commands, however there are workarounds for your issue.

  • In PowerShell 7+, the easiest way to handle it, is to use the EnumerationOptions class:

    # NOTE:
    #    - Sets `IgnoreInaccessible` to `true` by default
    #    - By default skips Hidden and System. To not skip those use:
    #      `AttributesToSkip = [System.IO.FileAttributes]::None`
    
    [System.IO.Directory]::EnumerateDirectories(
        'E:\test2', '*',
        [System.IO.EnumerationOptions]@{ RecurseSubdirectories = $true })
    
  • In PowerShell 5.1, the class used above doesn't exist in .NET Framework, thus more work is needed. What you can do here is to manually enumerate your enumerable:

    $enumerable = [System.IO.Directory]::EnumerateDirectories(
        'E:\test2', '*',
        [System.IO.SearchOption]::AllDirectories)
    
    $enumerator = $enumerable.GetEnumerator()
    
    while ($true) {
        try {
            # we're done if this is true
            if (-not $enumerator.MoveNext()) {
                break
            }
    
            $enumerator.Current
        }
        catch {
            # PowerShell always wraps method exceptions in `MethodInvocationException`,
            # it's safe to use `.InnerException` in this case
            Write-Error -Exception $_.Exception.InnerException
        }
    }
    

本文标签: