Powershell отключить вывод ошибок

You’re way off track here. Silencing errors is almost never a good idea, and manually checking $? explicitly after every single command is enormously cumbersome and easy to forget to do (error prone). Don’t set yourself up to easily make a mistake. If you’re getting lots and lots of red, that means your script kept going when it should have stopped instead. It can no longer do useful work if most of its commands are failing. Continuing a program when it and the system are in an unknown state will have unknown consequences; you could easily leave the system in a corrupt state.

The correct solution is to stop the algorithm on the first error. This principle is called «fail fast,» and PowerShell has a built in mechanism to enable that behavior. It is a setting called the error preference, and setting it to the highest level will make your script (and the child scopes if they don’t override it) behave this way:

$ErrorActionPreference = 'Stop'

This will produce a nice, big error message for your consumption and prevent the following commands from executing the first time something goes wrong, without having to check $? every single time you run a command. This makes the code vastly simpler and more reliable. I put it at the top of every single script I ever write, and you almost certainly should as well.

In the rare cases where you can be absolutely certain that allowing the script to continue makes sense, you can use one of two mechanisms:

  • catch: This is the better and more flexible mechanism. You can wrap a try/catch block around multiple commands, allowing the first error to stop the sequence and jump into the handler where you can log it and then otherwise recover from it or rethrow it to bubble the error up even further. You can also limit the catch to specific errors, meaning that it will only be invoked in specific situations you anticipated rather than any error. (For example, failing to create a file because it already exists warrants a different response than a security failure.)
  • The common -ErrorAction parameter: This parameter changes the error handling for one single function call, but you cannot limit it to specific types of errors. You should only use this if you can be certain that the script can continue on any error, not just the ones you can anticipate.

In your case, you probably want one big try/catch block around your entire program. Then your process will stop on the first error and the catch block can log it before exiting. This will remove a lot of duplicate code from your program in addition to cleaning up your log file and terminal output and making your program less likely to cause problems.

Do note that this doesn’t handle the case when external executables fail (exit code nonzero, conventionally), so you do still need to check $LASTEXITCODE if you invoke any. Despite this limitation, the setting still saves a lot of code and effort.

Additional reliability

You might also want to consider using strict mode:

Set-StrictMode -Version Latest

This prevents PowerShell from silently proceeding when you use a non-existent variable and in other weird situations. (See the -Version parameter for details about what it restricts.)

Combining these two settings makes PowerShell much more of fail-fast language, which makes programming in it vastly easier.

  • Remove From My Forums
  • Вопрос

  • есть скрипт…

    ——————————————————
    param ([int]$start, [int]$end = $start)
    [string]$range = ‘192.168.111.’

    function GetWmiClass {
        param ( $target = «» )
        if ($wmi = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $comp -ErrorAction SilentlyContinue -Authentication Call) { return $wmi }
        else { return $false }
    }

    $num = $start
    while ($num -le $end) {
        $comp = $range + $num
        Write-Host $comp»:`t`t» -NoNewline -ForegroundColor Gray
          if (Test-Connection -ComputerName $comp -Quiet -Count 1) {
            If ($wmi = GetWmiClass $comp ) {
                Write-Host $wmi.Name»`t`t» -NoNewline -ForegroundColor DarkGreen
                if ($wmi.UserName) { Write-Host $wmi.UserName -ForegroundColor DarkGreen }
                else { Write-Host «Вход не выполнен»  -ForegroundColor DarkGray }
            }
            else {
                Write-Host «Ошибка доступа к WMI» -ForegroundColor DarkRed
            }
          }
        else { Write-Host «Хост не доступен» -ForegroundColor DarkGray }
        $num++
    }
    ——————————————

    на некоторых хостах видим

    ——————————————
    Get-WmiObject : Отказано в доступе. (Исключение из HRESULT: 0x80070005 (E_ACCESSDENIED))
    D:dev.scriptsgetusers.ps1:6 знак:26
    +     if ($wmi = Get-WmiObject <<<<  -Class Win32_ComputerSystem -ComputerName $comp -ErrorAction SilentlyContinue -Authentication Call) { return $wmi }
        + CategoryInfo          : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException<br/>
        + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
    ——————————————

    как сделать чтоб ошибка не выводилась в консоль при выполнении скрипта?

    -ErrorAction SilentlyContinue указано, но ошибка всё равно прёт


    эээ…

