2010-08-12 19 views
139

Estoy usando un objeto COM (MODI) desde dentro de mi aplicación .net. El método que estoy llamando arroja System.AccessViolationException, que es interceptado por Visual Studio. Lo curioso es que he cerrado mi llamada en una captura de prueba, que tiene controladores para AccessViolationException, COMException y todo lo demás, pero cuando Visual Studio (2010) intercepta AccessViolationException, el depurador se rompe en la llamada al método (doc.OCR), y si paso, continúa a la siguiente línea en lugar de ingresar al bloque catch. Además, si ejecuto esto fuera del estudio visual mi aplicación se bloquea. ¿Cómo puedo manejar esta excepción que se lanza dentro del objeto COM?Cómo manejar AccessViolationException

MODI.Document doc = new MODI.Document(); 
try 
{ 
    doc.Create(sFileName); 
    try 
    { 
     doc.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false); 
     sText = doc.Images[0].Layout.Text; 
    } 
    catch (System.AccessViolationException ex) 
    { 
     //MODI seems to get access violations for some reason, but is still able to return the OCR text. 
     sText = doc.Images[0].Layout.Text; 
    } 
    catch (System.Runtime.InteropServices.COMException ex) 
    { 
     //if no text exists, the engine throws an exception. 
     sText = ""; 
    } 
    catch 
    { 
     sText = ""; 
    } 

    if (sText != null) 
    { 
     sText = sText.Trim(); 
    } 
} 
finally 
{ 
    doc.Close(false); 

    //Cleanup routine, this is how we are able to delete files used by MODI. 
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc); 
    doc = null; 
    GC.WaitForPendingFinalizers(); 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 

} 
+0

¿Ha intentado poner un controlador 'Exception' (temporalmente) para atrapar todas las excepciones y ver cuál es la excepción * en realidad *? – ChrisF

+2

@ChrisF: sí, ¿ves el último controlador de catch? Eso debería atrapar todo, incluida la excepción y cualquier subclase de excepción. Además, Visual Studio informa que la excepción es System.AccessViolationException – Jeremy

+0

D'oh - se perdió eso, lo siento. – ChrisF

Respuesta

239

En .NET 4.0, el tiempo de ejecución maneja ciertas excepciones planteadas como errores de manejo de errores estructurados de Windows (SEH) como indicadores de estado dañado. Estas Excepciones de estado dañado (CSE) no pueden ser atrapadas por su código administrado estándar. No entraré en el por qué o cómo está aquí. Lee este artículo sobre el CSE está en el .NET Framework 4.0:

http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035

Pero hay esperanza. Hay algunas formas de evitar esto:

  1. Vuelva a compilar como un ensamblado .NET 3.5 y ejecútelo en .NET 4.0.

  2. añadir una línea al archivo de configuración de la aplicación bajo el elemento de configuración/tiempo de ejecución: <legacyCorruptedStateExceptionsPolicy enabled="true|false"/>

  3. Decorar los métodos que se desea capturar estas excepciones con el atributo HandleProcessCorruptedStateExceptions. Vea http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035 para más detalles.

Para mayor referencia: http://connect.microsoft.com/VisualStudio/feedback/details/557105/unable-to-catch-accessviolationexception

+43

HandleProcessCorruptedStateExceptions hace el truco. – Jeremy

+7

'HandleProcessCorruptedStateExceptions' funciona para mí en .Net 4.5. – deerchao

+1

Gracias, esto realmente ayudó. – FlyingMaverick

1

puede probar a usar AppDomain.UnhandledException y ver si eso le permite ponerse él.

** * EDITAR

Aquí es un poco de more information que podría ser útil (es una lectura larga).

+1

AppDomain.UnhandledException probado, sin suerte, le dará al artículo una lectura ... – Jeremy

+1

Esta respuesta ya no es completa debido a los cambios en el marco de .NET. Antes de 4.0 es correcto. Por sección de AccessViolationException y try/catch bloques en https://msdn.microsoft.com/en-us/library/system.accessviolationexception(v=vs.110).aspx – Tedford

11

Añadir lo siguiente en el archivo de configuración, y serán atrapados en el bloque intento de captura. Palabra de advertencia ... trate de evitar esta situación, ya que esto significa que está ocurriendo algún tipo de violación.

<configuration> 
    <runtime> 
     <legacyCorruptedStateExceptionsPolicy enabled="true" /> 
    </runtime> 
</configuration> 
+0

Para aquellos que usan C++/cli como dll, el código debe agregarse al proyecto .exe superior. – Felix

4

Compilado de las respuestas anteriores, funcionó para mí, hizo los siguientes pasos para atraparlo.

Paso # 1 - Añadir siguiente fragmento de archivo de configuración

<configuration> 
    <runtime> 
     <legacyCorruptedStateExceptionsPolicy enabled="true" /> 
    </runtime> 
</configuration> 

Paso # 2

Add -

[HandleProcessCorruptedStateExceptions] 

[SecurityCritical] 

en la parte superior de la función que está atando captura la excepción

fuente: http://www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html

+0

De acuerdo con https://msdn.microsoft.com/en-us/library/system.security.securitycriticalattribute(v=vs.110).aspx, SecurityCriticalAttribute es equivalente a una solicitud de enlace para obtener plena confianza. No creo que el problema descrito requiera una confianza total exigente. – Jeremy

Cuestiones relacionadas