2016-06-27 10 views
12

Как я могу использовать потоки из PowerShell или перехватывать ошибки, такие, чтоКак я могу отобразить «голый» сообщение об ошибке в PowerShell без сопровождающей stacktrace?

  • Сообщение об ошибке отображается сообщение об ошибке (по-настоящему писать в стандартный поток ошибок, так что TeamCity и Octopus видеть это как ошибку)
  • Нет стека след мусор путает мое прекрасное, краткое сообщение об ошибке

всех этих лет я пережила throw ошибок или писать щие через Write-Error, но я устал и стар, и в моем сценарии я просто хочу, чтобы увидеть одну сжатых сообщение об ошибке. Я пытался все комбинации trap, throw, Write-Error и -ErrorAction, но безрезультатно:

try { 
    throw "error" #sample code for StackOverflow. In the theater 
    #of your mind, imagine there is code here that does something real and useful 
} catch { 
    Write-Error "An error occurred attempting to 'do something.' Have you tried rebooting?" 
} 

Вот пользовательский опыт, я хочу видеть:

C:\> & .\Do-Something.ps1 
An error occurred attempting to 'do something.' Have you tried rebooting? 

C:\> ▏ 

Вместо этого я получаю:

C:\> & .\Do-Something.ps1 
An error occurred attempting to 'do something.' Have you tried rebooting? 
At line:1 char:1 
+ Do-RealWork 
+ ~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [Write-Error], WriteErrorException 
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Do-RealWork  

C:\> ▏ 
+0

FWIW '$ error [0] .Exception.Message' содержит сообщение об ошибке, но я не уверен, что это будет полезно для вас. – sodawillow

ответ

9

Установка автоматического $ErrorView переменной на 'CategoryView' вызывает PowerShell для вывода лаконичных, однолинейных представления об ошибках вместо этого, но это представление не всегда может включать в себя достаточно информации, потому что ошибка сообщение обычно не включены; с положительной стороны, текст, переданный в Throw "..."-, отраженный, но, наоборот, Write-Error вывод содержит no конкретная информация, пока действует 'CategoryView'.
Добавление нового представления об ошибке в PowerShell, которое является однострочным, но всегда содержит всю важную информацию: being discussed for v6.

При условии, что ваш код PowerShell запускается из консоли (использует консоль хоста), использование [Console]::Error.WriteLine(), который безоговорочно пишет внешнего мираStderr (стандартная ошибка поток):

[Console]::Error.WriteLine("An error occurred ... Have you tried rebooting?") 

Примечание:

  • Это не будет работать с не-консольными хостами, такими как PowerShell ISE.

  • [Console]::Error.WriteLine() выход не печатается в красной в консоли [1].


К сожалению, нет единого решения, которое работает как с в PowerShell (по хостам) и из вне его:

  • [Console]::Error.WriteLine() , при правильном написании stderr для снаружи w orld, не может иметь свой выходной захват или подавлен внутри PowerShell, и работает только с консолью PowerShell хост.

  • Аналогично, $host.ui.WriteErrorLine(), несмотря на то, работает с всех хостов, это интерфейса метод, который работает вне системы потока PowerShell, как хорошо и, следовательно, его выходные тоже не может быть захвачен или подавлен в PowerShell.
    Что еще более важно, он не пишет в stderr внешнего мира (он ведет себя как Write-Error в этом отношении, см. Ниже).

  • Внутри PowerShell, только Write-Error записывает поток ошибок PowerShell, поэтому его выход может быть захвачены/подавлены.
    Однако, к сожалению, Write-Error (помимо того, что шумным) делает не пишите внешний мир STDERR, если, причудливо, STDERR не явно перенаправлена ​​ - см this answer шахт для деталей.


[1] Петр (сам OP) предлагает обходной путь для этого:

[Console]::ForegroundColor = 'red' 
[Console]::Error.WriteLine("An error occurred ... Have you tried rebooting?") 
[Console]::ResetColor() 

suneg's helpful answer обеспечивает функцию обертку для него.

К счастью, PowerShell автоматически опускает цветовые коды, когда обнаруживает, что выход перенаправляется (в файл).

1

