Reputation: 8224
Say you have two scripts,
outer.ps1
function Main()
{
Write-Host "starting outer"
TryRun "outer" {
& $PSScriptRoot\inner.ps1
}
}
Main
and inner.ps1
function ThrowError()
{
throw "Error"
}
function Main()
{
Write-Host "starting inner"
TryRun "inner" {
ThrowError
}
}
Main
where TryRun
is defined same in both and defined as:
function TryRun([string] $name, [scriptblock] $action)
{
try
{
$action.Invoke()
Write-Host "'$name' successfully finished"
Exit 0
}
catch [System.Exception]
{
$separator = New-Object string @("-", 120)
Write-Error "'$name' failed`n$separator`n$($_.Exception.ToString())`n$separator"
Exit 1
}
}
Now, the problem is, when you execute outer.ps1
, the output is:
starting outer
starting inner
<exception should have been printed here, but it was not>
'outer' successfully finished
However, starting inner.ps1
directly proves, it's behaving as expected:
TryRun : 'inner' failed
-------------------------------------------------------------------------------
-----------------------------------------
System.Management.Automation.RuntimeException: Error --->
System.Management.Automation.RuntimeException: Error
--- End of inner exception stack trace ---
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(F
unctionContext funcContext, Exception exception)
...
And what's more funny - if you change Write-Error
to Write-Host
and execute outer.ps1
the exception is getting printed
I also tried flushing Console.Out, etc
buffers before doing Exit
, but that did not help
Now, why is it behaving like that? What is the reason PS is not outputting exception before exit? Debugging session shows it always gets into catch and executes that Write-Error
Upvotes: 2
Views: 759
Reputation: 3686
The reason is because you are using .invoke() on a scriptblock. .invoke() returns a collection of PSObjects. From what I understand, all data written into the output pipe is returned back to the caller; Eg: {"a"}.invoke()
will return "a" , however, for some reason the contents of the error pipe is eaten or discarded (not sure why??).
You can fix your script by using the call operator &
. So changing $action.Invoke()
to & $action
in outer.ps1
should fix your problem.
Note: You should still be able to get error inside .invoke()
using $error
as in - {write-error "a"}.invoke(); $error
Upvotes: 2