web-dev-qa-db-ja.com

AccessViolationExceptionを処理する方法

.netアプリケーション内からCOMオブジェクト(MODI)を使用しています。呼び出しているメソッドは、Visual StudioによってインターセプトされるSystem.AccessViolationExceptionをスローします。奇妙なことに、AccessViolationException、COMException、その他すべてのハンドラーを持つtry catchで呼び出しをラップしましたが、Visual Studio(2010)がAccessViolationExceptionをインターセプトすると、デバッガーはメソッド呼び出し(doc.OCR)で中断します。そして、ステップスルーすると、catchブロックに入る代わりに次の行に進みます。さらに、Visual Studioの外部でこれを実行すると、アプリケーションがクラッシュします。 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();

}
167
Jeremy

.NET 4.0では、ランタイムはWindows構造化エラー処理(SEH)エラーとして発生した特定の例外を、破損状態のインジケーターとして処理します。これらの破損した状態の例外(CSE)は、標準のマネージコードでキャッチできません。ここにある理由や方法については説明しません。 .NET 4.0 FrameworkのCSEについてのこの記事を読んでください。

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

しかし、希望はあります。これを回避するにはいくつかの方法があります。

  1. .NET 3.5アセンブリとして再コンパイルし、.NET 4.0で実行します。

  2. Configuration/runtime要素の下に、アプリケーションの構成ファイルに行を追加します:<legacyCorruptedStateExceptionsPolicy enabled="true|false"/>

  3. これらの例外をキャッチしたいメソッドをHandleProcessCorruptedStateExceptions属性で飾ります。詳細については、 http://msdn.Microsoft.com/en-us/magazine/dd419661.aspx#id0070035 を参照してください。


編集

以前は、詳細については フォーラム投稿 を参照していました。ただし、Microsoft Connectは廃止されているため、興味がある場合の追加の詳細を以下に示します。

Microsoft CLRチームの開発者であるGaurav Khannaから

この動作は、破損した状態の例外と呼ばれるCLR 4.0の機能による設計によるものです。簡単に言えば、マネージコードは、破損したプロセス状態を示す例外をキャッチしようとしてはならず、AVはその1つです。

次に、彼は HandleProcessCorruptedStateExceptionsAttribute および上記の記事のドキュメントを参照します。これらのタイプの例外をキャッチすることを検討している場合、言うだけで十分です。

280
villecoder

設定ファイルに次を追加すると、try catchブロックでキャッチされます。警告の言葉...これは、ある種の違反が発生していることを意味するため、この状況を回避するようにしてください。

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

上記の回答からコンパイルされ、私のために働いて、それをキャッチするために次の手順を実行しました。

ステップ#1-次のスニペットを設定ファイルに追加します

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

ステップ2

追加 -

[HandleProcessCorruptedStateExceptions]

[SecurityCritical]

関数の上部で、あなたは例外をキャッチします

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

7
EvilInside

AppDomain.UnhandledException を使用してみて、キャッチできるかどうかを確認できます。

**編集*

ここにいくつかの 詳細 があります(長い読み物です)。

1
Tony Abrams