从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

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

时间: 2024-08-02 03:01:45

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

第一个lucene程序,把一个信息写入到索引库中、根据关键词把对象从索引库中提取出来、lucene读写过程分析

新建一个Java Project :LunceneTest 准备lucene的jar包,要加入的jar包至少有: 1)lucene-core-3.1.0.jar     (核心包) 2) lucene-analyzers-3.1.0.jar    (分词器) 3) lucene-highlighter-3.1.0.jar    (高亮器) 4) lucene-memory-3.1.0.jar       (高亮器) 新建实体类:Article, 属性:id,title,content; gett

Golang调用windows下的dll动态库中的函数

Golang调用windows下的dll动态库中的函数 https://blog.csdn.net/xuduorui/article/details/78943331 原文地址:https://www.cnblogs.com/yuanjiangw/p/12196004.html

在共享DLL中使用MFC 和在静态库中使用MFC的区别

使用VS2008,在项目属性中有一项MFC的使用,有三种设置: 1.使用标准Windows库 2.在共享DLL中使用MFC 3.在静态库中使用MFC 第一种顾名思义. 第二种指的是打包时一些MFC的DLL的内容没有被包含在EXE文件中,所以EXE文件较小,但是运行时要求系统中要有相关的DLL文件. 第三种是将DLL中的相关代码写进EXE文件中,文件较大,但是可以在没有相关DLL的机器上运行. 同时,如果程序本来是第二种方式,发给同事,在同事机器上运行时,可能会出现错误: “无法启动程序……,由于

[转]如何使用MFC和类型库创建自动化项目

本文转自:http://www.cnblogs.com/zhoug2020/archive/2012/04/01/2429064.html 摘要 本文详细介绍了如何自动化像Microsoft Office这样支持COM的应用程序. 更多信息 下面部分介绍了如何创建MFC项目.采用Microsoft Excel举例,你可以将前8个步骤用于任何项目,修改9-15步用于不同的应用程序. 创建自动化项目 1. 在Microsoft Developer Studio中,创建"MFC AppWizard(e

EXCEL类型库的添加

1. 创建新的C++工程 创建基于对话框的MFC程序 2. 添加库.添加Excel类库 在工程名上右键,选择“添加”—“类”(或者点击菜单栏的“项目”->“添加类”),选择“TypeLib中的MFC类”(MFC Class From TypeLib) 类来源选“注册表”,在可用的类型库中选择“Microsoft Excel 11.0 Object Library<1.5>”在接口列表框中选择需要的类,在此,我们选择_Application,_Workbook,Worksheet,Rang

[转]C# 互操作性入门系列(四):在C# 中调用COM组件

传送门 C#互操作系列文章: C#互操作性入门系列(一):C#中互操作性介绍 C#互操作性入门系列(二):使用平台调用调用Win32 函数 C# 互操作性入门系列(三):平台调用中的数据封送处理 C#互操作性入门系列(四):在C# 中调用COM组件 本专题概要: 引言 如何在C#中调用COM组件--访问Office 互操作对象 在C# 中调用COM组件的实现原理剖析 错误处理 小结 一.引言 COM(Component Object Modele,组件对象模型)是微软以前推崇的一个开发技术,所以

解决 “MoveFile”: 类型库“XXX.dll”中的标识符已经是宏;使用“rename”限定符 类型库符号与系统符号冲突问题

今天在VS工程当中引入一个组件,编译的时候出现警告, “MoveFile”: 类型库“XXX.dll”中的标识符已经是宏:使用“rename”限定符.虽然只是一个警告,但看着实在不爽,更重要的是,警告在某些情况下,可能正是bug的来源,并且这类bug往往非常难以定位.废话不多话,下面来解决问题. 看编译器给出的提示,是告诉我们,类型库当中的符号和系统符号有重名,同时也给出了解决方法,就是使用rename.怎么个rename法呢?其实很简单,我们在导入类型类的时候,直接#import语句后面,通过

Visual Studio中根据系统区分引用64位、32位DLL动态库文件的配置方法

原来使用Win7的32位系统,进行C#工程的开发,后来重装系统,换成了win7的64位系统 调试原来的工程,由于在其中引用了"SQLite"的32位的dll,导致在64为位下程序无法运行(但是编译可以通过) 后来通过修改工程文件(.csproj),在其中设置引用的条件,解决了问题 打开引用了SQLite的工程(例如叫做info)的工程文件(info.csproj),找到对SQLite引用的语句,类似如下的代码 代码如下: <Reference Include="Syst

SWF运行时判断两个DisplayObject是否同个类型,属于flash professional库中的同一个元件

一般我们判断两个实例对象是否同样的类型,可以用typeof得到对象类型,然后用==号比较. typeof适用于原生类型. 而对于自定义类型,虽然typeof得到的都是Object,但还有更强的招数:getQualifiedClassName 利用这个原生函数可以获取到两个实例的真实类型. 然而,对于Flash professional制作出来的swf,运行时要知道其中两个MovieClip是否来自库里边的同一个元件,上述方法都无能为力了. 本文就是探讨这个问题. 1.首先,想到的是,如果两个实例