SEHException не пойман Try/Catch

В фоновом потоке мое приложение регулярно проверяет сетевую папку (UNC-путь) для обновлений приложений. Он читает версию сборки файла, например:

Try
    newVers = System.Reflection.AssemblyName.GetAssemblyName("\\server\app.exe").Version
Catch ex As Exception
    ' ignore
End Try

Этот фрагмент выполняется довольно часто, в общем, я бы предпочел более 100 000 раз на нескольких сайтах клиентов до сих пор без проблем.

Иногда GetAssemblyName вызывает FileNotFoundException, например, если сетевая папка недоступна (что может случиться и должно быть рассмотрено). Это исключение попадает в блок Catch чуть ниже, и все работает отлично.

В трех сообщенных случаях, однако, вызов GetAssemblyName поднял SEHException. Странно, что это исключение не было захвачено блоком Catch чуть ниже, но мой глобальный обработчик обработанных исключений (System.AppDomain.CurrentDomain.UnhandledException). В результате приложение аварийно завершает работу.

Вот подробное описание исключения (к сожалению, поля ErrorCode и CanResume исключения не регистрируются моей процедурой обработки ошибок):

Caught exception: System.Runtime.InteropServices.SEHException
   Message: External component has thrown an exception.
   Source: mscorlib
   TargetSite: System.Reflection.AssemblyName nGetFileInformation(System.String)
   StackTrace: 
      at System.Reflection.AssemblyName.nGetFileInformation(String s)
      at System.Reflection.AssemblyName.GetAssemblyName(String assemblyFile)
      at SyncThread.Run() 
      at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
      at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
      at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
      at System.Threading.ThreadHelper.ThreadStart()

Почему исключение не попадает в блок Catch чуть ниже?

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

Ответ 1

Так как .NET 4, некоторые SEHException указывают на поврежденные состояния процесса и называются "поврежденными исключениями состояния". Это такие вещи, как нарушения segfaults/access, где исключение возникает после обнаружения повреждения памяти.

Пока эти ошибки все еще отображаются на управляемые .NET SEHExceptions, они по умолчанию не пойманы, поэтому try { ... } catch (Exception ex) { ... } не будет обрабатывать их.

Вы можете отказаться от использования этих исключений ( Статья, в которой эта цитата написана (в журнале MSDN), становится более подробной.

Если вы решите обработать эти исключения, есть много причин рассмотреть - как говорится в статье: "Очень сложно написать правильный код, который обрабатывает CSE и продолжает безопасный процесс".

В частности, все блоки finally, которые прошло исключение, не были выполнены (так, например, любые файлы обрабатываются до сбоя) и даже ограниченные области выполнения могут быть пропущены!


Кроме того, вероятно, вы должны сообщить об этом как об ошибке для Microsoft, поскольку GetAssemblyName не должно выбрасывать это исключение.