gpt4 book ai didi

如果之后抛出错误,则数组的 Powershell 写输出丢失

转载 作者:行者123 更新时间:2023-12-02 22:16:55 25 4
gpt4 key购买 nike

在 Powershell 中,如果你写输出一些行然后抛出一个错误,你会期望得到在错误之前发生的输出。所以如果你执行这个:

Write-Output ("test output 1")
Write-Output ("test output 2")
Write-Output ("test output 3")
Write-Output ("test output 4")
Write-Output ("test output 5")
throw "pretend error"
你会按预期得到这个:
test output 1
test output 2
test output 3
test output 4
test output 5
pretend error
At C:\Powershell\Test.ps1:7 char:1
+ throw "pretend error"
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (pretend error:String) [], RuntimeException
+ FullyQualifiedErrorId : pretend error
但是,如果您写入输出数组中的一堆对象,然后抛出错误,则永远不会出现数组的写入输出(以及之后的任何内容)。所以如果你运行这个:
Write-Output ("test output 1")
Write-Output ("test output 2")
Write-Output ("test output 3")
Write-Output ("test output 4")
Write-Output ("test output 5")
$testlist = @()
$count = 1
While($count -lt 6)
{
$testobj = new-object psobject -prop @{Name="array object $count"}
$testlist += $testobj
$count +=1
}
Write-Output $testlist
Write-Output ("test output 6")
Write-Output ("test output 7")
throw "pretend error"
...在“测试输出 5”之后你没有得到任何输出。好像输出数组会使所有内容都被缓冲,然后错误会丢失缓冲区。与 Powershell 使用带有数组的管道的方式有关吗?
所以我的问题是:我需要做什么来确保写输出不会得到 丢失 由于后续错误。这使得日志记录非常困难。
这是在 Powershell 5.1 中

最佳答案

看起来您看到的是 引入隐式使用 Format-Table 的有问题的 300 毫秒延迟的非常不幸的副作用在 PowerShell v5 中 为了更好地计算合适的列宽,在this answer中有详细说明。并在 GitHub issue #4594 中讨论;但是,您的症状非常有问题,需要 新的错误报告 :GitHub issue #13985 .
因为您的 $testlist数组包含少于 4 的对象属性(即在您的情况下只有一个)并且因为您的对象类型( [pscustomobject] )没有与之关联的格式数据,PowerShell 隐式使用 Format-Table用于输出格式。
到时候throw遇到语句,300 毫秒的延迟还没有过去,因为 throw终止运行空间[1],Format-Table输出(以及随后的 Write-Output 输出)永远不会显示。
- 不完美 - 解决方法 是到 强制输出同步 ,这可以通过以下三种方式之一完成:

  • 使用 Out-Host ,它同步使用默认输出行为,但这也意味着从 PowerShell 内部您将无法捕获或重定向输出;但是,当从外部调用时,通过 PowerShell 的 CLI,Out-Host输出到标准输出,也可以被捕获。
  • 使用 Format-Table明确地。这也适用于显示,但将数据的输出更改为格式化指令的不相关对象,PowerShell 本身将其转换为通常的、丰富的显示格式,但是如果您想捕获输出,这些是无用的 - 您的原始数据是丢失。
  • 如果您希望至少允许从 PowerShell 内部捕获原始对象的格式化字符串表示,您可以使用 Out-String , 将格式化表示输出为单个多行字符串(不幸的是,带有额外的尾随换行符);从 PowerShell 外部调用时,其效果本质上与调用 Out-Host 相同。 .

  • 请注意,在您的情况下,解决方法只需应用于 $testlist陈述:
    # Or ... | Out-Host or ... | Format-Table - see comments above.
    $testlist | Out-String
    有一个 替代,但更模糊的解决方法 依赖于使用 Start-Sleep等待至少 300 毫秒。并在隐式 Format-Table 之后输出至少一个对象调用,如这个简化示例所示:
    'before'
    [pscustomobject] @{ foo = 1 }
    Start-Sleep -Milliseconds 300 # wait for implicit Format-Table
    'after' # force output of the table by outputting at least one more object
    throw "error"
    优势此解决方法的主要内容是 您的原始对象以这种方式保留在输出中 ,这将允许您从 PowerShell 内部捕获它们,例如, $output = try { ./someScript.ps1 } catch { Write-Error $_ }
    最后, 您的代码可以精简 ;把它们放在一起:
    # Use *implicit* output - no need for Write-Output
    # If you do use Write-Output: separate the arguments with *spaces*,
    # don't put (...) around the argument list.
    "test output 1"
    # ...


    # Implicitly capture the foreach loop output in an array.
    # This is much more efficient than using += to "extend" an array
    # in a loop (which requires creating a *new* array every time).
    [array] $testlist =
    foreach ($count in 1..6) {
    # Simpler and more efficient PSv3+ method for constructing
    # custom objects.
    [pscustomobject] @{ Name="array object $count" }
    }

    # Apply the workaround.
    $testlist | Out-String

    # Use implicit output again.
    "test output 6"
    "test output 7"

    throw "pretend error"

    [1] 即 throw生成运行空间终止(脚本终止)错误,它会立即中止整个执行 - 不像语句终止错误,它只会中止手头的语句,例如在 .NET 方法调用中发生异常时会发生;您可以通过设置 $ErrorActionPreference 将所有语句终止和所有非终止错误转换为运行空间终止错误。偏好变量为 'Stop' - 见 this answer .

    关于如果之后抛出错误,则数组的 Powershell 写输出丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64681357/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com