2016-06-13 14 views
2

(アイコンオーバーレイハンドラのために)私は、COMオブジェクトと非常に経験の浅いです、次は私がやったことです:C++でWindowsでCOM(Component Object Model)を登録するには?

  • 、私はIUnknowを拡張するクラスを作成し、QueryInterfaceを、にAddRefとReleaseを実装しています。
  • IShellIconOverlayIdentifierを拡張し、内部に3つのメソッドを実装します。
  • __declspec(dllexport)でクラスをエクスポート
  • DLLはMSVC2015の64ビットでコンパイルされます。 (Windows7 64bitで作業しています)。

は今難しい部分が来る:

  • https://msdn.microsoft.com/en-us/library/windows/desktop/hh127455(v=vs.85).aspxオーバーレイハンドラを登録するが、どのようにCOMオブジェクトを登録しない方法について説明します/リンクDLLを使用するためのウィンドウを作成する方法

    。私はいくつか試しましたが、ウィンドウが再起動しても何も起こりません。

登録方法とCOM dllの登録方法を確認するにはどうすればいいですか?

コンパイラ/アーキテクチャのようなコンパイル制限はありますか?

EDITED簡体:

私がCOM実装の非常に不完全なビジョンを持っていたし、COMオブジェクトを登録するために、2つの方向が可能であることを思え:

  • 登録手動でオブジェクトにレジスタ、それは悪夢です。
  • DllRegisterServerとDllUnregisterServerの実装:これも悪夢です。

は、問題を単純化するために、私は、これらの2つの機能を持つまでに他のすべてを削除:

STDAPI DllRegisterServer(void) 
{ 
    return NOERROR; 
} 

STDAPI DllUnregisterServer(void) 
{ 
    return NOERROR; 
} 

は残念ながら、これは、DLLにエクスポートされていない(ノー__declspec(のdllexportとして)指定されているが) 。この宣言を追加しようとすると、コンパイラは不満を表明し、DLLは生成されません。

ソリューションSTEP 1:

Olectl.hは非常に非常に悪いですし、エクスポートするのDllRegisterServerを避けます。

+1

ここをクリックしてください。 http://stackoverflow.com/a/5665927/3747990; COM dllが正しく構築されていれば 'regsvr32'を使ってオブジェクトを登録することができます。 – Niall

+0

@Niall: "DllRegisterServerが見つかりません"とは、 "指定されたDLL名は.dllまたは.ocxファイルではありません。たとえば、regsvr32 wjview.exeと入力すると、このエラーメッセージが表示されます。私はMSVC2015を仮定しています。64ビットdllはサポートされていません。 –

+2

いいえ、それらはすべてサポートされています。 DLLから 'DllRegisterServer'という名前の関数をエクスポートしますか?エラーが発生した場合、少なくとも適切ではありません。 VS2015でウィザードを使用して "ATL COMオブジェクト"プロジェクトを生成するのが最も簡単です。すべてのボイラープレートコードを配置します。次に、「COMオブジェクト」をプロジェクトに追加します(メニューまたはプロジェクトを右クリックしてそこから追加します)。 – Niall

答えて

0

(ウィザードなし)手動COMオブジェクトを作成するために、以下のステップが必要とされる:

  • に延びる、ターゲットクラスを実装IClassFactory
  • を拡張ファクトリを実装DllGetClassObject & DllCanUnloadNow
  • を実装IUknown
  • を登録するレジストリ内の
  • [オプション] DllRegisterServe r & DllUnregisterServerを実装して、レジストリを簡単にします。

を実装いるDllGetClassObject &のDllCanUnloadNow

それらのみDLL関数に輸出されている:

STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID * ppObject) 
STDAPI DllCanUnloadNow(void) 

いるDllGetClassObject、提供rclsidTargetClassCLSIDriidが `FactoryCLSIDである場合、それFactoryオブジェクトを作成して返します。

DLLが使用されている場合(S_OK)、ユーザー/クライアントがDLL(S_FALSE)をアンロードする可能性がある場合は、DllCanUnloadNowが返します。

問題は、この定義ではVSを「必須」にするMicrosoft monopol指示におそらく__declspec(dllexport)が追加されないことです。

#pragma comment(linker, "/export:DllGetClassObject,PRIVATE") 
#pragma comment(linker, "/export:DllCanUnloadNow,PRIVATE") 
//TODO: make this cross-compiler compatible? 
直前に追加し、それらをエクスポートするには工場

を実装

AddRefReleaseを実装します:彼らは、クライアント/ユーザーは、現在このファクトリオブジェクトを使用しているどのように多くの維持します。 AddRefは1だけインクリメントし、Releaseは1だけインクリメントします。数字が0になるとすぐにReleaseが自動的に削除されます。

実装QueryInterfaceriidがFactoryCLSIDの場合に戻ってきます。

RIIDの試合が対象のクラスを再度

を実装

をTargetClassCLSID場合、我々はのAddRef、リリースとQueryInterfaceをを実装する必要がありますが、最終的にクラスのため、この対象物体のインスタンスを返すCreateInstanceを実装時間。

私の場合、このTargetクラスはIShellIconOverlayIdentifierを拡張します。

、DLLを生成した後、OSのレジストリ

にいくつかのレジストリをCOMオブジェクトを登録するには、設定する必要があります。それらのいくつかはリンクされているので、自動的に別のリンクを追加することがあります。追加するコンテンツ

HKEY_CLASS_ROOT::CLSID::<Add Here> 
HKEY_CLASS_ROOT::Wow6432Node::CLSID::<Add Here> 
HKEY_LOCAL_MACHINE::SOFTWARE::Classes::CLSID::<Add Here> 
HKEY_LOCAL_MACHINE::SOFTWARE::Classes::Wow6432Node::CLSID::<Add Here> 
HKEY_LOCAL_MACHINE::SOFTWARE::Wow6432Node::Classes::CLSID::<Add Here> 

です:

  • は、キーを作成します。名前= {TargetClassCLSID}、値= <Any app name>
  • は、サブキーを作成します。名前= InProcServer32、値を= <link to your dll>
  • の作成InProcServer32のサブストリング:name = ThreadingModel、値= Apartment

// TODO:おそらく、その意味を理解するために、他の選択肢があります。 <TargetClassCLSID>

新しいエントリがある=名前= <Any app name>、値:オーバーレイエントリはキーがある

HKEY_LOCAL_MACHINE::SOFTWARE::Microsoft::Windows::CurrentVersion::Explorer::ShellIconOverlayIdentifier::<Overlay here> 
HKEY_LOCAL_MACHINE::SOFTWARE::Microsoft::Windows::CurrentVersion::ShellExtensions::Aproved::<new entry here> 

:私の場合は

は、私はIconHandlerのためのいくつかのより多くのレジスタを登録しなければなりませんでした文字列値その名= <TargetClassCLSID>と値= Any app name

これらの値は、であることも必要です

HKEY_LOCAL_MACHINE::SOFTWARE::Wow6432Node::Microsoft::Windows.... 
関連する問題