2

我使用了一个有和没有类的方法,并且 Write-Error 似乎产生了不同的输出。在类的情况下,它不指定函数并且行号始终为 1,1

function oper1() {
    Try {
        [string] $cmd = ".\some_exe_which_does_not_exist.exe"
        iex $cmd 
    }
    Catch {
        Write-Error $_.Exception.Message
    }
}

oper1

以上输出:

oper1:术语“.\some_exe_which_does_not_exist.exe”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确并重试。在 F:\debug\encryption_concat_tests\Untitled1.ps1: 11 char:1 + oper1 + ~~~~~~ + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,操作1

当我在一个类中包含相同的函数时,我得到了这个:

class Operator {
    [void] oper1() {
        Try {
            [string] $cmd = ".\some_exe_which_does_not_exist.exe"
            iex $cmd 
        }
        Catch {
            Write-Error $_.Exception.Message
        }
    }
}

[Operator] $operator = New-Object Operator
$operator.oper1()

术语“.\some_exe_which_does_not_exist.exe”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确并重试。在 line:1 char:1 + F:\debug\encryption_concat_tests\Untitled1.ps1 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

类内方法的这种行为可能是什么原因?

4

1 回答 1

2

顺便说一句:Invoke-Expression( iex) 通常应避免;绝对不要用它来调用外部程序——直接调用就行了,如下图。


在 PowerShell 类方法中:

  • 不要使用Write-Error,因为类并非旨在发出非终止错误。

    • 您看到任何输出的唯一原因是PowerShell Core 7.0.0-rc.3的错误[void],其返回类型恰好是- 请参阅GitHub 问题 #5331
  • 相反,仅通过将错误与语句一起抛出或捕获终止错误(包括来自 .NET 方法和 cmdlet 调用的异常)来传达错误。Throw-ErrorAction Stop

    • 注意:Throw-ErrorAction Stop(或$ErrorActionPreference = 'Stop')创建脚本终止(线程终止)错误,而 .NET 方法抛出的异常(未在类方法中捕获和重新抛出)仅创建语句终止错误;也就是说,当类方法体立即终止时,默认情况下在调用者中继续执行;后者也适用于&找不到可执行文件的调用运算符 ( )、表达式中错误1 / 0如; 看到这个 GitHub 文档问题-ErrorAction Stop全面了解 PowerShell 的复杂错误处理。

有关类方法中的错误处理和流输出行为的更多信息,请参阅此答案。

这是您的代码的更正版本。

class Operator {
    [void] oper1() {
        Try {
            # Try to invoke a non-existent executable.
            & ".\some_exe_which_does_not_exist.exe"
        }
        Catch {
            # Re-throw the error.
            # Alternatively, don't use try / catch, but the error
            # then only aborts the method call, not the entire script.
            Throw
        }
    }
}

$operator = [Operator]::new()
$operator.oper1()
于 2020-03-02T04:36:35.430 回答