C# error “Attempted to read or write protected memory” or “External component has thrown an exception”

前端 未结 2 347
伪装坚强ぢ
伪装坚强ぢ 2021-01-18 03:41

I have a C# program (target framework .NET 4.0) which makes calls to COM objects (unmanaged code), all objects managed properly, destroyed when no longer required, etc.

相关标签:
2条回答
  • 2021-01-18 04:13

    One of your COM coomponents is causing the exception as indicated by:

    Message=External component has thrown an exception

    These two lines should help you locate which COM component and the called method that is 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 take it that you've written a wrapper in order to interface to these COM components? Or are you using direct Invoke calls?

    Perhaps the InnerException information would give you more details.

    Basically look for anything that you may recognise as being related to these COM components.

    0 讨论(0)
  • 2021-01-18 04:24

    The source of the exceptions are unamanged code and most likely your COM components. The stack trace indicates that the exceptions are caught in your message loop and this might be a result of doing cross apartment calls from your .NET code into a COM object in a STA (Single Threaded Apartment). Method calls are then marshaled and sent using windows messages to the component.

    There is nothing wrong about doing cross apartment calls, but I have seen some COM components not doing proper marshaling when given pointers from a different apartment and in general being ignorant about the threading rules in COM. If there is any kind of multi-threading in you application you should definitely look into 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.

    To be more specific: Lets say that your applications UI thread on startup enters a STA (Single Threaded Apartment) and creates the COM component. You then create a new thread (which will be in another apartment) and from this thread you call a method on the COM component. This is a cross apartment call. Your COM component can only execute on the UI thread (the thread of the apartment it lives in). The COM framework will note that you are doing a cross apartment call and it will serialize the call into a buffer (marshal the call in COM lingo). This buffer is then sent to the UI thread using a Windows message. If your application doesn't have a window COM will create a hidden window to receive these messages. The message loop of your application will then unpack the marshalled call and execute it on the UI thread.

    Now, lets assume that either you or the COM component doesn't understand the rules of COM apartments and marshalling. One of the arguments in the method call is a pointer or something that resolves into a pointer and this pointer isn't valid in the apartment of the COM component. Then, when the COM component derefences the pointer you get an error. The .NET runtime will detect this and throw one of the two exception types you see. However, this exception is thrown in the message loop of the UI thread, some code you don't have access to. Using a try-catch block at the caller doesn't help catching the exception as it is thrown on another thread. Anyway, you shouldn't catch the exception because it is a sign of something really bad going on in your application.

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

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

    0 讨论(0)
提交回复
热议问题