You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell:如何在try...catch块正确抛出数组适配日志函数

问题:PowerShell日志函数处理catch块数组输入异常

我需要日志函数支持三种输入场景:单个对象、数组对象作为命名参数、管道输入。当前函数在正常管道传递数组时工作正常,但在try块抛出数组后,catch块中将$_传入函数时,数组会被拼接成单个字符串输出。

原函数代码

function log {
    param (
        [Parameter(Mandatory,ValueFromPipeline)][object[]]$msg,
        [ValidateSet("FATAL", "ERROR", "WARN", "INFO", "DEBUG")]
            [string]$level = "INFO",
        [switch]$quiet
    )
    
    process
    {
        $msg | ForEach-Object {
            $out = "[$((Get-Date).ToUniversalTime().ToString("u"))] $($level.ToUpper()) $_"
            if ($quiet) { $out | Out-File -FilePath $logpath -Append } else { $out | Tee-Object -FilePath $logpath -Append }
        }
    }
}

测试代码

try {
    $a = @("Test", "Test2")
    $a | log
    throw $a
}
catch {
    $_ | log
    exit 1
}

实际输出

[2023-09-19 20:04:46Z] INFO Test
[2023-09-19 20:04:48Z] INFO Test2
[2023-09-19 20:04:50Z] INFO Test Test2

问题原因

PowerShell的catch块中,$_是ErrorRecord对象,而非直接抛出的原始数组。当你抛出非Exception类型的对象时,PowerShell会自动将其包装进RuntimeException,原始数组会被转换为字符串作为ErrorRecord的消息内容,所以直接传入$_时,函数处理的是ErrorRecord的字符串表示,而非原始数组。

解决方法

方法1:在catch块中传入原始对象

修改catch块,通过$_.TargetObject获取抛出的原始数组:

catch {
    $_.TargetObject | log
    exit 1
}

方法2:优化日志函数自动处理ErrorRecord

修改函数的process块,自动识别ErrorRecord并提取原始对象,这样调用方无需修改代码:

function log {
    param (
        [Parameter(Mandatory,ValueFromPipeline)][object[]]$msg,
        [ValidateSet("FATAL", "ERROR", "WARN", "INFO", "DEBUG")]
            [string]$level = "INFO",
        [switch]$quiet
    )
    
    process
    {
        # 处理ErrorRecord,提取原始抛出对象
        $processedItems = $msg | ForEach-Object {
            if ($_ -is [System.Management.Automation.ErrorRecord]) {
                $_.TargetObject
            } else {
                $_
            }
        }

        $processedItems | ForEach-Object {
            $out = "[$((Get-Date).ToUniversalTime().ToString("u"))] $($level.ToUpper()) $_"
            if ($quiet) {
                $out | Out-File -FilePath $logpath -Append
            } else {
                $out | Tee-Object -FilePath $logpath -Append
            }
        }
    }
}

两种方法都能让catch块中的数组被正确拆分输出,和正常管道输入的结果一致。

内容的提问来源于stack exchange,提问作者Appleoddity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:52:47