Ответы

  • Во-первых я испробовал get-wmiobject во всех комбинациях, и с 1.0 и с 2.0, с различными типами ошибок, но при -erroraction silentlycontinue ошибка не выводится. Вы можете отключить вывод ошибок глобально, установив для переменной $ErrorActionPreference значение silentlyContinue
    Во-вторых, успешность команды лучше проверять не по наличию данных, а с помощью специальной переменной $? в которой содержится статус выполнения предыдущей команды.


    AKA Xaegr, MCSE: Security, Messaging; MCITP: ServerEnterprise Administrator; Блог: http://xaegr.wordpress.com

    • Предложено в качестве ответа

      23 января 2010 г. 6:35

    • Помечено в качестве ответа
      OlegKrikun
      23 января 2010 г. 10:26

I am trying to see if a process is running on multiple servers and then format it into a table.

get-process -ComputerName server1,server2,server3 -name explorer | Select-Object processname,machinename

Thats the easy part — When the process does not exist or if the server is unavailable, powershell outputs a big ugly error, messes up the the table and doesn’t continue. Example

Get-Process : Couldn't connect to remote machine.At line:1 char:12 + get-process <<<<  -ComputerName server1,server2,server3 -name explorer | format-table processname,machinename
+ CategoryInfo          : NotSpecified: (:) [Get-Process], InvalidOperatio   nException    + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.Power   Shell.Commands.GetProcessCommand

How do I get around this? If the I would still like to get notified if the process isn’t available or Running.

Вы здесь сбились с пути.

У вас уже есть большое сообщение об ошибке. Зачем вам писать код, который $?явно проверяет каждую команду ? Это чрезвычайно громоздко и подвержено ошибкам. Правильное решение — прекратить проверку$? .

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

$ErrorActionPreference = 'Stop'

Я помещаю это в начало каждого сценария, который когда-либо писал, и теперь мне не нужно проверять $?. Это делает мой код намного проще и надежнее.

Если вы столкнетесь с ситуациями, когда вам действительно нужно отключить это поведение, вы можете либо catchуказать ошибку, либо передать настройку определенной функции, используя общий -ErrorAction. В вашем случае вы, вероятно, хотите, чтобы ваш процесс остановился при первой ошибке, перехватил ошибку и затем зарегистрировал ее.

Обратите внимание, что это не относится к случаю, когда внешние исполняемые файлы терпят неудачу (обычно код выхода ненулевой), поэтому вам все равно нужно проверить $LASTEXITCODE, вызываете ли вы какой-либо. Несмотря на это ограничение, настройка по-прежнему позволяет сэкономить много кода и усилий.

Дополнительная надежность

Вы также можете рассмотреть возможность использования строгого режима :

Set-StrictMode -Version Latest

Это препятствует тому, чтобы PowerShell молча продолжал работу, когда вы используете несуществующую переменную и в других странных ситуациях. ( -VersionПодробнее о том, что он ограничивает, см. В параметре.)

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

  • In a regular console window, in PowerShell v3 and above, stderr lines print just like stdout lines.

    • This is desirable, because stderr is used by many programs not just to report genuine errors, but anything that is not data, such as status messages.

    • Stderr lines (unless redirected — see below) print straight through the console (whereas stdout lines are sent to PowerShell’s success output stream, where they can be collected in a variable, sent through the pipeline, or redirected with > / >>).

  • Regrettably, the PowerShell ISE, even in v5.1, does print stderr lines in red, in the same format as PowerShell errors.

    • Visual Studio Code with the PowerShell extension doesn’t have this problem, and is worth migrating to in general, given that all future development effort will focus there, and given that it also works with the cross-platform PowerShell Core edition.
  • Well-behaved console applications solely use their exit code to signal success (exit code 0) vs. failure (any nonzero exit code). PowerShell saves the exit code of the most recently invoked console application in its automatic $LASTEXITCODE variable.

  • As an aside:

    • Common parameters -ErrorAction and -ErrorVariable cannot be used with external programs.
    • Similarly, preference variable $ErrorActionPreference has no effect (except accidentally, due to this bug, as of PowerShell v5.1 / PowerShell Core 6.2.0-preview.4).
    • try / catch cannot be used to detect and handle an external program’s failure.
    • For a comprehensive overview of PowerShell’s complex error handling rules, see this GitHub docs issue.

