Я использую COM-объект (MODI) из моего приложения .net. Метод, который я вызываю, вызывает исключение System.AccessViolationException, которое перехватывается Visual Studio. Странно то, что я заключил свой вызов в try catch, у которого есть обработчики для AccessViolationException, COMException и всего остального, но когда Visual Studio (2010) перехватывает AccessViolationException, отладчик прерывает вызов метода (doc.OCR), и если я перейду, он перейдет к следующей строке вместо входа в блок catch. Кроме того, если я запускаю это за пределами визуальной студии, мое приложение вылетает. Как я могу обработать это исключение, которое возникает в COM-объекте?
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();
}
Exception
обработчик (временно!), Чтобы перехватить все исключения и посмотреть, что это за исключение на самом деле ?Ответы:
В .NET 4.0 среда выполнения обрабатывает определенные исключения, возникающие как ошибки структурной обработки ошибок Windows (SEH), как индикаторы поврежденного состояния. Эти исключения поврежденного состояния (CSE) не могут быть обнаружены вашим стандартным управляемым кодом. Я не буду вдаваться в подробности почему и как здесь. Прочтите эту статью о CSE в .NET 4.0 Framework:
http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035
Но есть надежда. Есть несколько способов обойти это:
Перекомпилируйте как сборку .NET 3.5 и запустите ее в .NET 4.0.
Добавьте строку в файл конфигурации вашего приложения под элементом конфигурации / времени выполнения:
<legacyCorruptedStateExceptionsPolicy enabled="true|false"/>
Украсьте методы, в которых вы хотите перехватывать эти исключения,
HandleProcessCorruptedStateExceptions
атрибутом. Подробности см. На http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035 .РЕДАКТИРОВАТЬ
Ранее я ссылался на сообщение на форуме для получения дополнительных сведений. Но поскольку Microsoft Connect больше не работает, вот дополнительные сведения, если вам это интересно:
От Гаурава Ханна, разработчика из команды Microsoft CLR.
Затем он обращается к документации по атрибуту HandleProcessCorruptedStateExceptionsAttribute и указанной выше статье. Достаточно сказать, что это определенно стоит прочитать, если вы планируете перехватить эти типы исключений.
источник
HandleProcessCorruptedStateExceptions
у меня работает в .Net 4.5.OR
» способ сделать это. :)Добавьте следующее в конфигурационный файл, и он будет пойман в блоке try catch. Предупреждение ... старайтесь избегать этой ситуации, так как это означает, что происходит какое-то нарушение.
<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true" /> </runtime> </configuration>
источник
Скомпилированный из приведенных выше ответов, работал у меня, сделал следующие шаги, чтобы его поймать.
Шаг №1 - Добавьте следующий фрагмент в файл конфигурации
<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true" /> </runtime> </configuration>
Шаг 2
Добавить -
[HandleProcessCorruptedStateExceptions] [SecurityCritical]
в верхней части функции, которую вы связываете, поймайте исключение
источник: http://www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html
источник
Microsoft: «Исключения из состояния поврежденного процесса - это исключения, которые указывают на то, что состояние процесса было повреждено. Мы не рекомендуем запускать ваше приложение в этом состоянии ..... Если вы абсолютно уверены, что хотите продолжить обработку этих исключения, вы должны применить
HandleProcessCorruptedStateExceptionsAttribute
атрибут "Microsoft: «Используйте домены приложений, чтобы изолировать задачи, которые могут остановить процесс».
Приведенная ниже программа защитит ваше основное приложение / поток от неисправимых сбоев без рисков, связанных с использованием
HandleProcessCorruptedStateExceptions
и<legacyCorruptedStateExceptionsPolicy>
public class BoundaryLessExecHelper : MarshalByRefObject { public void DoSomething(MethodParams parms, Action action) { if (action != null) action(); parms.BeenThere = true; // example of return value } } public struct MethodParams { public bool BeenThere { get; set; } } class Program { static void InvokeCse() { IntPtr ptr = new IntPtr(123); System.Runtime.InteropServices.Marshal.StructureToPtr(123, ptr, true); } private static void ExecInThisDomain() { try { var o = new BoundaryLessExecHelper(); var p = new MethodParams() { BeenThere = false }; Console.WriteLine("Before call"); o.DoSomething(p, CausesAccessViolation); Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); //never stops here } catch (Exception exc) { Console.WriteLine($"CSE: {exc.ToString()}"); } Console.ReadLine(); } private static void ExecInAnotherDomain() { AppDomain dom = null; try { dom = AppDomain.CreateDomain("newDomain"); var p = new MethodParams() { BeenThere = false }; var o = (BoundaryLessExecHelper)dom.CreateInstanceAndUnwrap(typeof(BoundaryLessExecHelper).Assembly.FullName, typeof(BoundaryLessExecHelper).FullName); Console.WriteLine("Before call"); o.DoSomething(p, CausesAccessViolation); Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); // never gets to here } catch (Exception exc) { Console.WriteLine($"CSE: {exc.ToString()}"); } finally { AppDomain.Unload(dom); } Console.ReadLine(); } static void Main(string[] args) { ExecInAnotherDomain(); // this will not break app ExecInThisDomain(); // this will } }
источник
Вы можете попробовать использовать AppDomain.UnhandledException и посмотреть, позволит ли вам его поймать.
**РЕДАКТИРОВАТЬ*
Вот еще некоторая информация, которая может быть полезна (это долгое чтение).
источник