And*_*eas 12 .net vb.net exception seh
在后台线程中,我的应用程序会定期检查网络文件夹(UNC路径)以获取应用程序更新.它会读出文件的汇编版本,如下所示:
Try
newVers = System.Reflection.AssemblyName.GetAssemblyName("\\server\app.exe").Version
Catch ex As Exception
' ignore
End Try
Run Code Online (Sandbox Code Playgroud)
这段代码经常被执行,到目前为止我总共在多个客户站点猜测超过100.000次没有问题.
有时GetAssemblyName
会引发a 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()
Run Code Online (Sandbox Code Playgroud)
为什么Catch
下面的块没有捕获异常?
(也许这是相关的:这只发生在客户站点上,其中UNC路径指向不属于本地网络的服务器,而是VPN上的远程服务器.)
por*_*ges 15
从.NET 4开始,一些SEHException
s指示损坏的进程状态,并被称为"损坏的状态异常".这些是诸如段错误/访问冲突之类的事情,其中在检测到内存损坏后抛出异常.
虽然这些错误仍然映射回托管.NET SEHExceptions
,但默认情况下它们不可捕获,因此try { ... } catch (Exception ex) { ... }
无法处理它们.
您可以选择处理这些异常(通过应用程序配置文件中的属性或策略更改),但不建议这样做,因为您的程序现在可以处理无效数据:
CLR始终使用与程序本身引发的异常相同的机制向托管代码提供SEH异常.只要代码不尝试处理无法合理处理的异常条件,这就不是问题.在访问冲突后,大多数程序无法安全地继续执行.不幸的是,CLR的异常处理模型总是鼓励用户通过允许程序捕获System.Exception层次结构顶部的任何异常来捕获这些严重错误.但这很少是正确的做法.
写入捕获(异常e)是一种常见的编程错误,因为未处理的异常会产生严重后果.但是你可能会争辩说,如果你不知道函数会引发什么错误,你应该在程序调用该函数时防止所有可能的错误.这似乎是一个合理的行动方案,直到您考虑在您的流程可能处于损坏状态时继续执行意味着什么.有时中止和再次尝试是最好的选择:没有人喜欢看Watson对话框,但重启程序比让数据损坏更好.
程序捕获由他们不理解的上下文引起的异常是一个严重的问题.但是,您无法通过使用异常规范或其他合同机制来解决问题.由于CLR是多种应用程序和主机的平台,因此托管程序能够接收SEH异常通知非常重要.某些主机(如SQL Server)需要完全控制其应用程序的进程.与本机代码互操作的托管代码有时必须处理本机C++异常或SEH异常.
但是大多数编写catch(异常e)的程序员并不真正想要捕获访问冲突.他们宁愿在发生灾难性错误时停止执行程序,而不是让程序在未知状态下跛行.对于托管托管加载项(如Visual Studio或Microsoft Office)的程序尤其如此.如果加载项导致访问冲突,然后吞下异常,则主机可能会损坏自己的状态(或用户文件),而不会发现出现问题.
如果您决定处理这些异常,则需要考虑很多 - 正如文章所述:"编写处理CSE的正确代码并继续安全地运行流程非常困难."
特别是,finally
异常已经过去的任何块都没有被执行(因此,例如,任何文件句柄都悬空直到收集),甚至可以跳过约束执行区!
此外,您可能应该将此报告为Microsoft的错误,因为GetAssemblyName
不应该抛出此类异常.
归档时间: |
|
查看次数: |
7261 次 |
最近记录: |