1

I have a small script, C:\so\test.ps1, whose contents is:

Invoke-Expression 'using module .\notarealmodule.psm1'

This script intentionally references a non-existent module in order to throw an error.

When I run this script without redirection, I receive the expected output in $out:

PS C:\so> $out = & "C:\Program Files\PowerShell\7\pwsh.exe" -File ".\test.ps1"
PS C:\so> $out
Invoke-Expression: C:\so\test.ps1:1
Line |
   1 |  Invoke-Expression 'using module .\notarealmodule.psm1'
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The specified module 'C:\so\notarealmodule.psm1' was not loaded because no valid module file was found in any
     | module directory.

However, once I add redirection, the output is empty:

PS C:\so> $out = & "C:\Program Files\PowerShell\7\pwsh.exe" -File ".\test.ps1" 2>&1
PS C:\so> $out
PS C:\so> $out = & "C:\Program Files\PowerShell\7\pwsh.exe" -File ".\test.ps1" 1>$null
PS C:\so> $out
PS C:\so> $out = & "C:\Program Files\PowerShell\7\pwsh.exe" -File ".\test.ps1" 2>$null
PS C:\so> $out

What is going on here??

I was able to reproduce this issue with System.Diagnostics.Process. Here is the contents of C:\so\testprocess.ps1:

$proc = [System.Diagnostics.Process]::new()
$proc.StartInfo.FileName = "C:\Program Files\PowerShell\7\pwsh.exe"
$proc.StartInfo.Arguments = "-File $PSScriptRoot\test.ps1"
$proc.StartInfo.UseShellExecute = $false
$proc.StartInfo.RedirectStandardOutput = $true
$proc.StartInfo.RedirectStandardError = $true
$proc.StartInfo.CreateNoWindow = $true
[void]($proc.Start())
Write-Host ($proc.StandardOutput.ReadToEnd())
Write-Host ($proc.StandardError.ReadToEnd())
[void]($proc.WaitForExit())

Nothing is output when running this script.

PS C:\so> .\testprocess.ps1


PS C:\so>

This issue is not reproducible on PS 7.1.0:

PS C:\so> $out = & "C:\Program Files\PowerShell\7\pwsh.exe" -File ".\test.ps1" 2>&1
PS C:\so> $out
Invoke-Expression: C:\so\test.ps1:1
Line |
   1 |  Invoke-Expression 'using module .\notarealmodule.psm1'
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The specified module 'C:\so\notarealmodule.psm1' was not loaded because no valid module file was found in any
     | module directory.
PS C:\so>.\testprocess.ps1
Invoke-Expression: C:\so\test.ps1:1
Line |
   1 |  Invoke-Expression 'using module .\notarealmodule.psm1'
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The specified module 'C:\so\notarealmodule.psm1' was not loaded because no valid module file was found in any
     | module directory.

PS C:\so>

What kind of evil witchcraft is happening with PS 7.0.0 whereby the error message from Invoke-Expression ends up in $out when using & with no redirection, but doesn't end up in the output from System.Diagnostics.Process??? Is there a third stream (other than stdout/stderr) that only & (with no redirection) knows about?

Marco van Hilst
  • 579
  • 5
  • 11
  • 1
    Why not just call the ps1? `& ".\test.ps1"` – Abraham Zinala Mar 09 '21 at 12:55
  • I want to spawn it in a new PS session, and capture all the output. – Marco van Hilst Mar 09 '21 at 17:37
  • In a new Pssession? Such as a new window? Or a thread, or runspace? (I'm aware a new window will create a new instance of a runspace.) – Abraham Zinala Mar 09 '21 at 18:20
  • Regardless, my goal isn't to solve the original problem (I have workarounds for that). I just want to understand this particular behavior which shouldn't be happening and is forcing me to work around it. I think this behavior can be reproduced with calls to other programs, not just pwsh.exe. – Marco van Hilst Mar 09 '21 at 18:59
  • I can reproduce this on PS 7.0.0 but not 7.1.0. Seems to have been fixed in 7.1.0. Might be related to this fix: https://github.com/PowerShell/PowerShell/pull/13361 – Marco van Hilst Mar 09 '21 at 19:12

0 Answers0