【问题标题】:Errors prior to write-output in PowerShell在 PowerShell 中写入输出之前的错误
【发布时间】:2015-01-06 16:32:32
【问题描述】:

我正在编写一个函数来从各种计算机收集 WMI 信息。我要做的第一件事是检查我是否可以访问当前计算机,如果不能,我会写入错误并继续。我的问题是,我怎样才能将错误写入屏幕然后成功调用的结果? (删减代码:)

Function Get-Info
{
    Param([Parameter(ValueFromPipeline=$true)]
    [string[]] $computerName = "." )
    Process
    {
        foreach ($Computer in $ComputerName)
        {
            if (-Not $(test-connection $computer -Count 2 -ErrorAction SilentlyContinue) )
            {
                Write-Error "Unable to access $computer"
                continue
            }
            $Info = get-WMIObject -Class <someClass> -ComputerName $Computer
            $result = New-Object PSObject -Property @{
                 Prop1 = $Info.Property
                 <# ... #> }
            Write-Output $Result
       }
   }
}

当我查询一组系统时,我得到的是 info, &lt;error&gt;, info, &lt;error&gt; 而不是 &lt;error&gt;,&lt;error&gt;,info...,这正是我想要的。

任何帮助将不胜感激。

【问题讨论】:

  • 澄清:您希望在所有成功结果之前打印所有错误?
  • 你不能在foreach循环外部Write-Output $Results的数组$results += $result中捕获结果吗?
  • 请注意 Write-ErrorWrite-Output 写入不同的流。任何单个流的消息都是按顺序打印的,但不同流之间没有保证顺序。
  • 是arco444 - 输出前出错。
  • 尽量避免收集输出。在我见过的使用 Write-Output 的文章中查看书籍中的一些“最佳实践”(或将输出作为最后一个进入管道的条目),我正在努力为可重用性提供最佳功能。

标签: powershell output


【解决方案1】:

只需将你的结果累积到一个变量中,然后在完成并写入所有错误后输出:

$Result = $computers | Get-Info
$Result

【讨论】:

    【解决方案2】:

    给你,我只是把所有的错误收集到$errorComputers,把所有成功的Computers收集到$validComputers,然后在代码的最后显示出来。请注意,这种方法并不能很好地利用 PowerShell 管道(完全没有!),但它实现了您正在寻找的目标,在有效条目之前列出错误。

    Function Get-Info
    {
    Param([Parameter(ValueFromPipeline=$true)]
    [string[]] $computerName = "." )
    Process
    {
        foreach ($Computer in $ComputerName)
        {
            if (-Not $(test-connection $computer -Count 2 -ErrorAction SilentlyContinue) )
            {
                $errorcomputers += $computer
                continue
            }
            $Info = get-WMIObject -Class <someClass> -ComputerName $Computer
            $result = New-Object PSObject -Property @{
                 Prop1 = $Info.Property
                 <# ... #> }
            $validComputers += $Result
       }
    }
    $errorcomputers | ForEach-Object {
       Write-Warning "Unable to contact $PSitem"
       }
    $validComputers
    }
    

    现在,在第二个示例中,我使用了 Try/Catch,而不是您之前的逻辑。这应该确保首先显示您的错误,并保持进程块的功能以提高速度。

    Function Get-Info
    {
    Param([Parameter(ValueFromPipeline=$true)]
    [string[]] $computerName = "." )
    Process
    {
        foreach ($Computer in $ComputerName)
        {
    
        try {test-connection $computer -Count 1 -ErrorAction Stop}
       catch{Write-Error "Unable to access $computer"
                    Continue}
            $Info = get-WMIObject -Class <someClass> -ComputerName $Computer
            $result = New-Object PSObject -Property @{
                 Prop1 = $Info.Property
                 <# ... #> }
            Write-Output $Result
       }
      }
    }
    

    【讨论】:

    • 大家好,感谢您的意见。我想没有一个很好的方法来做我想做的事。正如 1RedOne 指出的那样,我想对管道使用良好的做法,我宁愿不收集对象,而是在每个单独的对象上使用写入输出(很好地使用管道)。
    猜你喜欢
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多