通过代码在typelib文件中查找依赖类型库

问题描述:

寻找一种方法来查找类型库的依赖类型库。例如,在IDL中声明依赖库时,常见依赖项为stdole2.tlb,声明为:通过代码在typelib文件中查找依赖类型库

importlib(“stdole2.tlb”);

我可以使用OleView.exe来查看这些依赖项,但我想弄清楚如何在代码中执行它。在ITypeLib或ITypeLib2接口中似乎没有可以获取这些依赖关系的成员。我搜索了OLE自动化参考,并没有找到一种方法来获取接口。

它们以某种方式在类型库的二进制资源格式?

任何人都可以指向正确的方向吗?

+2

据我所知,从'ITypeLib'很容易获得依赖关系的主列表。相反,我们应该枚举库中的所有类型,降序到接口方法及其参数等,并在每个类上调用“ITypeInfo :: GetContainingTypeLib”。这可能会给你一个不同于你开始的库(由ITypeLib :: GetLibAttr确定)。 –

+0

乔,我的回答对你有帮助吗? –

下面是一个类型库的GetDependencies函数的完整实现。

这将返回一个unordered_setITypeLibPtr智能指针。请注意散列函数,它使这些智能指针能够在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); 
} 
+0

'ITypeLib'和'ITypeInfo'非常详细。如果我忽视或错误实施了任何内容,请让我知道,以便我可以更正此代码。 –