2011-10-26 8 views
7

COMオブジェクト(アンマネージコード)を呼び出すC#プログラム(ターゲットフレームワーク.NET 4.0)C#エラー「保護されたメモリを読み書きしようとしました」または「外部コンポーネントが例外をスローしました」

私はいくつかの例外ハンドラ、カスタム例外なしでtry/catchブロックを持っています。しかし、このプログラムがクラッシュした時には、ほとんどの場合、ランダムな動作が行われます。また、スタックトレースもさまざまです(例:

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: 

Program.cs、Line 17:Application.Run(new 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: 

このエラーの原因を突き止めるために、私は分離段階にあります。

  • このエラーに関するご意見はありますか?
  • これらの例外をキャッチして正常に終了するための提案があります。

ありがとうございました。で示されるように、あなたのCOMのcoomponentsの一つが例外を引き起こしている

+0

ネイティブコードをデバッグする必要があります。これには、アンマネージデバッガが必要です。 –

+0

.NETオブジェクトの参照をCOMコンポーネントに渡しますか? – Seb

答えて

0

:=外部コンポーネントがこの2行は、あなたがCOMコンポーネントを見つけやすくして呼ばなければならない例外

を投げた

メッセージ問題の原因となっている方法

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) 

これらのCOMコンポーネントとのインターフェースをとるためにラッパーを作成しましたか?または、直接Invoke呼び出しを使用していますか?

おそらくInnerException情報が詳細を示します。

基本的に、これらのCOMコンポーネントに関連するものとして認識されるものを探します。

6

例外の原因は、una​​mangedコードであり、おそらくCOMコンポーネントです。スタックトレースは、例外がメッセージループでキャッチされていることを示しています。これは、.NETコードからSTA(シングルスレッドアパートメント)のCOMオブジェクトにクロスアパートメントコールを行った結果である可能性があります。メソッド呼び出しはマーシャリングされ、Windowsメッセージを使用してコンポーネントに送信されます。

クロスアパートの呼び出しについては何も問題はありませんが、別のアパートメントからのポインタが与えられ、一般にCOMのスレッディング規則を知らない場合、適切なマーシャリングを行わないCOMコンポーネントがあります。あなたのアプリケーションにマルチスレッドのようなものがある場合は、これを必ず調べてください。これらの「壊れた」COMオブジェクトは、メインのSTAスレッドから呼び出されたときに正常に動作しますが、別のスレッドで呼び出されたり作成されたりすると失敗する可能性があります。

具体的には:起動時にアプリケーションのUIスレッドがSTA(Single Threaded Apartment)に入り、COMコンポーネントが作成されます。その後、別のアパートにある新しいスレッドを作成し、このスレッドからCOMコンポーネントのメソッドを呼び出します。これはクロスマンションコールです。 COMコンポーネントは、UIスレッド(住んでいるアパートメントのスレッド)でのみ実行できます。COMフ​​レームワークは、クロスアパートコールを行っていることに気付き、コールをバッファにシリアル化します(マーシャル COM Lingoの呼び出し)。このバッファは、Windowsメッセージを使用してUIスレッドに送信されます。アプリケーションにウィンドウがない場合、COMはこれらのメッセージを受け取るための隠しウィンドウを作成します。アプリケーションのメッセージループは、マーシャリングされた呼び出しをアンパックし、UIスレッドで実行します。

ここでは、あなたまたはCOMコンポーネントがCOMアパートメントとマーシャリングのルールを理解していないと仮定します。メソッド呼び出しの引数の1つは、ポインターに変換されるもので、このポインターはCOMコンポーネントのアパートメントでは無効です。次に、COMコンポーネントがポインタをデフレクトすると、エラーが発生します。 .NETランタイムはこれを検出し、表示される2つの例外タイプのうちの1つをスローします。ただし、この例外は、UIスレッドのメッセージループにアクセスできないコードでスローされます。呼び出し側でtry-catchブロックを使用しても、別のスレッドで例外がスローされたときに例外をキャッチできません。とにかく、アプリケーションで実際に起こっていることの兆候であるため、例外をキャッチしないでください。

レコードの場合、エラーコード-2147467259は0x8004005で、これはE_FAILに変換されます。それほど役に立ちませんが、発生するエラーは、COMコンポーネントで無効なポインタが使用されている可能性が最も高いためです。

これを修正するには、COMコンポーネントを正しく使用するか、コンポーネント内の壊れたコードを修正する必要があります。

+0

残念ながら、私はCOMコンポーネントのソースにアクセスすることはできません。 なぜ私の一般的な例外ハンドラで例外がキャッチされないのだろうかと思います。どんな考え? – Din

+0

例外を捕まえない理由を説明するために質問を修正しました。 –

関連する問題