powershellerror-handlingtry-catchget-childitem

Trap error from Get-Childitem when access to directory is denied


I'm trying to trap errors using a try/catch block with Get-Childitem but it isn't working. Here is an excerpt of my code:

if((Test-Path .\test.txt)){
    $key = Get-Content -Path .\test.txt
} else {
  write-host "test.txt file not found in current folder. Searching for it in other folders." -ForegroundColor DarkCyan
  try {
        $key = @(gci -path $env:USERPROFILE -file test.txt -Recurse -ErrorVariable ers )[0]  
      } catch [System.UnauthorizedAccessException]{ 
        write-warning -Message "Folder offlimits" 
      } catch [RuntimeException]{
        write-warning -Message "Some other error occured"  
      } finally {
        write-host $key.FullName
      }
            
}

I know I can just use -erroraction silentlycontinue but I'm really just trying to figure out how to trap the error. I tried using $error[0].Exception.gettype().fullname to determine what the error was to trap it but I used what it returned and it didn't trap it. I don't want to use -filter or -include/exclude because there are just too many of them.

and $ers is:

    gci : Access to the path 'C:\User\Search\Data' is denied.
At line:6 char:26
+ ...    $key = @(gci -path $env:USERPROFILE -file test.txt -Recurse  -Error ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (C:\User\Search\Data:String) [Get-ChildItem], UnauthorizedAccessException
    + FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

which is the same thing $error[0] contains. I'm using 5.6.1 right now but I'm transitioning to 7. This is on Windows 10 if that matters. I'm stumped. Any thoughts?


Solution

  • Tl;dr: you need either add -ErrorAction Stop or change the value of $ErrorActionPreference

    if ((Test-Path .\test.txt)) {
        $key = Get-Content -Path .\test.txt
    }
    else {
        Write-Host 'test.txt file not found in current folder. Searching for it in other folders.' -ForegroundColor DarkCyan
    
        try {
            # -ErrorAction Stop will thow an Terminating Error that Catch can catch.
            # Using Select-Object -First 1 should stop Get-ChildItem after getting
            # the first result; useful to avoid traversing the whole directory and
            # subs.
            $key = Get-ChildItem -Path $env:USERPROFILE -File -Filter test.txt -Recurse -ErrorAction Stop -ErrorVariable ErrorGCI | Select-Object -First 1 
            Write-Host $key.FullName
        }
        # Catch only [UnauthorizedAccessException] type of errors
        # In this case is mostly when you don't have the permission to a directory
        catch [System.UnauthorizedAccessException] { 
            # also added the target of the error so you can know what directory did trigger the issue
            Write-Warning -Message "Folder '$($ErrorGCI.errorrecord.targetobject)' offlimits"
        }
        # Removed the [RuntimeException] specification: as it's higher level than
        # [UnauthorizedAccessException], it would intercept the errors before the
        # more specific Catch
        catch {
            # you might want to improve the error description
            Write-Warning -Message 'Some other error occured' 
        }
        finally {
            # Finally{} is used for operations happening regardless the TRY block succeeds or not. 
            # In this specific example, it's useless.
            # Unless you want to print an empty line in case of errors, I guess.
        }
                    
    }