windowspowershellcicdwindows-subsystem-for-linuxpowershell-7.3

`Get-ChildItem` does not throw a `cannot find path` error in a class function of PowerShell as expected


I'm working on a dev tool based on PowerShell. But it always failed in Ubuntu-Latest CI/CD tests. If interested, please check the GitHub Link of Actions

After a day of trying, I found and minimized the process of reproducing the problem.

Consider a directory ${Home}/test/ with a file test_in_method.ps1 and a file test_out_of_method.ps1 as:

${Home}/test/
|----test_in_method.ps1
|----test_out_of_method.ps1
|----(no other items, i.e., no other dirs or files)

The test_in_method.ps1 is as:

# PowerShell 7.3.6 on Windows Or Linux
# test_in_method.ps1
class FormattedFileSystemPath {
    FormattedFileSystemPath([string] $Path) {
        $link_target  = $this.PreProcess()
    }
    [string] PreProcess(){
        Write-Verbose "PWD is:$PWD" -Verbose
        return (Get-ChildItem 'usr'| Where-Object Name -eq 'sbin')
    }
}
Write-Verbose ([FormattedFileSystemPath]::new('???')) -Verbose

, and the test_out_of_method.ps1 is as:

# PowerShell 7.3.6 on Windows Or Linux
# test_out_of_method.ps1
class FormattedFileSystemPath {

    FormattedFileSystemPath([string] $Path) {
        Write-Verbose "PWD is:$PWD" -Verbose
        $link_target = (Get-ChildItem 'usr'| Where-Object Name -eq 'sbin')
    }
}
Write-Verbose ([FormattedFileSystemPath]::new('???')) -Verbose

First, test test_in_method.ps1 as:

pwsh
cd "${Home}/test/"
./ test_in_method.ps1

The output is:

VERBOSE: PWD is:C:\Users\User\test
VERBOSE: FormattedFileSystemPath

Second, test test_out_of_method.ps1 as:

pwsh
cd "${Home}/test/"
./ test_out_of_method.ps1

The out put is:

VERBOSE: PWD is:C:\Users\User\test
Get-ChildItem: C:\Users\User\test\test_out_of_method.ps1:7
Line |
   7 |          $link_target = (Get-ChildItem 'usr'| Where-Object Name -eq 's …
     |                          ~~~~~~~~~~~~~~~~~~~
     | Cannot find path 'C:\Users\User\test\usr' because it does not exist.
VERBOSE: FormattedFileSystemPath

Expected behavior: both test_in_method.ps1 and test_out_of_method.ps1 throw cannot find path errors

Actual behavior: only test_out_of_method.ps1 throws cannot find path errors but test_in_method.ps1 does not.

I have tested on my local machines, and both Windows 11 (PowerShellv7.3.6) and WSL2(PowerShellv7.3.5) show the above phenomenon.

Even more strangely, when put into a CI/CD environment, see here, either of the above writes (whether put Get-ChildItem into a class function or a constructor function) can both throw errors as expected.

What's the problem? Why? And how can I deal with it? Why Get-ChildItem does not throw a cannot find path error in the class method as expected?

Thanks in advance.


Solution

  • The problem has 2 aspects and can be answered respectively:

    And how to do it?

    I think the best way is as @Santiago Squarzon's comments, adding -ErrorAction Stop to Get-ChildItem in class methods. Because it follows the principle of Occam's Razor, with the minimized scope of changes.

    Thanks for every above comments and advice.