Лучший способ по-моему перехвата ошибок в PowerShell будет использовать следующее:

$Error[0].Exception.GetType().FullName 

Вот пример того, как использовать это должным образом. В основном проверьте, что вы пытаетесь сделать в PowerShell с различными сценариями, в которых ваш скрипт не работает.

Вот типичное сообщение об ошибке PowerShell:

PS C:\> Stop-Process -Name 'FakeProcess' 
Stop-Process : Cannot find a process with the name "FakeProcess". Verify the process name and call the cmdlet again. 
At line:1 char:1 
+ Stop-Process -Name 'FakeProcess' 
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : ObjectNotFound: (FakeProcess:String) [Stop-Process], ProcessCommandException 
    + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.StopProcessCommand 

Далее вы получите исключение с сообщением об ошибке:

PS C:\> $Error[0].Exception.GetType().FullName 
Microsoft.PowerShell.Commands.ProcessCommandException 

Вы могли бы установить свой код, чтобы поймать сообщение об ошибке выглядит следующим образом:

Try 

    { 
     #-ErrorAction Stop is needed to go to catch statement on error 
     Get-Process -Name 'FakeProcess' -ErrorAction Stop 
    } 

Catch [Microsoft.PowerShell.Commands.ProcessCommandException] 

    { 
     Write-Host "ERROR: Process Does Not Exist. Please Check Process Name" 
    } 

Выход будет выглядеть следующим образом вместо стандартного Powershell d в приведенном выше примере:

ERROR: Process Does Not Exist. Please Check Process Name 

Наконец, вы также можете использовать несколько блоков catch для обработки нескольких ошибок в коде. Вы также можете включить блок блокировки «одеяло», чтобы поймать все ошибки, которые вы не обрабатывали. Пример:

Try 

    { 
     Get-Process -Name 'FakeProcess' -ErrorAction Stop 
    } 

Catch [Microsoft.PowerShell.Commands.ProcessCommandException] 

    { 
     Write-Host "ERROR: Process Does Not Exist. Please Check Process Name" 
    } 

Catch [System.Exception] 
    { 
     Write-Host "ERROR: Some Error Message Here!" 
    } 

Catch 
    { 
     Write-Host "ERROR: I am a blanket catch to handle all unspecified errors you aren't handling yet!" 
    } 

Надеюсь, что это поможет!

+1

Написание сообщений об ошибках с помощью «Write-Output» не рекомендуется, поскольку он записывает поток PowerShell _success_ (output). Кроме того, ваш пост больше ориентирован на обработку исключений per se, и это не то, о чем идет речь в OP (он ясно знает, как ловушки исключений, как показано в его вопросе). – mklement0

+0

Будет ли Write-Host лучше для этого? –

+0

Честно говоря, я надеюсь, что кто-то появится и сообщит мне, что есть параметр, который я могу установить на $ host, который будет подавлять трассировки стека. Мне действительно нужны реальные ошибки (написанные на stderr), чтобы ошибки были помечены в местах, которые ищут выход ошибки (например, сборки TeamCity). Глядя на журнал построения 20000 строк в TeamCity для сообщений об ошибках сложно; поэтому нам это нужно написать stderr –

5

Основываясь на idea in a previous answer, вы можете временно переопределить командлет Write-Error с помощью специальной функции.

# Override the built-in cmdlet with a custom version 
function Write-Error($message) { 
    [Console]::ForegroundColor = 'red' 
    [Console]::Error.WriteLine($message) 
    [Console]::ResetColor() 
} 

# Pretty-print "Something is wrong" on stderr (in red). 
Write-Error "Something is wrong" 

# Setting things back to normal 
Remove-Item function:Write-Error 

# Print the standard bloated Powershell errors 
Write-Error "Back to normal errors" 

С этим вы используете тот факт, что функции Powershell имеют приоритет над командлетами.

https://technet.microsoft.com/en-us/library/hh848304.aspx

Это самый элегантный подход, который я смог придумать, чтобы показать, как красивые и лаконичные сообщения об ошибках, а также позволяет обнаружить проблемы TeamCity легко.

 Смежные вопросы

  • Нет связанных вопросов^_^