2016-02-19 74 views
2

說你有兩個腳本之前,寫入錯誤不打印到控制檯腳本退出

outer.ps1

function Main() 
{ 
    Write-Host "starting outer" 
    TryRun "outer" { 
     & $PSScriptRoot\inner.ps1 
    } 
} 

Main 

inner.ps1

function ThrowError() 
{ 
    throw "Error" 
} 

function Main() 
{ 
    Write-Host "starting inner" 
    TryRun "inner" { 
     ThrowError 
    } 
} 

Main 

其中TryRun在兩個定義相同,定義如下:

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 
    } 
} 

現在的問題是,當你執行outer.ps1,輸出爲:

starting outer 
starting inner 
<exception should have been printed here, but it was not> 
'outer' successfully finished 

但是,在開始inner.ps1直接證明,它表現爲預期:

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) 
    ... 

而且更重要的是有趣的 - 如果您將Write-Error更改爲Write-Host並執行outer.ps1例外正在打印

我也想這樣做Exit前沖洗Console.Out, etc緩衝器,但這並沒有幫助

現在,爲什麼會表現成這樣? PS在退出前不輸出異常的原因是什麼?調試會話顯示它總是陷入困境並執行它Write-Error

+4

看來PowerShell中忽略錯誤流,當你調用腳本塊用'調用()'方法:'{直寫錯誤測試} .Invoke()'。 – PetSerAl

回答

2

原因是因爲您在腳本塊上使用.invoke()。 .invoke()返回PSObjects的集合。據我所知,寫入輸出管道的所有數據都會返回給調用者;例如:{"a"}.invoke()將返回「a」,但是,出於某種原因錯誤管道的內容被吃掉或丟棄(不知道爲什麼?)。

您可以使用呼叫運營商&修復腳本。因此在outer.ps1中將$action.Invoke()更改爲& $action應該可以解決您的問題。

注:您應該仍然能夠使用$error在進去.invoke()錯誤 - {write-error "a"}.invoke(); $error