前提
.NET Framework で CoClass を実装して登録し,そのクラスが外部のアプリケーションから呼び出される。
こねくりまわした環境
.NET Framework 4.5
Windows 10 (x64)
結論
interface の宣言に, InterfaceTypeAttribute
を設定していなかった。
だめだったコード
[ComImport]
[Guid(~~~~)]
public interface Hoge
{
// ~~~~~
}
呼び出し元プロセスに Visual Studio でアタッチするとこのような例外が表示された。
うまくいったコード
[ComImport]
[Guid(~~~~)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface Hoge
{
// ~~~~~
}
[](タイトル原案: C# で COM Server を作ろうとしたら,clr.dll が Access Violation するときに確認すべきこと)
[](タイトル案: .NET Framework で COM Server を作ろうとしたら CLR の Access Violation に悩まされた話)
以下,解決までの経緯
落ちる
C# で COM に登録するクラスを作って実験していたところ,特定のタイミングで呼び出し元のアプリケーションが落ちる。
C# で書いた部分に問題があると考え,try-catch など普段通りデバッグを行ってみるも,これらのすべてに到達せずに落ちる。何の前触れもなく。
デバッガを接続してみる
Visual Studio をそのプロセスに接続してから実験を行うと,このような表示が。
落ちるタイミングの特定
実験を続けていたら,少なくともこのタイミングで落ちるということが特定できたので,コードを減らして実験をしたところ,
C# で書いたクラスのインスタンスを COM を通して外部から呼び出されるように登録するコードを実行しない,あるいは登録後すぐに登録を解除したところ,落ちないことが分かった。
見つける
登録メソッドに渡す引数の型を確認して,渡すクラスの宣言を確認し,インターフェースの確認をしたところで, InterfaceTypeAttribute
をこのインターフェースだけ書き忘れていることがわかり,書き加えたところ登録をしてもアクセス違反が発生しなくなった。
場合によってはアクセス違反にならず,別のメソッドが呼ばれる可能性?
自分の場合は,後ろから3番目のメソッドが呼び出されるときにアクセス違反になっていたのだが,メソッドが4つ以上あるインターフェースの,最初に書かれたメソッドが呼び出されるような場合はもしかすると4番目のメソッドが呼び出されるかもしれない。
Access Violation した。よくわからない。IUnknown
が QueryInterface
, AddRef
, Release
の3つを持っているため,3つずれた結果,自分の場合は存在しない領域を参照してしまっていたのではないかと考えている。[要検証]