Note: I’m using the following external commands in the examples below, which produce 1 line of stdout and 1 line of stderr output (note that the redirection >&2 is handled by cmd, not PowerShell, because it is inside the '...'; it is used to produce stderr output):

cmd /c 'echo stdout & echo stderr >&2' 

A variant that makes the command signal failure, via a nonzero exit code (exit 1):

cmd /c 'echo stdout & echo stderr >&2 & exit 1' 

Therefore, normally the following should suffice:

$stdOut = cmd /c 'echo stdout & echo stderr >&2' # std*err* will print to console
if ($LASTEXITCODE -ne 0) { Throw "cmd failed." } # handle error

This captures stdout output in variable $stdout and passes stderr output through to the console.


If you want to collect stderr output for later and only show them in case of error:

$stdErr = @() # initialize array for collecting stderr lines.

# Capture stdout output while collecting stderr output in $stdErr.
$stdOut = cmd /c 'echo stdout & echo stderr >&2 & exit 1' 2>&1  | Where-Object { 
  $fromStdErr = $_ -is [System.Management.Automation.ErrorRecord]
  if ($fromStdErr) { $stdErr += $_.ToString() }
  -not $fromStdErr # only output line if it came from stdout
}

# Throw an error, with the collected stderr lines included.
if ($LASTEXITCODE -ne 0) { 
  Throw "cmd failed with the following message(s): $stdErr"
}
  • Note the 2>&1 redirection, which instructs PowerShell to send stderr lines (stream 2, the error stream) through the pipeline (stream 1, the success stream) as well.

  • In the Where-Object block, $_ -is [System.Management.Automation.ErrorRecord] is used to identify stderr lines, because PowerShell wraps such lines in instances of that type.

Alternatively, you could collect stderr output in a temporary file (2>/path/to/tmpfile), read its contents, and delete it.

This GitHub issue proposes introducing the option of collecting redirected stderr output in a variable, analogous to how you can ask cmdlets to collect errors in a variable via common parameter
-ErrorVariable.

There are two caveats:

  • Inherently, by only printing stderr lines later, the specific context relative to the stdout output may be lost.

  • Due to a bug as of Windows PowerShell v5.1 / PowerShell Core 6.2.0, $ErrorActionPreference = Stop mustn’t be in effect, because the 2>&1 redirection then triggers a script-terminating error as soon as the first stderr line is received.


If you want to selectively act on stderr lines as they’re being received:

Note:

  • Inherently, as you’re processing the lines, you won’t yet know whether the program will report failure or success in the end.

  • The $ErrorActionPreference = 'Stop' caveat applies here too.

The following example filters out stderr line stderr1 and prints line stderr2 to the console in red (text only, not like a PowerShell error).

$stdOut = cmd /c 'echo stdout & echo stderr1 >&2 & echo stderr2 >&2' 2>&1 |
  ForEach-Object { 
    if ($_ -is [System.Management.Automation.ErrorRecord]) { # stderr line
      $stdErrLine = $_.ToString()
      switch -regex ($stdErrLine) {
        'stderr1' { break } # ignore, if line contains 'stderr1'
        default   { Write-Host -ForegroundColor Red $stdErrLine }
      }
    } else { # stdout line
      $_ # pass through
    }
  }

