Powershell将std错误重定向到变量

时间:2015-05-07 00:02:27

标签: powershell powershell-v3.0

我想调用任意表达式并将std错误重定向到变量而不重定向到文件。

例如,在Powershell中,可以重定向标准错误using 2> operator。使用临时文件,我可以很容易地得到我想要的东西:

#$expr = "1/0"                          # with std error
#$expr = "2+2"                          # without stderror
#$expr = "Get-Service invalidsvc"       # with stderror
$expr = "try { throw '111' } catch { }" # without std error
$ans = Invoke-Expression $expr -ErrorVariable ev 2> C:\log\stderr.txt
if(cat C:\log\stderr){
    Write-Host "Error $ev"    
}

我怎样才能这样做,但没有创建时间输出文件?

错误的解决方案:

  1. 使用-ErrorVariable开关。反例:
  2. Invoke-Expression $expr -ErrorVariable ev 2> C:\aaa\file1.txt
    $expr = "try { throw '111' } catch { }"
    Write-Host "Error $ev" # will output error, but std error is empty
    
    1. $ LASTEXITCODE和$?校验。反例:

      Get-Service invalidservice

    2. $ lastexitcode等于0,$?等于True,但是std错误不为空

      UPD :有人可以解释为什么会被投票?我是否需要创建更清晰的解释?

      UPD2 :想法很简单:将Powershell控制台中的“红色”(标准错误)文本保存在变量中。我收到的命令是一个任意字符串。 例子:

      1. 当我在Powershell控制台中写“try {throw'111'} catch {}”时,PS控制台中没有红色(错误)文本(尽管$ error不是空的)。因此,如果我在代码中调用该表达式,则不会在某个变量中保存错误。

      2. 当我写“Get-Service notexistingservice”,或“1/0”或“Write-Error 111”时,会出现红色(错误)文本和非空$错误。因此,如果我在代码中调用该表达式,我希望将错误保存在某个变量中。

3 个答案:

答案 0 :(得分:1)

执行此操作的方法是-errorvariable常用参数。您的计数器示例仅有效(我只是犹豫地使用该单词),因为您已明确编码,因为它不会使用Try/Catch输出错误,并且不会在您的catch中包含任何编码。您基本上抱怨说,您告诉PowerShell将错误案例发送到Catch脚本块,您没有输出任何内容,然后在没有输出任何内容时出现问题。仍然会发生错误,它会记录在您应该声明的错误变量中,并且也存储在$Error中,但由于您没有在Catch块中输出任何内容,因此您的StdErr重定向没有任何内容做。

如果您希望$ ev不包含错误,因为您更正了Catch块中的问题,那么也要清除catch块中的变量。

$expr = 'try{ throw "1111"}catch{Remove-Variable ev}'

或者,如果您希望StdErr包含错误文本,请确保在Catch块中包含该输出:

$expr = 'try{ throw "1111"}catch{Write-Error $_.Exception.Message}'

答案 1 :(得分:1)

将标准输出和标准错误保存到单独的变量中。没有美元符号,它将无法正常工作(来自Windows Powershell in Action)。

$err = $( $output = get-childitem foo3 ) 2>&1

答案 2 :(得分:0)

我知道这是一个非常老的问题,但是我也遇到了同样的问题,并且想分享我最终得出的结论。

        $error.clear()
    $List = New-Object PSObject
    Invoke-Command -ComputerName $server -ScriptBlock {
        $smbv1 = (Get-SmbServerConfiguration | Select EnableSMB1Protocol)
        $smbv1 | Select-Object EnableSMB1Protocol} -OutVariable List    

    foreach($item in $list.EnableSMB1Protocol){
        if($error -ne $null){
            $item = "unknown"
            $msg = $error.Exception.Message
            ac .\smb1errors.txt "$Server, $msg"
        }

由于$ error变量是一个.NET对象,为了清除它,我需要将其传递给参数()。然后,我执行了我的代码,在本例中检查SMBv1服务,并测试$ error是否仍然为$ null。如果$ error变量包含内容,则将其包含在变量中。 $ msg = $ error.Exception.Message