Я пишу BHO, который выставляет ряд методов через COM. Большинство из них работают нормально, но два последних добавленных показывают странное поведение.
При вызове из JavaScript на странице вновь добавленные методы «возвращают» Undefined, в отличие от исключения, что метод или свойство не существует, поэтому объект, по крайней мере, знает, что методы находятся на нем, но никогда не выполняет их.
bho.h
class ATL_NO_VTABLE CBho :
public IObjectWithSite,
public IDispatchImpl<IBho, &IID_IBho>,
public IOleCommandTarget
{
public:
STDMETHOD(DeletePreference)(BSTR prefName);
};
bho.cpp:
STDMETHODIMP CBho::DeletePreference(BSTR prefName) {
//some code that interacts with localStorage
return S_OK;
}
И мой IDL:
[
object,
uuid(/*uuid/*),
dual,
nonextensible,
helpstring("IBho Interface"),
pointer_default(unique)
]
interface IBho : IDispatch{
...
[id(5), helpstring("method DeletePreference")] HRESULT DeletePreference([in] BSTR prefName);
};
[
uuid(/*uuid*/),
version(1.0),
helpstring("Bho1.0 Type Library")
]
library MyBhoLib
{
importlib("stdole2.tlb");
[
uuid(36BA1FA3-144A-4A1A-BE62-8301C4E4ADEF),
helpstring("Bho Class")
]
coclass BhoSite
{
[default] interface IBho;
};
}
Я заметил, что подобное поведение может быть создано путем изменения идентификаторов, я попытался «сбросить» библиотеку типов, определив новый интерфейс для реализации, изменив направляющие, увеличив версию библиотеки типов и т. Д. Все это привело к в методах, не вызываемых вообще.
Насколько я могу судить по исследованиям, которые я провел здесь и на MSDN, я на правильном пути. Как мне успешно добавить новые методы в мой COM-класс, чтобы их можно было вызывать для моего объекта BHO? BHO еще не был выпущен, поэтому интерфейс еще не был установлен в камне.
Я смог решить эту проблему, но не так, как я полностью понимаю. Кажется, интерфейс IBho поддерживает только 4 метода, предоставляемых IDL. После этого методы становятся видимыми для вызывающей стороны, но не будут выполняться. Я понятия не имею, почему это так, и до сих пор не нашел какой-либо документации, касающейся этого.
Чтобы решить эту проблему, я просто создал новый класс COM, предназначенный для управления хранилищем, и открыл его для COM через IDL и процесс регистрации. Это позволило мне расширить API, связанные с хранилищем, чтобы включить DeletePreference
метод, а также добавить другие запрошенные функциональные возможности в BHO. В любом случае, это, вероятно, лучшая практика кодирования. Вот как это выглядит сейчас:
Preferences.h
class CPreferences :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CPreferences, &CLSID_Preferences>,
public IDispatchImpl<IPreferences , &IID_IPreferences >
{
...
/implementation
};
IDL:
[
object,
uuid(/*uuid/*),
dual,
nonextensible,
helpstring("IBho Interface"),
pointer_default(unique)
]
interface IBho : IDispatch{
...
[id(4), helpstring("method DoSomeThing")] HRESULT DoSomeThing([in] BSTR prefName);
};
[
object,
uuid(/*uuid/*),
dual,
nonextensible,
helpstring("IPreferences Interface"),
pointer_default(unique)
]
interface IPreferences : IDispatch{
...
[id(3), helpstring("method DeletePreference")] HRESULT DeletePreference([in] BSTR prefName);
};
[
uuid(/*uuid*/),
version(1.0),
helpstring("Bho1.0 Type Library")
]
library MyBhoLib
{
importlib("stdole2.tlb");
[
uuid(36BA1FA3-144A-4A1A-BE62-8301C4E4ADEF),
helpstring("Bho Class")
]
coclass BhoSite
{
[default] interface IBho;
};
[
uuid(uuid),
helpstring("Preferences Class")
]
coclass Preferences
{
[default] interface IPreferences;
};
}
Других решений пока нет …