Windows 7SP1x64でVisualStudio2010を使用しています。
32ビットアプリとしてコンパイルされたwin32アプリケーションと通信するカスタムデスクバンドを作成する必要があります。
私はこのCodeProjectの記事を出発点として使用しました:http://www.codeproject.com/Articles/39189/Shell-Extensibility-Explorer-Desk-Band-Tray-Notifi
デスクバンドdll(x64用にコンパイル)は正常に動作します-タスクバーなどに表示されます。
「管理者として実行」であったcmd.exeからのzippy32を使用して登録されます。rgsファイルは次のとおりです。
HKCR
{
NoRemove CLSID
{
ForceRemove {8D330AEA-90D1-4632-804B-4710F2358A18} = s 'my deskbar'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
}
}
}
このstackoverflowの回答に基づく:InprocCOMサーバーに新しいインターフェイスを追加して実装する方法
IDLファイルにインターフェイスを作成しました。
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(35662650-07D0-4F31-B5F0-3C21FCA4BDA2),
version(1.0),
oleautomation
//dual,
//pointer_default(unique)
]
interface IGEDeskBand : IDispatch
{
HRESULT BadgeSet([in] long arg);
HRESULT BadgeClear(void);
HRESULT BadgeBlink(void);
};
[
uuid(33EB8C00-F66A-493C-8607-529060FAA378),
version(1.0),
helpstring("GamEffective DeskBand Library")
]
library GEDeskBandLib
{
importlib("stdole32.tlb");
[
uuid(8D330AEA-90D1-4632-804B-4710F2358A18),
helpstring("GEDeskBand Class")
]
coclass GEDeskBand
{
[default] interface IGEDeskBand;
};
cpp_quote("const size_t MAX_GUID_STRING_LEN = 39;")
};
、visual studioは、生成されたヘッダーを生成するmidlを使用してコンパイルし、生成されたコードを含めます#include "GEDeskBand_i.h"
。
public IDispatchImpl<IGEDeskBand, &__uuidof(IGEDeskBand), &LIBID_GEDeskBandLib, /* wMajor = */ 1, /* wMinor = */ 0>
、COM_INTERFACE_ENTRY
COM MAPにwithインターフェイスを追加し、メソッドを追加しました。
STDMETHOD(BadgeSet)(/* [in] */ long arg);
STDMETHOD(BadgeClear)();
STDMETHOD(BadgeBlink)();
(まあ、私はビジュアルスタジオウィザードを使用しました:クラスビュー->クラスを右クリックし、追加->インターフェイスを実装します)、現在、メソッドの実装はただですreturn E_NOTIMPL;
、そしてそれが問題ではないことを願っています。これが、サーバー上のコードで行ったすべてのことです。インターフェイスに関して、別のプロセスからこのオブジェクトと通信しようとしています。
#define _ATL_DEBUG_QI
この記事(http://msdn.microsoft.com/en-us/library/ezs95xhx%28v=vs.80%29.aspx )を使用すると、explorer.exeに接続するとVisual Studioの[出力]ウィンドウに表示されます(デスクバーdllが読み込まれ、COMオブジェクトが存在する場所)QueryInterfaceは適切なインターフェイスでクエリされ、「失敗」とは表示されません。
これは、デスクバーがロードされたときです。
CComClassFactory - IClassFactory
CGEDeskBand - IDeskBand
CGEDeskBand - IPersistStreamInit
CGEDeskBand - IDeskBand2
CGEDeskBand - IDeskBand
CGEDeskBand - {EA5F2D61-E008-11CF-99CB-00C04FD64497} - failed
CGEDeskBand - IObjectWithSite
CGEDeskBand - {7FE80CC8-C247-11D0-B93A-00A0C90312E1} - failed
CGEDeskBand - IOleCommandTarget - failed
CGEDeskBand - IDeskBandInfo - failed
CGEDeskBand - IDeskBand
CGEDeskBand - IOleWindow
CGEDeskBand - IPersist
CGEDeskBand - IDeskBand2
これは、問題を示すテスターを実行するときです。
CGEDeskBand - IDeskBand
CGEDeskBand - {00000003-0000-0000-C000-000000000046} - failed
CGEDeskBand - {00000003-0000-0000-C000-000000000046} - failed
CGEDeskBand - {0000001B-0000-0000-C000-000000000046} - failed
CGEDeskBand - IUnknown
CGEDeskBand - {00000018-0000-0000-C000-000000000046} - failed
CGEDeskBand - {00000019-0000-0000-C000-000000000046} - failed
CGEDeskBand - {4C1E39E1-E3E3-4296-AA86-EC938D896E92} - failed
CGEDeskBand - IDeskBand
CGEDeskBand - IDeskBand
CGEDeskBand - IPersist
CGEDeskBand - IPersist
CGEDeskBand - {1C733A30-2A1C-11CE-ADE5-00AA0044773D} - failed
CGEDeskBand - {35662650-07D0-4F31-B5F0-3C21FCA4BDA2}
最後のものは私のIIDであり、失敗したとは言いません。
これは、問題を示すテストコードです。
#include <Shobjidl.h>
#include "GEDeskBand_i.h"
#include "GEDeskBandGuids.h"
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr;
CComPtr<IUnknown> spBandService;
CComPtr<IBandSite> spBandSite;
CoInitialize(NULL);
hr = spBandService.CoCreateInstance(CLSID_TrayBandSiteService);
if (SUCCEEDED(hr)) {
hr = spBandService->QueryInterface(&spBandSite);
if (SUCCEEDED(hr)) {
DWORD dwBandId = 0;
UINT num_bands = spBandSite->EnumBands((UINT)-1, &dwBandId);
for (UINT uBand = 0; uBand < num_bands; uBand++) {
if (SUCCEEDED(spBandSite->EnumBands(uBand, &dwBandId))) {
IDeskBand *band;
if (SUCCEEDED(spBandSite->GetBandObject(dwBandId, IID_IDeskBand, (void**)&band))) {
IPersist* pPersist = NULL;
if (SUCCEEDED(band->QueryInterface(IID_IPersist, (void**)&pPersist))) {
CLSID clsid = CLSID_NULL;
if (SUCCEEDED(pPersist->GetClassID(&clsid))) {
if (clsid == CLSID_GEDeskBand) {
// reaches here fine
IGEDeskBand *pGEDeskBand = NULL;
hr = band->QueryInterface(IID_IGEDeskBand, (void**)&pGEDeskBand);
if (SUCCEEDED(hr)) {
// never reaches here, always get E_NOINTERFACE
pGEDeskBand->BadgeSet(1);
}
break;
}
}
}
}
}
}
spBandSite.Release();
}
spBandService.Release();
}
CoUninitialize();
return 0;
}
問題は、DeskBandオブジェクトのIDeskBandまたはIPersistが表示されても(CLSIDは一致しますが、それが私のオブジェクトであり、そのインターフェイスを実装していることを知っています)、インターフェイスIID_IGEDeskBandを使用するQueryInterfaceが成功しないことです。
QueryInterfaceはIIDを検出しますが、クライアントに到達しません。マーシャリングのせいで、私は思います。
テスターをx64としてコンパイルしようとしましたが、うまくいきませんでした。
レイモンドチェンはこれについて書いています:http://blogs.msdn.com/b/oldnewthing/archive/2004/12/13/281910.aspx
そのブログ投稿から私が理解したのは、マーシャリングに対処する必要があるということだけです。自動であるはずだと思いましたか?
これを修正する1つの方法は、midlで生成されたプロキシスタブを構築することです。インターフェイスが見つかった場合でもCoCreateInstanceがE_NOINTERFACEを返します。
http://msdn.microsoft.com/en-us/library/aa366768%28VSからmidlを使用して32ビットプロキシコードとレシピを作成することにより、32ビットのプロキシスタブdllを構築して登録しました。 85%29.aspx
これも機能しませんでした。テスターを実行しているときに、テスタープロセスにプロキシスタブDLLがロードされていません。するべきか?正しく登録されているようです。
COMや一般的なwin32についてもよくわかりませんが、何時間もグーグルを続けていて、何が間違っているのかわかりません。