C # error "Attempted to read or write protected memory" or "External component threw an exception"

I have a C # program (target platform .NET 4.0) that calls COM objects (unmanaged code), all objects are managed properly, destroyed when they are no longer needed, etc.

I also have several exception handlers, try / catch blocks without custom exceptions. However, several times this program crashed, working most of the time, random behavior. Stack traces also vary, for example:

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: 

In Program.cs, line 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: 

I am in isolation to find out the root of this error.

  • Do you have any suggestions about this error?
  • Any suggestions on catching these exceptions and a graceful exit.

Thank you for your help.

+7
source share
2 answers

The original exceptions are unchanged code and most likely your COM components. A stack trace indicates that exceptions fall into your message loop, and this may be the result of cross-calling apartments from your .NET code into a COM object in STA (Single Threaded Apartment). Then, method calls are then marshaled and sent using window messages to the component.

There is nothing wrong with making cross calls to the apartment, but I saw that some COM components did not perform proper marshaling when they were pointed to by pointers from another apartment and did not know about the flow rules in COM at all. If your application has any kind of multithreading, you definitely need to learn this. These β€œbroken” COM objects will behave well when called from the main STA thread, but may fail when called or created on different threads.

More specifically: Assume that the application user interface thread at startup enters the STA (Single Threaded Apartment) and creates a COM component. Then you create a new thread (which will be in another apartment), and from this thread you call the method on the COM component. This is a cross call apartment. The COM component can only be run in a user interface thread (a thread in the apartment in which it lives). In the COM infrastructure, note that you are cross-calling the apartment, and it will serialize the call to the buffer (call marshal in COM lingua). This buffer is then sent to the user interface stream using a Windows message. If your application does not have a window, COM will create a hidden window to receive these messages. Then the message loop of your application will unpack the marshall call and execute it in the user interface thread.

Now let's assume that either you or the COM component do not understand the rules of COM apartments and sorting. One of the arguments in a method call is a pointer or something that resolves to a pointer, and that pointer is not valid in the apartment of the COM component. Then, when the COM component cancels the pointer, you get an error. The .NET runtime will detect this and throw one of two types of exceptions that you see. However, this exception is thrown into the message loop of the user interface stream, in some code that you do not have access to. Using the try-catch block on the caller does not help catch the exception, because it is thrown in a different thread. In any case, you should not catch an exception, because this is a sign of something really bad in your application.

For writing, error code -2147467259 is 0x8004005, which corresponds to E_FAIL. Not very useful, but the errors you experience are most likely due to invalid pointers used in the COM component.

To fix this, you will need to use COM components correctly and / or fix any broken code in the components.

+6
source

One of your COM components throws an exception as indicated:

Message = External component throws an exception

These two lines will help you determine which COM component and the called method are causing the problem:

  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) 

I understand that you wrote a shell to interact with these COM components? Or are you using direct invoke calls?

Perhaps the InnerException information will provide you more detailed information.

Basically find everything you can recognize as related to these COM components.

0
source

All Articles