使用ValueFromPipeline的CatchError函数

时间:2015-12-11 15:31:41

标签: powershell

我正在尝试编写一个PowerShell函数,我可以在每个命令之后将其放入管道中。它应该能够从管道获取$ Error值并写入日志。

到目前为止,这就是我所拥有的:

function CatchError
{   
    [CmdletBinding()]
    Param
    (
        [parameter(ValueFromPipeline=$true)]
        [string[]]$Error,
        [Parameter(Mandatory=$True)]
        [string]$OutPath
    )
    Try
    {
        $Error | Out-File $OutPath -Append -Force
    }
    Catch [Exception]
    {
        Write-Error $_.Exception.Message
    }
}

但是当我像这样管道时:

gci R:\test | CatchError -OutPath C:\install\test\log.txt

log.txt已创建,但没有任何内容。路径R:\test不存在,因此它应该创建一个内容为"R:\test does not exist.. etc."的日志文件,但它会在powershell窗口中打印出错误异常。

如何阻止将错误打印到powershell窗口并将其放入我的日志文件中?我认为[parameter(ValueFromPipeline=$true)]已经成功了。提前致谢

1 个答案:

答案 0 :(得分:0)

另一种方法(除了我在评论中提到的内容)基于我的回答here。特别是讨论了通过管道传递背景的最终部分。您可以执行以下操作(感谢PetSerAl传递脚本的想法):

# Could add try/catch blocks as needed. Keep in mind that errors generated
# within try block are still put into $error (depending on -erroraction
# and $erroractionpreference). 
# Besides extracting errors from $error another option to explore is to use 
# -ErrorVariable when $scriptOrCmdlet was executed, but that would
# only work if a cmdlet or function was passed

# Can pass in anything acceptable to &
function CatchAndWrap-ErrorAtHead ($scriptOrCmdlet) {
  $wasErrorCount = $error.count
  $output = & $scriptOrCmdlet # could accept set of args to this func and pass them here
  $numErrorsToCatch = $error.count - $wasErrorCount
  # Need to wrap everything as an array, so that 2-tuples are in pipeline
  # Not positive @() will do that (versus @(,$output))
  @($output),@($error[0..$numErrorsToCatch])
}

filter Log-PipelinedError {
  $_[1] | Out-File $OutPath -Append -Force
  # Remove logged error(s), but keep 2-tuple intact
  $_ = $_[0], $null
  $_
}

# This function is to insert cmdlets/scripts in the pipeline besides at the head,
# although you could combine the two functions by defining CatchAndWrapHead-Error
# to accept pipeline input
filter CatchAndWrap-ErrorWithin( $script) {
  $wasErrorCount = $error.count
  $output = $_[0] | & $script # again with the args
  $numErrorsToCatch = $error.count - $wasErrorCount

  # Need to decide what to do with errors in the pipe before here
  # This code keeps them, but discarding them is an option
  @($output),@($_[1] + $error[0..$numErrorsToCatch])
}

将此代码视为模板而非工作脚本。可能有几个恶魔般的细节需要解决。