Подтвердить что ты не робот

PowerShell попробуйте/поймать/наконец

Недавно я написал сценарий PowerShell, который прекрасно работает - однако я хотел бы сейчас обновить сценарий и добавить некоторую проверку/обработку ошибок - но я, кажется, был озадачен первым препятствием. Почему не работает следующий код?

try {
  Remove-Item "C:\somenonexistentfolder\file.txt" -ErrorAction Stop
}

catch [System.Management.Automation.ItemNotFoundException] {
  "item not found"
}

catch {
  "any other undefined errors"
  $error[0]
}

finally {
  "Finished"
}

Ошибка перехватывается во втором блоке перехвата - вы можете увидеть вывод из $error[0]. Очевидно, я хотел бы поймать его в первом блоке. Что мне не хватает?

4b9b3361

Ответ 1

-ErrorAction Stop меняет вещи для вас. Попробуйте добавить это и посмотреть, что вы получаете:

Catch [System.Management.Automation.ActionPreferenceStopException] {
"caught a StopExecution Exception" 
$error[0]
}

Ответ 2

Это очень странно.

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

try {
  remove-item C:\nonexistent\file.txt -erroraction stop
}
catch [System.Management.Automation.ItemNotFoundException] {
  write-host 'ItemNotFound'
}
catch [System.Management.Automation.SessionStateException] {
  write-host 'SessionState'
}
catch [System.Management.Automation.RuntimeException] {
  write-host 'RuntimeException'
}
catch [System.SystemException] {
  write-host 'SystemException'
}
catch [System.Exception] {
  write-host 'Exception'
}
catch {
  write-host 'well, darn'
}

Как оказалось, выход был 'RuntimeException'. Я также попробовал это с другим исключением CommandNotFoundException:

try {
  do-nonexistent-command
}
catch [System.Management.Automation.CommandNotFoundException] {
  write-host 'CommandNotFoundException'
}
catch {
  write-host 'well, darn'
}

Правильно выводит 'CommandNotFoundException'.

Я смутно помню, как читал в другом месте (хотя я не мог найти его снова) о проблемах с этим. В таких случаях, когда фильтрация исключений работала некорректно, они могли бы найти ближайший Type, а затем использовать switch. Следующие просто ловит Exception вместо RuntimeException, но эквивалент switch моего первого примера, который проверяет все базовые типы ItemNotFoundException:

try {
  Remove-Item C:\nonexistent\file.txt -ErrorAction Stop
}
catch [System.Exception] {
  switch($_.Exception.GetType().FullName) {
    'System.Management.Automation.ItemNotFoundException' {
      write-host 'ItemNotFound'
    }
    'System.Management.Automation.SessionStateException' {
      write-host 'SessionState'
    }
    'System.Management.Automation.RuntimeException' {
      write-host 'RuntimeException'
    }
    'System.SystemException' {
      write-host 'SystemException'
    }
    'System.Exception' {
      write-host 'Exception'
    }
    default {'well, darn'}
  }
}

Это записывает 'ItemNotFound', как и должно быть.