从tlb,ocx,dll类型库中提取com组件的CLSID

最近在做项目的时候遇到了这个问题。

项目需要动态根据添加com组件,获取组件的某个接口函数。

一般情况下,我们创建com组件的方法是根据它的CLSID号,获得相应的interface,然后通过返回的指针调用相应的接口函数。如下:

CoInitialize( NULL );
IpTest* pMask = NULL;
HRESULT hr = CoCreateInstance( CLSID_TEST, NULL, CLSCTX_INPROC, IID_ITEST, (LPVOID*)&IpTest );
if( !SUCCEEDED(hr) )
{
    AfxMessageBox( _T("com组件创建失败,请检查其是否安装并注册") );
    return 0;
}
IpTest->SomeFunc();//调用相应的接口函数
IpTest->Release();
CoUninitialize();

现在项目要根据输入tlb文件获得对应com组件的CLSID,然后调用CoCreateInstance()函数,传给它刚刚读取的CLSID。

百度,google了半天才找到了解决方案,特此记录下来。

稍微简单封装成函数.

#include <windows.h>
#include <comdef.h>
ITypeLib *pTypeLib = NULL;
ITypeInfo *pTypeInfo = NULL;
TYPEATTR *pTypeAttr = NULL;

void Cleanup();
GUID getCLSIDFromFile(const CString &strFileName)throw(std::runtime_error);

//strFileName--输入tlb,ocx文件路径
GUID getCLSIDFromFile(const CString &strFileName)throw(std::runtime_error)
{
    _bstr_t str;
    HRESULT hr;
    TCHAR* pwszProgID = NULL;
    
    hr = LoadTypeLib(strFileName,&pTypeLib);//加载类型库信息
    if ( FAILED(hr)) 
    {
        Cleanup(); 
        return GUID();
    }
    UINT iCount = pTypeLib->GetTypeInfoCount(); //获取类型数量
    for (int i=0; i < iCount ; i++) 
    {
        if (FAILED(hr = (pTypeLib->GetTypeInfo(i, &pTypeInfo))))//获取类型说明信息
        {
            Cleanup();
            throw runtime_error("输入文件不包含相关com组件接口");
            return GUID();
        }
        if (FAILED(hr = (pTypeInfo->GetTypeAttr(&pTypeAttr))))//获取类型属性
        {
            Cleanup();
            throw runtime_error("输入文件不包含相关com组件接口");
            return GUID();
        }
        
        if (TKIND_COCLASS == pTypeAttr->typekind)//判断是否为组件接口
            return pTypeAttr->guid;
        pTypeInfo->ReleaseTypeAttr(pTypeAttr);
        pTypeInfo->Release();

    }

    pTypeLib->Release();
    pTypeLib = NULL;
    throw runtime_error("输入文件不包含相关com组件接口");
    return GUID();
}

void Cleanup()
{
    if (pTypeAttr)
        pTypeInfo->ReleaseTypeAttr(pTypeAttr);

    if (pTypeInfo)
        pTypeInfo->Release();
    pTypeAttr = NULL;
    pTypeInfo = NULL;
}

使用的时候直接传入tlb,ocx,dll文件路径给getCLSIDFromFile()函数,函数返回值即对应com组件的CLSID;

获得了组件的CLSID,就可以按照常规方法访问组件对应的接口了。

当然如果知道了对应组件的ProgID,可以用

HRESULT CLSIDFromProgID(
  LPCOLESTR lpszProgID,  //Pointer to the ProgID
  LPCLSID pclsid         //Pointer to the CLSID
);
传入对应ProgID字符串,返回相应CLSID;

参考链接:http://support.microsoft.com/kb/286340/zh-cn

原文地址:https://www.cnblogs.com/sunbing/p/3880812.html