Powershell防弹异常处理

Gor*_*don 5 oop powershell exception

我正在将一个非常大的基于函数的脚本迁移到类,并同时尝试启动我的错误捕获游戏。代码要么通过作业在远程机器上运行,要么在用户登录时自动且透明地运行,日志文件是传达问题的唯一方式。当前(基于函数的)版本有一些错误会导致未处理的异常,这意味着这些问题永远不会记录在日志中。代码读取用户提供的 XML 文件以进行数据处理,我需要提供有意义的反馈,以便可以处理数据或数据结构。我的总体目标是... 1:捕获所有异常。2:在视觉上区分“预期”异常;我在日志中提供了一些有用的信息以允许用户进行故障排除和“意外”异常;我提供脚本名称和行号来帮助我追踪错误。3:随着时间的推移,将尽可能多的项目从“意外”移动到“预期”。

考虑到这些目标,我正在考虑几件事,但我觉得我知道的还不够多,无法确保我的决策是正确的。1:$ErrorActionPreference=Stop历史上的建议是不要设置全局错误操作,而是根据具体情况进行操作。但是考虑到我可以将它设置为停止的每一种情况,我都会,似乎这个建议实际上更多是关于快速“脚本”,而我基本上是使用 PS 来编写“程序”,而全局停止是更好的答案?

2:鉴于这样的场景,我在一个实用程序方法中有一个异常(不,我没有在这里实现一个类,我试图让示例保持简单,但希望这个概念仍然清晰)...

$path = '\\Server\InvalidFolder|'
try {
    Test-Path $path -errorAction:stop
} catch [System.ArgumentException] {
    throw [Custom.ExpectedException] "Error: Invalid characters in path - $invalidCharacters"
} catch {
    # Generic error trap
    throw [Custom.UnexpectedException] "Unexpected Error: $($_.ScriptStackTrace) $($_.Exception.Message)"
}
Run Code Online (Sandbox Code Playgroud)

我觉得我想要/需要做的是创建一些自定义错误类型,这样我就可以捕获不同的 Powershell 错误并将它们转换为我的类型,然后我抛出,并且调用代码有自己的 try/catch 然后格式化并推送到日志。这是正确的方法,还是我错过了一些更好的选择?3:假设这甚至是可能/可取的,如何创建自定义异常类型?我的 Google-Fu 失败了,这让我想知道我是否找不到任何东西,因为它不能/不应该完成。

编辑:就自定义异常类型而言,这看起来工作正常。

class PxException : Exception {
    PxException() {
    }

    PxException([string] $message): base($message) {
    }

    PxException([string] $message, [Exception] $inner) : base($message, $inner) {
    }
}


$path = '\\Server\InvalidFolder|'
try {
    Test-Path $path -errorAction:stop
} catch [System.ArgumentException] {
    Write-Host "Error: $($_.Exception.Message)"
    throw [PxException] "Px expected exception"
} catch {
    # Standard Px error trap
    Write-Host "Unexpected Error: $($_.ScriptStackTrace)"
    Write-Host "$($_.Exception.Message)"
}
Run Code Online (Sandbox Code Playgroud)

仍然想知道这是正确的方式,但它显然是一种方式,这是一个好兆头。

编辑 2:所以,这有效

class PxException : Exception {
    PxException() {}
    PxException([string] $message) : base($message) {}
    PxException([string] $message, [Exception] $inner) : base($message, $inner) {}
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试在我的自定义类型中实现 InvocationInfo 时,它会...

class PxException : Exception {
    PxException() {}
    PxException([string] $message) : base($message) {}
    PxException([string] $message, [InvocationInfo] $InvocationInfo) : base($message, $InvocationInfo) {}
    PxException([string] $message, [Exception] $inner) : base($message, $inner) {}
}
Run Code Online (Sandbox Code Playgroud)

[InvocationInfo]不被识别为类型。即使我有using namespace System;,这也是我认为 InvocationInfo 被定义的地方。

编辑3:GetType()救援。这有效。 PxException([string] $message, [System.Management.Automation.InvocationInfo] $InvocationInfo) : base($message, $InvocationInfo) {} 不需要using。至少就消除异常类定义中的错误而言。但

$InvocationInfo = $_.InvocationInfo
throw [PxException] "Px expected exception" $InvocationInfo
Run Code Online (Sandbox Code Playgroud)

行不行。必须弄清楚为什么我不能用两个参数抛出异常。但是……进步。