2011-10-26 20 views
7

Tengo un programa en C# (objetivo NET Framework 4.0) que hace que las llamadas a los objetos COM (código no administrado), todos los objetos administrados adecuadamente y se desgarra cuando ya no sean necesarios, etc.C "Intento de leer o escribir en la memoria protegida" o "componente externo ha iniciado una excepción"

también tengo manejador pocas excepciones, bloques try/catch sin excepciones personalizadas. Sin embargo, algunas veces este programa se bloquea, funciona la mayoría de las veces, el comportamiento aleatorio. trazas de la pila también varían, ejemplo:

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: 

En Program.cs, Línea 17: Application.Run (nuevo 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: 

Estoy en la etapa de aislamiento para averiguar la raíz de este error.

  • ¿Tiene alguna sugerencia de este error?
  • Cualquier sugerencia sobre atrapar estas excepciones y salir con gracia.

Gracias por su ayuda.

+0

Deberá depurar el código nativo. Eso requiere un depurador no administrado. –

+0

¿Transfiere referencias sobre los objetos .NET a los componentes COM? – Seb

Respuesta

0

Uno de sus coomponents COM está causando la excepción, como se indica por:

Mensaje = componente externo ha iniciado una excepción

Estas dos líneas deberían ayudar a localizar qué componente COM y la llamada método que está causando el problema:

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) 

Supongo que ha escrito un contenedor para interactuar con estos componentes COM? ¿O está utilizando llamadas directas de Invoke?

Tal vez la información InnerException le daría más detalles.

vistazo Básicamente cualquier cosa que se puede reconocer por estar relacionados con estos componentes COM.

6

El origen de las excepciones son código no procesado y muy probablemente sus componentes COM. El seguimiento de la pila indica que las excepciones están atrapadas en su ciclo de mensajes y esto podría ser el resultado de realizar llamadas entre apartamentos desde su código .NET a un objeto COM en un STA (Apartamento de un solo subproceso). Las llamadas a métodos se clasifican y envían utilizando mensajes de Windows al componente.

No hay nada malo en hacer llamadas de apartamentos cruzadas, pero he visto algunos componentes COM no hacer el cálculo de referencias adecuado cuando se administra punteros de un apartamento diferente y, en general, ser ignorante acerca de las reglas de roscado en COM. Si hay algún tipo de multi-threading en su aplicación, definitivamente debe considerar esto. Estos objetos COM "rotos" se comportarán bien cuando se invoquen desde el hilo STA principal, pero pueden fallar cuando se los llama o se crean en hilos diferentes.

Para ser más específicos: Digamos que su hilo de aplicaciones de interfaz de usuario en el arranque entra en una STA (único subproceso Apartamento) y crea el componente COM. A continuación, crea un nuevo hilo (que estará en otro departamento) y de este hilo llama a un método en el componente COM. Esta es una llamada entre apartamentos. Su componente COM solo se puede ejecutar en el hilo de UI (el hilo del departamento en el que vive).El marco COM notará que está haciendo una llamada de varios pisos y serializará la llamada en un búfer (Marshal llamada en COM lingo). Este búfer se envía a la secuencia de la interfaz de usuario utilizando un mensaje de Windows. Si su aplicación no tiene una ventana, COM creará una ventana oculta para recibir estos mensajes. El bucle de mensajes de su aplicación descomprimirá la llamada marshalled y la ejecutará en el subproceso UI.

Ahora, supongamos que usted o el componente COM no comprende las reglas de los departamentos COM y la clasificación. Uno de los argumentos en la llamada al método es un puntero o algo que se resuelve en un puntero y este puntero no es válido en el departamento del componente COM. Luego, cuando el componente COM pone a cero el puntero se obtiene un error. El tiempo de ejecución de .NET detectará esto y arrojará uno de los dos tipos de excepciones que ve. Sin embargo, esta excepción se genera en el bucle de mensaje del subproceso de la interfaz de usuario, código al que no tiene acceso. El uso de un bloque try-catch en la persona que llama no ayuda a atrapar la excepción, ya que se lanza a otro hilo. De todos modos, no debería detectar la excepción porque es un signo de que algo realmente malo está sucediendo en su aplicación.

Para el registro, el código de error -2147467259 es 0x8004005 que se traduce en E_FAIL. No es muy útil, pero es probable que los errores que experimente se deba a que los punteros no válidos se utilizan en el componente COM.

Para resolver esto, tendrá que usar los componentes COM correctamente y/o reparar cualquier código roto en los componentes.

+0

Desafortunadamente, no tengo acceso a la fuente del componente COM. Me pregunto por qué la excepción no queda atrapada en mi controlador de excepción general. ¿Cualquier pensamiento? – Din

+0

Modifiqué mi pregunta para explicar por qué no puedes ver las excepciones. –

Cuestiones relacionadas