0

ATL サービス VC++2010 テンプレートに基づくプロセス外サーバーがあります。現在、独自の COM クラスを含む追加の dll を動的にロードして、彼の COM インターフェイスを拡張することはありません。ロードする dll は、単純な ATL オブジェクト「IMModule」を含む ATL dll VC++2010 テンプレートに基づいています。LocalServer セクションとサーバーの AppID を次のように追加して、対応する .rgs ファイルを変更し、クラスを dll から EXE サーバーに接続しました。

HKCR
{
  NoRemove CLSID
  {
    ForceRemove {59276614-A811-4D27-B131-514656E643D3} = s 'IMModule Class'
    {
      ForceRemove Programmable
      LocalServer32 = s 'path to the service exe'
      {
    val ServerExecutable = s 'path to the service exe'
      }
      TypeLib = s '{250685C7-CBD3-4FF8-A3A6-2AF668794CFC}'
      Version = s '1.0'
      val AppID = s '{7EFD508A-53C6-4EA0-B21A-D29277B86CBC}'
    }
  }
}

dll をロードした後にサービスによって呼び出される dll init() メソッドで、CoRegisterClassObject を呼び出して IMModule クラス オブジェクトを登録します。しかし、 IUnknown インターフェイス ポインター ( CoRegisterClassObject の 2 番目のパラメーター) を取得する方法がわかりません。私は次のことを試しました:

CIMModule::_ClassFactoryCreatorClass* pClassFak = 
    new CIMModule::_ClassFactoryCreatorClass;
IUnknown* pUnk;
HRESULT hr =
pClassFak->CreateInstance(CIMModule::_ClassFactoryCreatorClass::CreateInstance, 
                            IID_IIMModule, (LPVOID*)&pUnk);

しかし、CreateInstance の呼び出しは E_NOINTERFACE で失敗します。では、DLL 内に実装された IMModule クラスを登録して、アウト プロセス サーバーから COM クライアントが利用できるようにする方法を教えてください。

4

2 に答える 2

1

Roman.RI の助けを借りて、必要な動作を取得します。@roman-r さん、いくら感謝してもしきれません。私が行ったことを正確に説明するので、誰かが手順をたどって応答してくれるかもしれません。

まず、ATL ベースの Windows サービス (UmbrellaService という名前) を作成しました。UmbrellaService 内に、Control という名前の単純な ATL オブジェクトを追加し、次のメソッドを追加しました。

 FindMeAnInterface(BSTR moduleName, IDispatch** ppDispach);

VC++ ウィザードについては以上です。次に、次を追加して Control.rgs ファイルを修正しました。

 val AppID = s '%APPID%'

なぜ VC++ は 17 年間の進化を経てもまだそのようなバグを抱えているのでしょうか? ( CoCreateInstance が開始されない、または ATL COM サービスに接続されないを参照してください) 次に、"Module" シンプルな ATL オブジェクトを内部に持つ、MyModule という名前の ATL-dll プロジェクトを作成しました。Module クラスにはメソッドがあります

testMethod (LONG a, LONG b, LONG* sum)"

MyModule dll はインプロセス サーバーとして登録されます。さらに、dll には、必要に応じて dll をプラグインにするクラスがいくつかあります。

UmbrellaService の PreMessageLoop メソッドでは、MyModule dll が LoadLibrary でロードされ、GetProcAddress を通じてファクトリ作成メソッドのアドレスが取得されます。ファクトリ作成メソッドは、プラグイン エントリ ポイントとして機能するプラグイン依存の FactoryClass を返します。これは私の COM に依存しないプラグイン メカニズムです。

ここで、プラグイン dll から UmbrellaService インターフェイスを介してモジュール インターフェイスをエクスポートするために、次のことを行いました。 FactoryClass にメソッドを追加します。

IDispatch* getInterface();

getInterface メソッドで呼び出します

CoCreateInstance(__uuidof(Module), NULL , CLSCTX_INPROC_SERVER , __uuidof(IDispatch), (VOID**) &pDispatch); 

取得した IDispatch インターフェイスを返します。FactoryClass::getInterface メソッドは、FindMeAnInterface に渡された名前と FactoryClass によって提供された名前を比較した後、UmbrellaService の Control::FindMeAnInterface メソッド内で呼び出されます。FindMeAnInterface は、取得した IDispatch ポインタをクライアントに返します。

クライアント側では、UmbrellaService から tlb ファイルをインポートし、適切なプラグイン dll から tlb をインポートします。次のように testMethod を呼び出します。

IControlPtr pControl(__uuidof(Control));
_bstr_t moduleName("Module");
IDispatchPtr moduleDisp = pControl->FindMeAnInterface(moduleName);
IModulePtr pModule(moduleDisp );
LONG res = pModule->testMethod(42,23);

これはすべて実際に機能しますが、これがその方法であるかどうかはわかりません。参照カウントについて何か見逃しましたか? プラグイン DLL は 2 回ロードされますか? 1 回目はプラグイン メカニズムを使用し、2 回目は CoCreateInstance を使用しますか? 他に注意すべきことはありますか?

ご協力いただきありがとうございます!

于 2012-07-10T11:18:19.573 に答える
0

これまで自分のコードを見つけることができませんでした。しかし、お気に入りの Web サイトの 1 つである The Code Project を確認しました。特に COM などの古いテクノロジで人気がありました (そうです)。新しい WFC やその他のテクノロジではなく、COM を使用する必要があることをすでに確信していただければ幸いです。

適切なドキュメントとサンプル コード@ATL COM EXE docを確認してください。この Web ページは、過去のプロジェクトの開始点として使用したと思います。

頑張って楽しんでね。

于 2012-07-06T19:09:02.080 に答える