【问题标题】:Find dependent type libraries in typelib file through code通过代码在typelib文件中查找依赖类型库
【发布时间】:2017-07-12 16:22:52
【问题描述】:

寻找一种方法来查找类型库的依赖类型库。例如,在 IDL 中声明依赖库时,常见的依赖是 stdole2.tlb,声明为:

importlib("stdole2.tlb");

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

它们是否以某种方式采用类型库的二进制资源格式?

谁能指出我正确的方向?

【问题讨论】:

  • 据我所知,ITypeLib 没有容易获得的依赖项主列表。相反,应该枚举库中的所有类型,下降到接口方法及其参数等,并在每个上调用ITypeInfo::GetContainingTypeLib。这可能会为您提供与您开始时使用的库不同的库(由 ITypeLib::GetLibAttr 确定)。
  • 乔,我的回答对你有帮助吗?

标签: com


【解决方案1】:

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

这将返回unordered_setITypeLibPtr 智能指针。请注意散列函数,它使这些智能指针能够在unordered_set 和其他散列容器中使用。

这仅返回第一级依赖项。如果这些类型库有额外的依赖,你可以通过某种递归的方式使用这个方法来获得一组完整的依赖(一级及以上)。

通过存储访问过的ITypeInfounordered_set 来支持循环引用(例如IInterfaceA 有一个返回IInterfaceB 指针的属性,而IInterfaceB 有一个返回IInterfaceA 指针的属性) s 同时在类型库中爬行。

此代码旨在引发_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);
}

【讨论】:

  • ITypeLibITypeInfo 非常详细。如果我忽略或错误实现了任何内容,请告诉我,以便我更正此代码。
  • 碰巧遇到了同样的问题,并注意到您从未被标记为答案 - 以为您想知道您的解决方案确实可以很好地满足我的需求。非常感谢!
  • 由于答案适用于另一个,我会给予信任。我最终做了其他事情——在过去找到了一些其他方式……一些无证结构有效。
猜你喜欢
  • 2010-11-25
  • 1970-01-01
  • 2019-01-16
  • 2012-03-11
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 2010-12-08
相关资源
最近更新 更多