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
не должно выбрасывать это исключение.