Ошибка записи не приводит к полезной информации при использовании внутри методов класса | Powershell - PullRequest
1 голос
/ 02 марта 2020

Я использовал метод с классом и без него, и, похоже, ошибка записи дает разные результаты. В случае класса, он не определяет функцию , а номер строки всегда 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' не распознается как имя командлета, функции, файла сценария или работающей программы. Проверьте правильность написания имени или, если путь был указан, проверьте правильность пути и повторите попытку. В F: \ debug \ encryption_concat_tests \ Untitled1.ps1: 11 char: 1 + oper1 + ~~~~~ + CategoryInfo: NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId: Microsoft.PowerShell.Commands.WriteErrorException, oper1

Когда я вложил одну и ту же функцию в класс, я получил это:

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» не распознается как имя командлета, функции, файла сценария или работающей программы. Проверьте правильность написания имени или, если путь был указан, проверьте правильность пути и повторите попытку. В строке: 1 символ: 1 + F: \ debug \ encryption_concat_tests \ Untitled1.ps1 + ~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId: Microsoft.PowerShell.Commands.WriteErrorException

В чем может быть причина такого поведения методов внутри классов?

1 Ответ

1 голос
/ 02 марта 2020

В качестве отступления: Invoke-Expression (iex) обычно следует избегать ; определенно не используйте его для вызова внешней программы - просто вызовите ее напрямую , как показано ниже.


В методах класса PowerShell:

  • Не используйте Write-Error, поскольку классы не предназначены для выдачи нескончаемых ошибок.

    • Единственная причина, по которой вы видите любой вывод - это ошибка в PowerShell Core 7.0.0-r c .3 с методами, тип возвращаемого значения которых [void] - см. эту проблему GitHub .
  • Вместо этого сообщайте об ошибках только путем выброса их с помощью оператора Throw или не перехвата завершения ошибок (включая исключения из. NET методов и вызовов командлетов с -ErrorAction Stop).

    • Примечание: Throw и -ErrorAction Stop (или $ErrorActionPreference = 'Stop') create сценарий -конкретный (завершающий пространство выполнения) ошибки, тогда как исключения, выброшенные методом. NET (не перехвачены и повторно выброшены в методе класса), создают только stat элемент - определяющие ошибки; то есть, хотя тело метода класса сразу завершается, выполнение в вызывающей программе продолжается по умолчанию; последнее также относится к оператору вызова (&), не находящему исполняемый файл, ошибкам в выражениях, таких как 1 / 0, и вызовам командлетов, которые генерируют ошибки завершения операторов (самый серьезный тип ошибок, который они могут сообщить) без их переводят в скрипт -конечные с -ErrorAction Stop; см. эту проблему с документами GitHub для полного обзора сложной обработки 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-Object Operator
$operator.oper1()
...