EXE(OUT-OF-PROCESS)COMサーバーには登録フリーのアクティベーションが可能ですか?
-
13-09-2020 - |
質問
ColoadLibraryとDllGetClassObjectを使用してICLassFactoryインタフェースを取得し、DLLを登録せずにCOMコンポーネントインタフェースを取得できることを知っています。
しかし、EXEのCOM成分はどうですか?異なるファイルパスを提供するだけで、EXEタイプのCOMサーバーからCOMコンポーネントインタフェースを取得できる方法はありますか?
解決
real 登録無料COMには、in-procおよびout-of-proc comオブジェクトの両方でこの機能を得ることができるはずです。
SharpToothが指摘したように、あなたは本当に登録無料のCOMを使用していません。代わりに、アクティベーション中にCOMが使用するコールを偽造することで、本当に自分自身を転がしています。アプリケーションとCOMサーバーの両方を制御している場合は、ソリューションが機能できますが、それ以外の場合は失敗する可能性があります。
他のヒント
いいえ、あなたはできません。プログラムとOUT-PROC COMサーバーの間にCOMセットアップマーシャリングが必要です。これを実現するには、CoInitialize()
を呼び出してからCoCreateInstance()
またはCoGetClassObject()
を呼び出す必要があります。
in-procサーバーを呼び出して、CoLoadLibrary()
を呼び出してからDllGetClassObject()
- は、実際にはダーティハックです - それは通常のCOMメカニズムをバイパスします。要件(STA / MTAのもの)。In-Procサーバーは、いくつかの周知の機能が公開された通常のDLLであるため、このような汚れたハックが可能です。OUT-PROC COMサーバーでは同じことが不可能です。その場合はCOMに頼る必要があります。
関数呼び出しでCOMコンポーネントをポインタとして渡すことができます。
では、EXEにオブジェクトを実装し、DLLから別のCOMオブジェクトをロードすると、EXEベースのオブジェクトをDLLからオブジェクトに渡すことができます。ロードされたオブジェクトは、ポインタを受け入れる関数を持つインターフェイスをサポートする必要があります。
interface ILoadedObject
{
HRESULT GiveObject(IUnknown *pObj);
};
.
DLLベースのオブジェクトがそれを実装している場合は、EXEからそれを呼び出して登録されていないオブジェクトを渡すことができるので、達成するためにEXEにオブジェクトを登録する必要はありません。これ。
IUnknown
の正しい実装にある唯一の要件は、Release
が正しい回数と呼ばれ、QueryInterface
を使用してオブジェクト上の固定インターフェイスのセットを通過することを確実にすることができます。 IUnknown
の照会は常に同じアドレスを返します。
一方、EXEをオブジェクトのサーバーとして登録することはできますが、それは多くの複雑さを紹介します。 COMはEXE実行を開始してからWindowsメッセージキューを介してメッセージを送信する必要があります。これはOLEに広く使用されています。それはかなり壊れやすいかもしれません。
更新
より完全な解決策は、オブジェクト型のインスタンスを作成するための標準的な方法を定義することですが、EXEが機能する方法を定義できるようにすることです。 EXEは実装されます:
interface IComponent;
interface IEnvironment : IUnknown
{
HRESULT CreateInstance(REFCLSID clsid, IComponent **ppNew);
}
.
すべてのコンポーネントはこのインタフェースをサポートしている必要があります。
interface IComponent : IUnknown
{
HRESULT SetEnvironment(IEnvironment *pEnv);
}
.
EXEがレジストリを使用してコンポーネントを見つけたい標準的な動作を取得するには、次のようなCreateInstance
メソッドを実装できます。
HRESULT Env::CreateInstance(REFCLSID clsid, IComponent **ppNew)
{
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
__uuidof(IComponent), (void **)&ppNew);
if (FAILED(hr))
return hr;
(*ppNew)->SetEnvironment(this);
return S_OK;
}
.
もちろん、これを変更していくつかのコンポーネントを変更することができます。そのため、レジストリの代わりに(またはそれに加えて)設定ファイルを使用することができます。または(尋ねたように)EXEはいくつかのコンポーネントの実装を組み込んでいる可能性があります:
作成時に環境がすべてのコンポーネントに通知されるため、環境を使用してその他のコンポーネントを作成できます。
// inside some component:
HRESULT Comp::SetEnvironment(IEnvironment *e)
{
m_env = e; // using a smart pointer for ref-counting
return S_OK;
}
// in some method of the component
ComPtr<IComponent> button;
m_env->CreateInstance(CLSID_Button, &button);
// now query button for more useful interface...
.
soコンポーネントが作成されるたびに、環境(EXEで定義されている)は、コンポーネントの実装がどのように見つかったかを正確に制御できます。すべての作成はexeを介して行く。
これは「依存注入」または「対照の反転」と呼ばれることがあります。