




已阅读5页,还剩79页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Email COM技术及组件开发 主要内容 COM的基本原理构件对象模型COM DCOM基于COM构件的开发 COM是微软提出的第一个构件模型 源于OLE ObjectLinkandEmbedding 动态链接和嵌入 OLE1采用DDE DynamicDataExchange 动态数据交换 在不同的程序之间进行通信DDE缺点 建立在Windows消息机制基础上 效率低 稳定性不好 使用不方便COM是为克服上述不足而出现的 COM技术的发展 COM定义了客户与构件之间互操作的标准 包括规约与实现两个部分规约部分定义了构件之间的通信机制 这些规约不依赖于任何特定的语言和操作系统实现部分就是COM库 为COM规约的具体实现提供了一些核心服务COM仅支持同一台计算机上 当然是Windows操作系统 的互操作 不支持分布式计算环境 COM技术的发展 将COM技术延伸到分布计算环境 产生了所谓的DCOM DistributedCOM 分布构件对象模型 用网络协议代替本地进程之间的通信针对分布环境提供了新特性 位置透明网络安全性跨平台调用等为了满足企业级应用的需求 推出了微软事务服务器 MTS MicrosoftTransactionServer 把应用系统的客户程序 应用构件和各种资源有机结合起来 为分布式企业应用提供了一种服务器端的构件运行和部署环境 COM技术的发展 为了使Windows真正成为企业应用平台 微软推出了分布式网络应用体系结构 WindowsDNA DistributedinterNetApplicationArchitecture DNA是一个完整的 多层的企业应用体系结构 包含工具 数据库 操作系统 编程模型和应用服务等随着Windows2000的发布 微软进一步把COM DCOM MTS统一起来 形成了真正适合于企业级应用的构件技术 COM 可以认为 COM DCOM MTS COM COM 是一种中间件技术规约 提供操作系统级的分布式 服务 COM技术的发展 WindowDNA 是一个服务器端的开发平台 包括WindowsNT 2000 2003提供运行环境和支持COM DCOMMSMQ消息队列产品 支持构件间异步通信MTS管理构件的应用服务MicrosoftWolfpack支持集群服务器的软件MicrosoftSQLServerMicrosoftIISWeb服务器MicrosoftManagementConsole部署和管理工具 WindowDNA COM 基本结构 COM 目录负载平衡驻留内存数据库对象池新的事件模型构件管理和部署JIT激活 COM MTS事务支持资源分发管理安全模型易于管理 远程支持DCOM分布式构件服务 COM基于接口的编程模型基本的构件服务 COM ComponentObjectModel 组件对象模型 是一种以组件为发布单元的对象模型 这种模型使得各个软件组件可以用一种统一的方式进行交互COM是一种协议 它建立了一个软件模块同另一个软件模块之间的连接 提供了组件之间进行交互的规范 也提供了实现交互的环境当这种连接建立起来后 两个模块之间就可以通过 接口 的机制来进行通讯 这些接口既不需要静态的或动态的连接入口点 也不需要编码很复杂的地址 什么是COM 全局唯一标识符 GlobalUniqueIDentifier 来源于OSF的通用统一标识符UUID UniversalUniqueIDentifier 是一个128位整数用于标识COM对象 CLSID 和接口 IID 由于空间足够大 冲突较小 可以用编程的方法生成具有唯一性的GUIDVC UUIDGEN EXE GUIDGEN EXE对GUID值的传递通常通过引用进行 COM基本概念 GUID 基本概念 COM对象 COM构件 COM接口 基本概念 COM对象和COM构件 在COM规约中 构件 和 对象 经常混淆 所谓COM对象是指符合COM规则的CoClass 构件类 的实例 每一个COM对象都有一个GUID 称为CLSID CoClassID COM构件是指以编译后的形式提供一组功能的COM对象独立于具体编程语言一个构件可以由多个类实现以二进制形式 DLL或EXE 发布可以在不妨碍客户的形式下被升级可以透明地在网络上被重新分配 COM接口是COM规范的核心内容 是COM对象显示出来的所有信息 是一组逻辑上相关的函数集合每一个接口都有一个GUID 称为接口标识符 简称IID InterfaceIDentifier COM接口具有不变性 只允许单继承一个COM对象可以实现多个接口 这体现了COM对象的多态性 这些接口由IUnknown接口来管理在C 中 可以用抽象基类来定义COM接口 基本概念 COM接口 新版本构件的处理 COM接口永远不会变化 一个IID就是一个接口 当对组件进行升级时 一般不会修改已有的接口 而是加入一些新接口当下列条件中的任何一个变化时 应给新接口指定新IID接口中函数数目接口中函数顺序某个函数的参数某个函数参数的顺序某个函数参数的类型函数可能的返回值函数返回值的类型等不同版本接口的命名 在老名称后加一个数字 是所有COM对象都必须实现的接口 其它接口都直接或间接继承IUnknown IID为 00000000 0000 0000 C0046 接口 包含三个基本操作AddRef 提供生存周期管理功能 增加对象引用计数Release 提供生存周期管理功能 用于释放对象QueryInterface 负责向客户提供接口查询功能 基本概念 IUnknown接口 IUknown接口的定义 定义在win32SDK中的UNKNWN h头文件中 interfaceIUnkown virtualHRESULT stdcallQueryInterface constIID 微软接口定义语言MIDL MicrosoftInterfaceDefinitionLanguage 是定义COM接口的申述式语言通过独立于具体编程语言的方式来定义接口该语言基于OSF分布式计算环境 DCE 远程过程调用 RPC 的接口描述语言IDLCOM规范使用的IDL接口描述语言不仅可用于COM接口 同时还定义了一些常用的数据类型 也可描述自定义的数据结构 对于接口的成员函数 可以指定每个参数的类型 输入输出特性 甚至可支持变长度的数组的描述MIDL支持指针类型 与C C 类似 基本概念 接口定义语言 接口定义例 interfaceIDictionary HRESULTInitialize HRESULTLoadLibrary in string HRESULTInsertWord in string in string HRESULTDeleteWord in string HRESULTLookWorld in string out string HRESULTRestoreLibrary in string HRESULTFreeLibrary 基本概念 接口定义语言 COM接口是一个二进制标准 客户同接口的连接并不是通过其名称或其成员函数的名称来实现的 而是通过其在内存块中的位置完成的COM接口是一个包含一个函数指针数组的内存结构 每一个数组元素包含的是一个由组件所实现的函数的地址C 通过纯抽象基类实现COM接口 实际上是定义了一个内存块的结构 但此内存只是在派生类中实现此抽象基类时才会被分配 派生类继承此抽象基类时将继承此内存结构 COM接口 虚拟函数表 COM接口的内存结构同C 编译器为抽象基类所生成的内存结构是相同的 对于如下利用纯抽象基类方式定义的接口interfaceIX virtualvoid stdcallFx1 0 virtualvoid stdcallFx2 0 virtualvoid stdcallFx3 0 virtualvoid stdcallFx4 0 提高接口实现的灵活性 实现抽象基类的类可能会将特定于实例的信息同vtbl一块保存 例子 一个实现接口IX的类CA CA包含2个数据 classCA publicIX public virtualvoid stdcallFx1 virtualvoid stdcallFx2 virtualvoid stdcallFx3 virtualvoid stdcallFx4 doubleData1 doubleData2 Vtbl的作用 Vtbl指针 虚拟函数表 IX Fx1 Fx2 Fx3 Fx4 Data1 Data2 pA Fx1Fx2Fx3Fx4 CA 实例数据和vtbl一起保存 注意 COM组件决不会访问任何实例数据 在COM中 对一个组件的访问只能通过函数完成 绝不能直接通过变量纯抽象基类只有虚拟函数 没有实例数据 两个实例共享同一Vtbl 所有COM接口都必须继承IUnknown接口 支持其定义的三个函数 而且必须是接口vtbl的前三个函数 IUnknown CreateInstance 创建构件时 客户可以使用CreateInstance 而不是newCreateInstance的定义 IUnknown CreateInstance IUnknown pI static cast newfoo pI AddRef returnpI IUnknown指针的获取 一个COM对象 构件 可以实现多个接口 使用QueryInterface查询某个构件是否支持某个特定的接口voidfoo Iunknown pI IX pIX NULL HRESULThr pI QueryInterface IID IX void 接口查询 假定存在类CA 继承接口IX与IYHRESULT stdcallCA QueryInterface constIID QueryInterface的实现 QueryInterface返回的总是同一个IUnknown指针若客户曾经获取过某个接口 那么它将总能获取此接口客户可以再次获取已经拥有的接口客户可以返回到起始接口若能够从某个接口获取某特定接口 则可以从 该构件的 任意接口获取此接口 QueryInterface的实现规则 通过函数AddRef与Release实现控制构件的生命期解决内存管理问题使构件能够自己将自己删除使用规则返回接口指针之前调用AddRef 使用完接口之后调用Release 赋值之后调用AddRef 引用计数 在什么层次上进行计数 构件 对象 接口 引用计数的实现方式 函数的参数中使用接口指针变量对于输入参数 被调函数不必改变计数对于输出参数 相当于生成了一个新的接口指针变量 因此在返回之前 需要使计数增1对于输入输出参数 参数修改之前计数减1 修改之后计数加1 若参数未被修改 计数不变对于局部接口指针变量 不改变计数对于全局接口指针变量 作为参数传给某函数之前 计数增1 返回之后计数减1 C 类成员变量为接口指针变量时也采用此规则 引用计数的更详细的规则 COM构件可以和客户机程序在同一个进程中 也可以在不同的进程中前者称为进程内构件 INPROC SERVER 后者称为进程外构件 LOCAL SERVER 如果是DCOM 进程外构件还包括CLSCTX REMOTE SERVER COM构件与客户机之间的通信机制 在Windows平台上 进程内构件以动态链接库 DLL 形式实现由于DLL包含一个导出函数表 客户机程序和DLL动态连接时会建立一张表 把客户机调用和DLL中函数的地址连接起来因此客户机程序和进程内构件可通过直接函数调用进行交互进程内构件程序也可称作进程内服务程序 COM构件与客户机之间的通信机制 对于进程外构件 由于进程之间相互屏蔽 客户机进程不能直接调用构件进程 需要遵循操作系统对进程间通信所做的规定 在Windows平台上 进程外构件以EXE实现 COM采用本地过程调用 LPC 作为进程间通信机制 COM构件与客户机之间的通信机制 当调用组件的时候 其实是依靠代理 运行在本地 和存根 运行在远端 之间的通讯完成的 组件调用机制 COM不仅定义了客户与构件之间交互的规约 而且提供了全面的实现细节 COM的实现与操作系统密切相关 包括 COM库 COMLibrary 系统注册表 windowsregistry 类工厂COM服务器 COM的实现 是COM标准的系统级实现 为COM对象的标识和创建 内存管理 构件程序的卸载等提供了一组标准接口和辅助函数在Windows系统中 COM库主要包含在OLE32 dll OLE32 lib和RPCSS dll文件中COM库很多地方直接用到了Windows系统的一些特性 例如系统注册表和动态链接库 COM通过注册表查找本地服务器 即EXE程序 以及程序名与CLSID的转换 COM库 COM库 COM库中常用的函数初始化函数与GUID相关的函数对象创建函数内存管理函数 在使用COM库中的其他函数之前 进程必须先调用HRESULTCoInitialize void reserved 参数必须为NULL注意 对每一个进程 COM库函数只需要初始化一次 由于COM主要用于创建组件 进程内组件无需初始化COM库在退出之前调用voidCoUninitialize void reserved 注意 和初始化函数配合使用由于OLE建立在COM基础上 初始化需要调用OleInitialize 函数和OleUnInitialize 函数DCOM使用CoInitializeEx函数进行初始化 初始化函数 关于HRESULT 组件API及接口指针中 除了IUnknown AddRef IUnknown Release 两个函数外 其它所有的函数 都以HRESULT作为返回值HRESULT是一个双字节的值最高位0表示成功最高位1表示错误 HRESULTS OK0 x00000000成功S FALSE0 x00000001函数成功执行完成 但返回时出错E INVALIDARG0 x80070057参数有错误E OUTOFMEMORY0 x8007000E内存申请错误E UNEXPECTED0 x8000FFFF未知的异常E NOTIMPL0 x80004001未实现功能E FAIL0 x80004005没有详细说明的错误E POINTER0 x80004003无效的指针E HANDLE0 x80070006无效的句柄E ABORT0 x80004004终止操作E ACCESSDENIED0 x80070005访问被拒绝E NOINTERFACE0 x80004002不支持接口 关于HRESULT 由于注册表中包含的是CLSID的字符串表示 因此需要一些函数完成CLSID与表示CLSID的字符串之间的转换StringFromGUID2 将GUID转换为字符串类型其它 StringFromCLSID 将CLSID转化为文本串StringFromIID 将IID转化为文本串CLSIDFromString 将一个文本串转化为CLSIDIIDFromString 将一个文本串转化为IIDIsEqualGUID IsEqualIID IsEqualCLSIDCLSIDFromProgID 与GUID CLSID 相关的函数 对象创建函数 CoGetClassObjectCoCreateInstanceCoCreateInstanceExCoRegisterClassObjectCoRevokeClassObjectCoDisconnectObject 内存管理函数 CoTaskMemAllocCoTaskMemReallocCoTaskMemFreeCoGetMalloc 一个例子 IX pIX NULL HRESULThr CoCreateInstance CLSID Component1 NULL CLSCTX INPROC SERVER IID IDX void Windows注册表 系统注册表是一个全操作系统范围公用的信息仓库 可用作客户程序 构件程序和COM库三者交换有关COM对象信息和接口信息的场所Windows操作系统的系统注册表中包括硬件 软件 配置及用户等各种信息由REGEDIT EXE启动由REGSVR32 EXE来注册某个构件系统注册表是一个由许多元素构成的层次结构 每个元素均被称作一个关键字 每个关键字可以包含一系列子关键字例如 HKEY CLASSES ROOTCLSIDProgID等 通过Windows注册表注册组件 注册文件REGEDIT4 HKEY CLASSES ROOT TEST TESTCOM HKEY CLASSES ROOT TEST CLSID b91c46bc 5841 4f41 95f3 daade42b3436 组件注册其它方法 情况1 当使用ATL ActiveTemplateLibrary 编写组件程序 编译成功后 IDE自动完成注册 情况2 当使用MFC编写组件程序 由于编译器不知道编写的是否是COM组件 所以无法自动注册 可执行菜单 Tools RegisterControl 来注册情况3 当写了一个具有COM功能的EXE程序时 运行一次该程序即可完成组件注册情况4 当需要使用第三方提供的组件程序时 可通过命令行运行 regsvr32 exe文件名 来注册 反注册的方法是 regsvr32 exe u文件名 关于注册组件 情况5 当需要在程序中 如安装程序 执行注册 那么 typedefHRESULT WINAPI FREG TCHARszWorkPath MAX PATH GetCurrentDirectory sizeof szWorkPath szWorkPath SetCurrentDirectory 组件目录 HMODULEhDLL LoadLibrary 组件文件名 if hDLL FREGlpfunc FREG GetProcAddress hDLL T DllRegisterServer if lpfunc lpfunc FreeLibrary hDLL SetCurrentDirectory szWorkPath 类工厂是能够创建其它COM对象的特殊COM对象 类工厂支持一个特殊的接口IClassFactory 为例化CoClass构件类提供了一种标准机制每一个COM对象类应该有一个相应的类工厂对象IClassFactory接口中定义了两个重要的操作CreateInstance 生成COM对象并返回所请求接口的指针LockServer 负责在内存中保持COM构件 类工厂 具有四个输入参数和一个输出参数 第一个参数表示待创建组件的CLSID 第三个参数表示组件执行上下文 第四个参数表示待使用接口的IID 输出代表接口指针执行上下文可通过如下值组合CLSCTX INPROC SERVER CLSCTX INPROC HANDLER CLSCTX LOCAL SERVER CLSCTX REMOTE SERVER无法为组件的创建加上限制条件 用该函数建立组件后 无法控制组件的装载位置或无法检查客户是否有权限创建该组件 CoCreateInstances函数的灵活性不足有必要使用一个专门用于创建所需组件的组件 类厂 关于CoCreateInstance的分析 类厂 ClassFactory 如果使用类厂 CoCreateInstance实际上未直接创建COM构件 而是创建了一个被称为类厂的构件 类厂构件的唯一功能是创建其他构件客户可以通过类厂所支持的接口来对类厂创建构件的过程加以控制CoCreateInstance首先调用CoGetClassObjec获取类厂中的IClassFactory接口的指针然后使用返回的指针调用IClassFactory CreateInstance完成新组件的创建 IClassFactory 用于创建构件的标准接口 InterfaceIClassFactory IUnknown HRESULT stdcallCreateInstance IUnknown pUnknownOuter constIID 另一个创建接口 IClassFactory2增加了许可和权限功能 通过使用该接口 类厂可以保证客户只能获得他能合法访问的组件 并具有此组件的访问授权 CoCreateInstance通过CoGetClassObject实现HRESULTCoCreateInstance constCLSID 组件创建过程 是指包含一个或多个COM对象类和相应的类工厂 能向客户提供服务的一个程序 EXE 或库 DLL COM服务器 客户机 COM库 6 对象被创建 COM的复用方式 COM不允许直接继承 但可通过包含和聚合来代替继承如果一个构件B使用另外一个构件A 我们称使用者B为外部构件 被使用者A为内部构件 则称 外部构件B包含 聚合 了内部构件A包含与聚合是COM的两种复用方式 模型 为系统升级和扩展提供支持 包含 Containment 包含 Containment 对象B的成员函数在调用对象A的接口之前或之后可以进行其他任何操作IX 提供的功能可以超过IX对象B是对象A的客户 而对象B的客户看到的只是对象B显露出的接口 IY和IX 对象A的创建与释放完全在对象B内部进行 对象A的生命期包含在对象B的生命期内 包含 Containment 聚合 Aggregation 聚合 Aggregation 聚合可看作是包含的一个特例 聚合更好地体现了复用虽然对象A直接向对象B的客户提供服务 但对象B的客户感觉不到对象A的存在 对象A的生存期受到对象B的控制实现聚合的关键在于QueryInterface当客户向对象B请求IX时 对象B的QueryInterface返回对象A的IX指针存在问题 1 从IX如何得到IY 2 从IX得到的Iunknown如何与从IY得到的IUnknown相同 聚合 Aggregation 包含的复用性建立在客户 服务器模式上 而聚合的复用性需要内部构件提供支持复用方式的选择 当内部构件提供的接口完全满足要求时 使用聚合合适当内部构件提供的接口与需求类似时 使用包含合适在一个对象中可以同时使用两种复用方式 包含与聚合的使用 自动化是允许高级语言使用构件的COM应用技术 自动化的核心是IDispatch接口 自动化对象就是实现了IDispatch接口的COM对象IDispatch接口是自动化对象必须实现的接口 IDispatch在IUnkown接口的基础上增加了如下操作GetIDsOfNames操作负责返回操作或属性及其参数名字的分发标识符 分发ID 即DISPID 用于管理属性和操作 GetTypeInfo处理对象类型信息GetTypeInfoCount处理对象类型信息Invoke是IDispatch的核心操作 根据分发ID执行相应函数 COM的动态激活机制 自动化 COM的动态激活机制 自动化 Invoke操作和分发ID机制使得运行时动态绑定属性和方法成为可能 但灵活性的代价是效率的降低 如果将DISP硬编码在应用中而不是频繁调用GetIDsofNames 即早绑定 情况也许会更好 IDL中用disinterface支持该类情况对象描述语言ODL是对IDL的扩充 用来描述COM对象的类型信息 包括接口的类型信息 interface或disinterface 和COM对象类的类型信息 用coclass关键字描述 类型库是IDL文件经过编译后产生的一个资源文件 包含COM服务器中COM对象和接口的信息IDL用library描述类型库信息 包括类型库的全局唯一标识符 LIBID 类型库所使用的版本 语言等 COM的动态激活机制 自动化 COM的动态激活机制 自动化 自动化组件可以被脚本语言直接调用 也称为双接口组件 DCOM是COM的进一步扩展 DCOM用网络协议来代替本地进程之间的通信 并针对分布环境提供了一些新的特性 例如 位置透明 网络安全性 跨平台调用等DCOM的分布特性依靠远程过程调用实现 分布构件对象模型DCOM 基于COM组件开发可简要描述为以下几个过程建立COM组件基于ATL编程基于MFC编程 可用于实现自动化组件 组件的编译组件的注册编写客户端程序 调用组件的接口函数 基于COM组件的开发过程 组件程序的编译 说明1 编译后 类型库以TLB文件形式单独存在 同时也保存在目标文件的资源中 import引入类型库的时候 既可以指定TLB文件 也可以指定目标文件说明2 IDL编译后生成代理 存根源程序 有 dlldata c xxx p c xxxps def xxxps mak可以用NMAKE EXE再次编译来产生真正的代理 存根DLL目标文件 组件程序编译过程 组件调用的方法主要分为以下几种 include方法 IDL编译后 会产生xxx h和xxx i c文件 可直接 include该文件 如 include ComTest h include ComTest i c 如用到CComBSTR 还需要包含 include import方法 比较通用的方法 vc会帮我们产生包装类 如 import ComTest tlb 客户端程序 组件调用 include ComTest h include ComTest i c CoInitialize NULL IUnknown pUnk NULL IFun pFun NULL HRESULThr hr CoCreateInstance CLSID Fun NULL CLSCTX INPROC SERVER IID IUnknown LPVOID 调用组件函数 组件调用 简单调用1 include ComTest h include ComTest i c CoInitialize NULL IFun pFun NU
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年医药流通行业供应链可视化与成本控制策略研究报告
- 中国储能电池市场2025年能源资源应用分析报告
- 河北省廊坊市2025届英语八年级第二学期期末复习检测模拟试题含答案
- 保安岗位科目题库及答案
- 2025年家具制造业个性化定制生产模式下的个性化定制生产模式下的产业竞争力分析报告
- 安全注射管理试题及答案
- 安全试题分类及答案大全
- 安全环保试题题库及答案
- 沟通培训课件模板
- 学校礼仪接待培训课件
- GB/T 32151.6-2015温室气体排放核算与报告要求第6部分:民用航空企业
- GB/T 13936-2014硫化橡胶与金属粘接拉伸剪切强度测定方法
- GB 29837-2013火灾探测报警产品的维修保养与报废
- 一例慢阻肺病人护理个案
- 建平中学自招真题解析
- DB50-T 1293-2022 松材线虫病疫木除治技术规范(标准文本)
- 微电子工艺实验报告
- 金属材料检验的标准课件
- 动物疫病流行病学调查表诊断送检用
- 模具技术要求
- 广东省公务员录用审批表
评论
0/150
提交评论