我有一个C#程序(目标框架.NET 4.0),它调用COM对象(非托管代码),正确管理所有对象,不再需要时销毁,等等.
我也有一些异常处理程序,没有自定义异常的try/catch块.然而有时候这个程序崩溃了,大部分时间都是随机行为.堆栈跟踪也有所不同,例如:
System.AccessViolationException was unhandled
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at IndexerTester.Program.Main() in D:\Tester\Program.cs:line 17
InnerException:
Run Code Online (Sandbox Code Playgroud)
在Program.cs中,第17行:Application.Run(new Form1());
System.Runtime.InteropServices.SEHException was unhandled
Message=External component has thrown an exception.
Source=System.Windows.Forms
ErrorCode=-2147467259
StackTrace:
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at IndexerTester.Program.Main() in D:\Tester\Program.cs:line 17
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
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()
InnerException:
Run Code Online (Sandbox Code Playgroud)
我处于隔离阶段,找出这个错误的根源.
谢谢你的帮助.
异常的来源是无人值守的代码,很可能是您的COM组件.堆栈跟踪指示异常在消息循环中捕获,这可能是因为从.NET代码到STA(单线程单元)中的COM对象进行跨公寓调用.然后对方法调用进行封送处理,并使用Windows消息将其发送到组件.
进行跨公寓呼叫没有任何问题,但是我看到一些COM组件在从不同的公寓发出指针时没有做正确的编组,并且通常对COM中的线程规则一无所知.如果你的应用程序中有任何类型的多线程,你一定要看看这个.从主STA线程调用时,这些"损坏"的COM对象将表现良好,但在不同线程上调用或创建时可能会失败.
更具体一点:假设启动时应用程序UI线程进入STA(单线程单元)并创建COM组件.然后创建一个新线程(将在另一个公寓中),并从该线程调用COM组件上的方法.这是一个跨公寓电话.您的COM组件只能在UI线程(它所在的公寓的线程)上执行.COM框架会注意到你正在进行跨公寓呼叫,它会将呼叫序列化为一个缓冲区(用COM术语编组调用).然后使用Windows消息将此缓冲区发送到UI线程.如果您的应用程序没有窗口,COM将创建一个隐藏窗口来接收这些消息.然后,应用程序的消息循环将解压缩编组调用并在UI线程上执行它.
现在,让我们假设您或COM组件不了解COM公寓和编组规则.方法调用中的一个参数是一个指针或某个解析为指针的东西,并且该指针在COM组件的单元中无效.然后,当COM组件derefences指针时,您会收到错误..NET运行时将检测到这一点并抛出您看到的两种异常类型之一.但是,此异常将在UI线程的消息循环中抛出,您可以访问某些代码.在调用者处使用try-catch块无助于捕获异常,因为它在另一个线程上抛出.无论如何,你不应该捕获异常,因为它表明你的应用程序中发生了一些非常糟糕的事情.
对于记录,错误代码-2147467259是0x8004005,转换为E_FAIL.不是很有帮助,但您遇到的错误很可能是由于COM组件中使用了无效指针.
要解决此问题,您必须正确使用COM组件和/或修复组件中的任何损坏代码.
您的 COM 组件之一导致了异常,如下所示:
消息=外部组件抛出异常
这两行应该可以帮助您找到导致问题的 COM 组件和调用的方法:
Run Code Online (Sandbox Code Playgroud)at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
我认为您已经编写了一个包装器来连接这些 COM 组件?或者您正在使用直接 Invoke 调用吗?
也许 InnerException 信息将为您提供更多详细信息。
基本上寻找您可能认为与这些 COM 组件相关的任何内容。
| 归档时间: |
|
| 查看次数: |
6601 次 |
| 最近记录: |