2010-08-12 3 views
139

Я использую COM-объект (MODI) из моего приложения .net. Метод, который я вызываю, вызывает исключение System.AccessViolationException, которое перехватывается Visual Studio. Странно, что я завернул свой вызов в try catch, у которого есть обработчики для AccessViolationException, COMException и всего остального, но когда Visual Studio (2010) перехватывает AccessViolationException, отладчик прерывает вызов метода (doc.OCR), и если я пройду через нее, она продолжит следующую строку вместо входа в блок catch. Кроме того, если я запустил это за пределами визуальной студии, мое приложение выйдет из строя. Как я могу обработать это исключение, которое выбрасывается в COM-объект?Как обращаться с 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

Вы пытались помещать обработчик 'Exception' в (временно!), Чтобы уловить все исключения и посмотреть, что такое исключение * на самом деле *? – ChrisF

+2

@ChrisF - да, см. Последний обработчик улова? Это должно поймать все, включая Exception и любой подкласс Exception. Кроме того, Visual studio сообщает, что исключением является System.AccessViolationException – Jeremy

+0

D'oh - пропустил это, извините. – ChrisF

ответ

239

В .NET 4.0 среда выполнения обрабатывает определенные исключения, вызванные ошибками обработки структурированных ошибок Windows (SEH) как индикаторы поврежденного состояния. Эти Исключенные Исключения Исключения (CSE) не могут быть уловлены вашим стандартным управляемым кодом. Я не буду вдаваться в то, почему и как здесь. Прочитайте эту статью о CSE лет в Рамках .NET 4.0:

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

Но есть надежда. Существует несколько способов обойти это:

  1. Перекомпилировать как сборку .NET 3.5 и запустить ее в .NET 4.0.

  2. Добавьте строку в конфигурационный файл вашего приложения в элементе конфигурации/выполнения: <legacyCorruptedStateExceptionsPolicy enabled="true|false"/>

  3. Украсьте методы, которые вы хотите, чтобы поймать эти исключения с использованием атрибута HandleProcessCorruptedStateExceptions. См. http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035.

Для получения дополнительной справки: http://connect.microsoft.com/VisualStudio/feedback/details/557105/unable-to-catch-accessviolationexception

+43

HandleProcessCorruptedStateExceptions делает трюк. – Jeremy

+7

'HandleProcessCorruptedStateExceptions' работает для меня в .Net 4.5. – deerchao

+1

Спасибо, это действительно помогло. – FlyingMaverick

1

Вы можете попробовать использовать AppDomain.UnhandledException и посмотреть, если это позволяет поймать его.

** EDIT *

Вот некоторые more information, которые могут быть полезны (это долго читать).

+1

Tried AppDomain.UnhandledException, не повезло, даст статью прочитанной ... – Jeremy

+1

Этот ответ больше не является точным из-за изменений в .NET framework. До 4.0 это правильно. За раздел AccessViolationException и блоки try/catch в https://msdn.microsoft.com/en-us/library/system.accessviolationexception(v=vs.110).aspx – Tedford

11

Добавьте следующее в конфигурационном файле, и он будет пойман в попытке поймать блок. Осторожно ... старайтесь избегать этой ситуации, так как это означает, что происходит какое-то нарушение.

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

Для тех, кто использует C++/cli как dll, код должен быть добавлен в верхний .exe-проект. – Felix

4

Скомпилированный из ответов выше, работал для меня, сделал следующие шаги, чтобы поймать его.

Шаг # 1 - Добавьте следующий фрагмент в конфигурационный файл

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

Шаг № 2

Add -

[HandleProcessCorruptedStateExceptions] 

[SecurityCritical] 

на вершине функции вы зафиксируете поймать исключение

источник: http://www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html

+0

Согласно https://msdn.microsoft.com/en-us/library/system.security.securitycriticalattribute(v=vs.110).aspx, атрибут SecurityCriticalAttribute эквивалентен запросу связи для полного доверия. Я не думаю, что описанная проблема требует требовать полного доверия. – Jeremy