寻找一种方法来查找类型库的依赖类型库。例如,在IDL中声明依赖库时,常见的依赖项是stdole2.tlb并声明为:
导入库(" STDOLE2.TLB&#34);
我可以使用OleView.exe来查看这些依赖项,但我试图找出如何在代码中执行此操作。在ITypeLib或ITypeLib2接口中似乎没有可以获取这些依赖关系的任何成员。我已经搜索了OLE自动化参考,但还没有找到一种方法来获取接口。
它们是否以某种方式处于类型库的二进制资源格式?
任何可以指出我正确方向的人?
答案 0 :(得分:3)
以下是类型库的GetDependencies
函数的完整实现。
这将返回unordered_set
个ITypeLibPtr
智能指针。请注意散列函数,它允许在unordered_set
和其他散列容器中使用这些智能指针。
这只返回第一级依赖项。如果这些类型库具有其他依赖项,则可以以某种递归方式使用此方法来获取一组完整的依赖项(第一级和更高级别)。
循环引用(例如IInterfaceA
具有返回IInterfaceB
指针的属性,而IInterfaceB
具有返回IInterfaceA
指针的属性)通过存储{在浏览类型库时访问ITypeInfo
的{3}}。
此代码旨在抛出unordered_set
个异常(除了使用_com_error
时可能发生的任何STL异常)。适当处理这些。如果您不想处理unordered_set
例外情况,请使用您自己的_com_util::CheckError
值的错误处理逻辑替换HRESULT
次调用。
#include <windows.h>
#include <comdef.h>
#include <unordered_set>
// gets dependencies of a type library
std::unordered_set<ITypeLibPtr> GetDependencies(ITypeLib* pTypeLib);
// gathers dependencies of a type library
void GetDependenciesHelper(ITypeLib* pTypeLib, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
// gathers dependencies of a type
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
// gathers dependencies of a reference
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, HREFTYPE hRefType, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
// gathers dependencies of a reference
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, TYPEDESC& referencedTypeDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
// gathers dependencies of a function declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, FUNCDESC& functionDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
// gathers dependencies of a variable declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, VARDESC& variableDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
// gathers dependencies of an array declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ARRAYDESC& arrayDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
// gathers dependencies of an array element declaration
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ELEMDESC& elementDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput);
namespace std
{
// provides a function for hashing ITypeLibPtr instances by their raw address
template<> struct hash<ITypeLibPtr>
{
size_t operator()(ITypeLibPtr const& pTypeLib) const { return pTypeLib; }
};
// provides a function for hashing ITypeInfo instances by their raw address
template<> struct hash<ITypeInfoPtr>
{
size_t operator()(ITypeInfoPtr const& pTypeInfo) const { return pTypeInfo; }
};
}
std::unordered_set<ITypeLibPtr> GetDependencies(ITypeLib* pTypeLib)
{
// get dependencies
std::unordered_set<ITypeLibPtr> output;
std::unordered_set<ITypeInfoPtr> history;
GetDependenciesHelper(pTypeLib, &history, &output);
return output;
}
void GetDependenciesHelper(ITypeLib* pTypeLib, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
// iterate over type infos
auto typeInfoCount = pTypeLib->GetTypeInfoCount();
for (UINT typeInfoIndex = 0; typeInfoIndex < typeInfoCount; ++typeInfoIndex)
{
// get type info
ITypeInfoPtr pTypeInfo;
_com_util::CheckError(pTypeLib->GetTypeInfo(typeInfoIndex, &pTypeInfo));
// get dependencies for type info
GetDependenciesHelper(pTypeLib, pTypeInfo, pHistory, pOutput);
}
}
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
// short-circuit if we've already processed this type info
if (!pHistory->insert(pTypeInfo).second)
return;
// get type attributes
TYPEATTR* typeAttributes;
_com_util::CheckError(pTypeInfo->GetTypeAttr(&typeAttributes));
try
{
// special handling for aliases
if (typeAttributes->typekind == TKIND_ALIAS)
{
// get dependencies of the alias
GetDependenciesHelper(pTypeLib, pTypeInfo, typeAttributes->tdescAlias, pHistory, pOutput);
}
else
{
// iterate over implemented types
auto implementedTypeCount = typeAttributes->cImplTypes;
for (WORD implementedTypeIndex = 0; implementedTypeIndex < implementedTypeCount; ++implementedTypeIndex)
{
// get type reference
HREFTYPE hRefType;
_com_util::CheckError(pTypeInfo->GetRefTypeOfImplType(implementedTypeIndex, &hRefType));
// get dependencies of the implementation
GetDependenciesHelper(pTypeLib, pTypeInfo, hRefType, pHistory, pOutput);
}
// iterate over functions
auto functionCount = typeAttributes->cFuncs;
for (WORD functionIndex = 0; functionIndex < functionCount; ++functionIndex)
{
// get function description
FUNCDESC* functionDescription;
_com_util::CheckError(pTypeInfo->GetFuncDesc(functionIndex, &functionDescription));
try
{
// get dependencies of the function declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, *functionDescription, pHistory, pOutput);
}
catch (...)
{
// release function description
pTypeInfo->ReleaseFuncDesc(functionDescription);
throw;
}
// release function description
pTypeInfo->ReleaseFuncDesc(functionDescription);
}
// iterate over variables
auto variableCount = typeAttributes->cVars;
for (WORD variableIndex = 0; variableIndex < variableCount; ++variableIndex)
{
// get variable description
VARDESC* variableDescription;
_com_util::CheckError(pTypeInfo->GetVarDesc(variableIndex, &variableDescription));
try
{
// get dependencies of the variable declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, *variableDescription, pHistory, pOutput);
}
catch (...)
{
// release variable description
pTypeInfo->ReleaseVarDesc(variableDescription);
throw;
}
// release variable description
pTypeInfo->ReleaseVarDesc(variableDescription);
}
}
}
catch (...)
{
// release type attributes
pTypeInfo->ReleaseTypeAttr(typeAttributes);
throw;
}
// release type attributes
pTypeInfo->ReleaseTypeAttr(typeAttributes);
}
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, HREFTYPE hRefType, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
// get referenced type info
ITypeInfoPtr referencedTypeInfo;
_com_util::CheckError(pTypeInfo->GetRefTypeInfo(hRefType, &referencedTypeInfo));
// get referenced type lib
ITypeLibPtr referencedTypeLibrary;
UINT referencedTypeInfoIndex;
_com_util::CheckError(referencedTypeInfo->GetContainingTypeLib(&referencedTypeLibrary, &referencedTypeInfoIndex));
// store dependency
if (referencedTypeLibrary != pTypeLib)
pOutput->insert(referencedTypeLibrary);
}
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, TYPEDESC& referencedTypeDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
switch (referencedTypeDescription.vt)
{
case VT_PTR:
{
// get dependencies of the pointer declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, *referencedTypeDescription.lptdesc, pHistory, pOutput);
break;
}
case VT_CARRAY:
{
// get dependencies of the array declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, *referencedTypeDescription.lpadesc, pHistory, pOutput);
break;
}
case VT_USERDEFINED:
{
// get dependencies of the UDT reference
GetDependenciesHelper(pTypeLib, pTypeInfo, referencedTypeDescription.hreftype, pHistory, pOutput);
break;
}
}
}
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, FUNCDESC& functionDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
// get dependencies of the function return value
GetDependenciesHelper(pTypeLib, pTypeInfo, functionDescription.elemdescFunc, pHistory, pOutput);
// iterate over parameters
auto parameterCount = functionDescription.cParams;
for (SHORT parameterIndex = 0; parameterIndex < parameterCount; ++parameterIndex)
{
// get parameter description
auto& parameterDescription = functionDescription.lprgelemdescParam[parameterIndex];
// get dependencies of the parameter declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, parameterDescription, pHistory, pOutput);
}
}
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, VARDESC& variableDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
// get dependencies of the variable declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, variableDescription.elemdescVar, pHistory, pOutput);
}
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ARRAYDESC& arrayDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
// get dependencies of the array declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, arrayDescription.tdescElem, pHistory, pOutput);
}
void GetDependenciesHelper(ITypeLib* pTypeLib, ITypeInfo* pTypeInfo, ELEMDESC& elementDescription, std::unordered_set<ITypeInfoPtr>* pHistory, std::unordered_set<ITypeLibPtr>* pOutput)
{
// get dependencies of the array element declaration
GetDependenciesHelper(pTypeLib, pTypeInfo, elementDescription.tdesc, pHistory, pOutput);
}