通过代码在typelib文件中查找依赖的类型库
Find dependent type libraries in typelib file through code
正在寻找一种方法来查找类型库的依赖类型库。比如在IDL中声明依赖库时,一个普通的依赖是stdole2.tlb,声明为:
导入库("stdole2.tlb");
我可以使用 OleView.exe 来查看这些依赖项,但我正在尝试找出如何在代码中执行此操作。 ITypeLib 或 ITypeLib2 接口中似乎没有任何成员可以获取这些依赖项。我搜索了 OLE 自动化参考,但没有找到获取接口的方法。
它们是否以某种方式采用类型库的二进制资源格式?
有人能给我指出正确的方向吗?
这是类型库的 GetDependencies
函数的完整实现。
这将 return 一个 unordered_set
of ITypeLibPtr
smart pointers. Note the hashing function, which enables these smart pointers to be used in unordered_set
和其他哈希容器。
这只是return一级依赖。如果那些类型库有额外的依赖关系,您可以以某种递归方式使用此方法来获得一组完整的依赖关系(第一级和更高级别)。
循环引用(例如,IInterfaceA
有一个 属性,return 是一个 IInterfaceB
指针,而 IInterfaceB
有一个 属性,它returns 一个 IInterfaceA
指针)通过在类型库中爬行时存储所访问 ITypeInfo
s 的 unordered_set
来支持。
此代码旨在抛出 _com_error
异常(除了使用 unordered_set
时可能发生的任何 STL 异常)。酌情处理这些。如果您不想处理 _com_error
异常,请将 _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);
}
正在寻找一种方法来查找类型库的依赖类型库。比如在IDL中声明依赖库时,一个普通的依赖是stdole2.tlb,声明为:
导入库("stdole2.tlb");
我可以使用 OleView.exe 来查看这些依赖项,但我正在尝试找出如何在代码中执行此操作。 ITypeLib 或 ITypeLib2 接口中似乎没有任何成员可以获取这些依赖项。我搜索了 OLE 自动化参考,但没有找到获取接口的方法。
它们是否以某种方式采用类型库的二进制资源格式?
有人能给我指出正确的方向吗?
这是类型库的 GetDependencies
函数的完整实现。
这将 return 一个 unordered_set
of ITypeLibPtr
smart pointers. Note the hashing function, which enables these smart pointers to be used in unordered_set
和其他哈希容器。
这只是return一级依赖。如果那些类型库有额外的依赖关系,您可以以某种递归方式使用此方法来获得一组完整的依赖关系(第一级和更高级别)。
循环引用(例如,IInterfaceA
有一个 属性,return 是一个 IInterfaceB
指针,而 IInterfaceB
有一个 属性,它returns 一个 IInterfaceA
指针)通过在类型库中爬行时存储所访问 ITypeInfo
s 的 unordered_set
来支持。
此代码旨在抛出 _com_error
异常(除了使用 unordered_set
时可能发生的任何 STL 异常)。酌情处理这些。如果您不想处理 _com_error
异常,请将 _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);
}