マネージド/アンマネージド相互運用で登録不要のCOMを機能させる方法
-
28-10-2019 - |
質問
マネージC#DLL(Managed.dll)から使用しようとしているアンマネージC ++ / ATLインプロセスCOMオブジェクト(Unmanaged.dll内)があります。ただし、登録不要のCOMを使いたい。私はこれらのステップにそれを持っています:
- 開発マシンにCOMオブジェクトを登録します。インプロセスサーバーには、適切に登録されたタイプライブラリが必要です。
- C#プロジェクト内のCOMオブジェクトへの参照を追加してから、参照プロパティをIsolated= Trueに設定します。
これにより、Unmanaged.dll、Managed.dll、およびNative.Managed.manifestが生成されます。マニフェストを開くと、システムがマニフェストを使用して、登録不要の方法でCOMオブジェクトをロードする方法がかなり明確になります。
これが摩擦です。 Managed.dllを動的にロードしてパブリックタイプにアクセスするマネージドEXE(Managed.exe)があります。 「動的に」とは、Assembly.LoadFrom( "Managed.dll")を使用することです。 Managed.dll内のコードがCOMオブジェクトを作成しようとすると、「クラスが登録されていません」という例外が発生します。 Managed.dllが読み込まれると、アクティベーションコンテキストが正しく設定されないようです。
このシナリオで登録不要のCOMを機能させる方法はありますか?
解決
答えのない2日間なので、その間に私が思いついたのは...
実際、アクティベーションコンテキストは、メインEXEに関連付けられたマニフェストに基づいてプロセスの起動時にOSによってセットアップされているように見えます。つまり、登録不要のCOM関連要素はすべて、プロセスの開始時にMain.exe.manifestに含まれている必要があります。これにより、EXEとDLLの間の分離が解除されます。 DLLがCOMオブジェクトの作成を担当している場合、EXEマニフェストにreg-freeCOM情報が含まれている必要はありません。 DLLがロードされるときに、DLLに関連付けられたマニフェストがプロセスアクティベーションコンテキストにマージされることを期待していたかもしれませんが、そうではありません。
これを回避するには、DLLはCOMオブジェクトを作成する前に新しいアクティベーションコンテキストを構成する必要があります。さらに悪いことに、現在(.NET 4.0の時点で)これを行うための管理された方法はありません。したがって、DLLは次のWin32関数をPInvokeする必要があります。
- CreateActCtx
- ActivateActCtx
- DeactivateActCtx
- ReleaseActCtx
これらの呼び出しを、コンストラクターでCreateActCtxとActivationActCtxを呼び出し、IDisposable :: DisposeでDeativateActCtxとReleaseActCtxを呼び出すマネージクラスでラップしました。