# Handle error.
if ($LASTEXITCODE -ne 0) { Throw "cmd failed." }

Вы делаете это неправильно.

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

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

$ErrorActionPreference = 'Stop'

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

если вы столкнетесь с ситуациями, где вы действительно нужно, чтобы отключить это поведение, вы можете либо catch ошибки, или передавать значение определенной функции, используя общие -ErrorAction. В вашем случае вы, вероятно, хотите, чтобы ваш процесс остановился на сначала ошибка, поймать ошибку, а затем зарегистрировать его.

обратите внимание, что это не обрабатывает случай, когда внешние исполняемые файлы терпят неудачу (код выхода ненулевой, условно), поэтому вам все равно нужно проверить $LASTEXITCODE если вы вызываете какие-либо. Несмотря на это ограничение, установка по-прежнему экономит много кода и усилий.

дополнительную надежность

вы также можете рассмотреть возможность использования строгого режима:

Set-StrictMode -Version Latest

это предотвращает PowerShell от молча идет, когда вы используете несуществующую переменную и в других странных ситуациях. (См. -Version параметр для получения подробной информации о том, что он ограничивает.)

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

  1. Introduction to Error Action in PowerShell
  2. Use the -ErrorAction Parameter in PowerShell
  3. Setting Error Action Preferences in PowerShell

Suppressing PowerShell Errors

Whether we want to ignore error messages or terminate a script’s execution when an error occurs, Windows PowerShell has plenty of options for dealing with errors. This article will discuss multiple techniques in handling and suppressing errors.

Introduction to Error Action in PowerShell

Even though it is effortless to suppress Windows PowerShell errors, doing so isn’t always the best option (although it can be). If we carelessly tell PowerShell to hide errors, it can cause our script to behave unpredictably.

Suppressing error messages also makes troubleshooting and information gathering a lot more complicated. So tread lightly and be careful about using the following snippets that you will see in this article.

Use the -ErrorAction Parameter in PowerShell

The most common method for dealing with errors is to append the -ErrorAction parameter switch to a cmdlet. The -ErrorAction parameter switch lets PowerShell tell what to do if the cmdlet produces an error.

Command:

Get-Service 'svc_not_existing' -ErrorAction SilentlyContinue

In the command above, we are querying for a service that doesn’t exist. Usually, PowerShell will throw an error if the service doesn’t exist.

Since we use the -ErrorAction parameter, the script will continue as expected, like it doesn’t have an error.

Setting Error Action Preferences in PowerShell

If we need a script to behave in a certain way (such as suppressing errors), we might consider setting up some preference variables. Preference variables act as configuration settings for PowerShell.

We might use a preference variable to control the number of history items that PowerShell retains or force PowerShell to ask the user before performing specific actions.

For example, here is how you can use a preference variable to set the -ErrorAction parameter to SilentlyContinue for the entire session.

Command:

$ErrorActionPreference = 'SilentlyContinue'

There are many other error actions that we can specify for the ErrorAction switch parameter.

  • Continue: PowerShell will display the error message, but the script will continue to run.
  • Ignore: PowerShell does not produce any error message, writes any error output on the host, and continues execution.
  • Stop: PowerShell will display the error message and stop running the script.
  • Inquire: PowerShell displays the error message but will ask for confirmation first if the user wants to continue.
  • SilentlyContinue: PowerShell silently continues with code execution if the code does not work or has non-terminating errors.
  • Suspend: PowerShell suspends the workflow of the script.

As previously mentioned, the -ErrorAction switch has to be used in conjunction with a PowerShell cmdlet. For instance, we used the Get-Process cmdlet to demonstrate how the ErrorAction switch works.

Понравилась статья? Поделить с друзьями:
  • Powershell обработка ошибок выполнения
  • Powershell неизвестная ошибка 0x80005000
  • Powershell не показывать ошибку
  • Powershell не показывать ошибки
  • Powershell не отображать ошибки