通过代码在typelib文件中查找依赖类型库
寻找一种方法来查找类型库的依赖类型库。例如,在IDL中声明依赖库时,常见依赖项为stdole2.tlb,声明为:通过代码在typelib文件中查找依赖类型库
importlib(“stdole2.tlb”);
我可以使用OleView.exe来查看这些依赖项,但我想弄清楚如何在代码中执行它。在ITypeLib或ITypeLib2接口中似乎没有可以获取这些依赖关系的成员。我搜索了OLE自动化参考,并没有找到一种方法来获取接口。
它们以某种方式在类型库的二进制资源格式?
任何人都可以指向正确的方向吗?
下面是一个类型库的GetDependencies
函数的完整实现。
这将返回一个unordered_set
的ITypeLibPtr
智能指针。请注意散列函数,它使这些智能指针能够在unordered_set
和其他散列容器中使用。
这只返回第一级依赖关系。如果这些类型的库具有附加依赖关系,则可以使用此方法以某种递归方式获取一组完整的依赖关系(第一级和更高级别)。
循环引用(例如IInterfaceA
具有一个返回指针IInterfaceB
一个属性,并IInterfaceB
具有返回IInterfaceA
指针的性质)通过存储被访问ITypeInfo
S的unordered_set
同时通过类型库爬行支撑。
此代码旨在抛出_com_error
例外(除了使用unordered_set
时可能发生的任何STL例外)。适当处理这些。如果您不想处理_com_error
例外情况,请使用您自己的HRESULT
值的错误处理逻辑替换_com_util::CheckError
调用。
#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);
}
'ITypeLib'和'ITypeInfo'非常详细。如果我忽视或错误实施了任何内容,请让我知道,以便我可以更正此代码。 –
据我所知,从'ITypeLib'很容易获得依赖关系的主列表。相反,我们应该枚举库中的所有类型,降序到接口方法及其参数等,并在每个类上调用“ITypeInfo :: GetContainingTypeLib”。这可能会给你一个不同于你开始的库(由ITypeLib :: GetLibAttr确定)。 –
乔,我的回答对你有帮助吗? –