为什么ITypeInfo::Invoke返回0x80020003 (Member not found.) ?
Why does ITypeInfo::Invoke return 0x80020003 (Member not found.)?
我在Microsoft Visual c++中从shdocvb .dll实现DShellWindowsEvents的事件接收器时遇到了麻烦。
问题出现在我的IDispatch::Invoke的实现中。我通过将其调用委托给ITypeInfo::Invoke来实现它(正如微软在备注部分所建议的那样),但它总是失败,错误代码为0x80020003(未找到成员)。
有趣的是,虽然DShellWindowsEvents只有两个方法(WindowRegistered和windowwrevoked)和ITypeInfo::GetIDsOfNames成功地为两者工作,返回预期的DISPID。但是,它是如何给"成员未找到"的错误调用?
类型库的相关部分:
[
uuid(FE4106E0-399A-11D0-A48C-00A0C90A8F39),
helpstring("Event interface for IShellWindows")
]
dispinterface DShellWindowsEvents {
properties:
methods:
[id(0x000000c8), helpstring("A new window was registered.")]
void WindowRegistered([in] long lCookie);
[id(0x000000c9), helpstring("A new window was revoked.")]
void WindowRevoked([in] long lCookie);
};
[
uuid(9BA05972-F6A8-11CF-A442-00A0C90A8F39),
helpstring("ShellDispatch Load in Shell Context")
]
coclass ShellWindows {
[default] interface IShellWindows;
[default, source] dispinterface DShellWindowsEvents;
};
和实际代码
class CDShellWindowsEvents : public DShellWindowsEvents {
public:
// IUnknown implementation
virtual HRESULT __stdcall QueryInterface( REFIID riid, LPVOID *ppvObj )
{
if( ppvObj == NULL ) return E_INVALIDARG;
*ppvObj = NULL;
if( riid == IID_IUnknown || riid == IID_IDispatch || riid == DIID_DShellWindowsEvents )
{
*ppvObj = this;
AddRef( );
return NOERROR;
}
return E_NOINTERFACE;
}
virtual ULONG __stdcall AddRef( )
{
InterlockedIncrement( &m_cRef );
return m_cRef;
}
virtual ULONG __stdcall Release( )
{
ULONG ulRefCount = InterlockedDecrement( &m_cRef );
if( 0 == m_cRef )
delete this;
return ulRefCount;
}
// IDispatch implementation
virtual HRESULT __stdcall GetTypeInfoCount( unsigned int * pctinfo )
{
if( pctinfo == NULL ) return E_INVALIDARG;
*pctinfo = 1;
return NOERROR;
}
virtual HRESULT __stdcall GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo ** ppTInfo )
{
if( ppTInfo == NULL ) return E_INVALIDARG;
*ppTInfo = NULL;
if( iTInfo != 0 ) return DISP_E_BADINDEX;
*ppTInfo = m_pTypeInfo;
m_pTypeInfo->AddRef();
return NOERROR;
}
virtual HRESULT __stdcall GetIDsOfNames(REFIID riid, OLECHAR ** rgszNames, unsigned int cNames, LCID lcid, DISPID * rgDispId )
{
return m_pTypeInfo->GetIDsOfNames( rgszNames, cNames, rgDispId );
}
virtual HRESULT __stdcall Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, EXCEPINFO * pExcepInfo, unsigned int * puArgErr )
{
// We could switch on dispIdMember here but we want to do this the flexible way, so we can easily implement it later for dispinterfaces with dozens of methods.
return m_pTypeInfo->Invoke( this, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
/*HRESULT ret;
switch( dispIdMember )
{
case 0x000000c8: ret = WindowRegistered( pDispParams->rgvarg[0].intVal ); break;
case 0x000000c9: ret = WindowRevoked( pDispParams->rgvarg[0].intVal ); break;
default: ret = DISP_E_MEMBERNOTFOUND;
}
if( pVarResult ) pVarResult->lVal = ret;
return ret;*/
}
// DShellWindowsEvents implementation
virtual HRESULT __stdcall WindowRegistered( int nCookie )
{
LOG( "CDShellWindowsEvents::WindowRegistered( nCookie=0x%X ) ." , nCookie );
return NOERROR;
}
virtual HRESULT __stdcall WindowRevoked( int nCookie )
{
LOG( "CDShellWindowsEvents::WindowRevoked( nCookie=0x%X ) ." , nCookie );
return NOERROR;
}
// Constructor
CDShellWindowsEvents( )
{
m_cRef = 1;
LoadRegTypeLib( LIBID_SHDocVw, 1, 0, LANG_NEUTRAL, &m_pTypeLib );
m_pTypeLib->GetTypeInfoOfGuid( DIID_DShellWindowsEvents, &m_pTypeInfo );
}
// Destructor
~CDShellWindowsEvents( )
{
m_pTypeInfo->Release( );
m_pTypeLib->Release( );
}
private:
ULONG m_cRef;
ITypeLib *m_pTypeLib;
ITypeInfo *m_pTypeInfo;
};
这是类型库没有为disinterface指定double的问题吗?如果是,是否有办法强迫ITypeInfo::调用威胁它作为双重,因为我知道它的虚表是有序的。
dispinterface
是一个仅支持自动化的接口,而不是双接口。因此,DShellWindowsEvents
本身只有IDispatch
的7个方法,而不是它声明的额外的2个。这就像声明一个只有IDispatch
的接口与一个契约,如预定义的disid。
要以这种方式使用ITypeLib::Invoke
,您需要使用额外的方法将您自己的接口声明为[dual]
。
[ object, dual, oleautomation, uuid(...) ]
interface IMyDualShellWindowsEvents : IDispatch
{
[id(0x000000c8), helpstring("A new window was registered.")]
HRESULT WindowRegistered([in] long lCookie);
[id(0x000000c9), helpstring("A new window was revoked.")]
HRESULT WindowRevoked([in] long lCookie);
}
你需要提供或嵌入你自己的typelib,然后加载它。
DShellWindowsEvents
是一个disinterface,所以你的事件对象不会是你的内部接口的 QueryInterface
d,尽管你可以处理这种情况。因此,您不需要注册typelib,只需使用LoadLibraryEx
加载即可。
我认为你可以将hidden, restricted
添加到接口属性中,因此它不会显示并且不能在例如VBA中使用,即使手动添加对这样的私有 typelib的引用。
- OpenCV Android C++ imwrite not found
- 解决"ld: library not found for -ltensorflow_framework.2.3.0"
- 加载与引用 .NET DLL 位于同一文件夹中的引用的 .NET DLL 时"Not found"异常
- C++初学者:为什么我的编译器根据我的循环返回"name not found"?
- 使用提升 asio 时出现"resolve: Host not found (authoritative)"异常
- 为什么 VScode 在 .h 文件中显示"'iostream' file not found"?
- 为什么我在" 'X' identifier not found' "上收到错误
- WinDBG适用于从Visual Studio 2015保存的转储,但不适用于任务管理器。显示异常代码"not found"
- "Entry Point Not Found" Azure 中的错误 LightGBM R 包
- TBB_tbb_LIBRARY_DEBUG-NOT FOUND
- 在 Ubuntu 16.04 下运行协程示例会得到"'experimental/coroutine' file not found"
- 在 mongodb c++ 驱动程序中使用声明"not found"
- 如何修复"/bin/sh: bc: command not found"
- CMake,QT Quick & Visual Studio:"qrc:/main.qml:-1 File not found"
- opencv aruco.h not found windows 10 visual studio
- Qt Cmake 错误编译"GuiSupportQt not found"
- 如何在C++的程序中显示Windows的"DLL not found"错误?
- 如何修复张量流中的"Non-OK-status: Not found: Op type not registered 'NoOp' in binary running"
- 如何在Xcode中修复'sh: brew: command not found'?
- OpenCV: reconstruct() not found