COM组件编写与调用
- 格式:doc
- 大小:180.50 KB
- 文档页数:11
C#调⽤COM组件的⼏个步骤< DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd>这⾥我们将介绍C#调⽤COM组件的⼏个步骤,先将Com类型信息转换为.NET元数据,然后查看元数据,最后测试程序。
⾸先将Com类型信息转换为.NET元数据1. tlbimp sample.dll /out: sample_clw.dll⼯具:Tlbimp.exe(类型库导⼊程序)参考:.Net framework SDK ⽂档1. ms-help://FrameworkSDK.CHS/cptools/html/cpgrftypelibraryimportertlbimpexe.htm查看元数据⼯具:ILDasm参考:ms-help://FrameworkSDK.CHS/cptutorials/html/il_dasm_tutorial.htm测试程序:⽣成⼀个console programme在project->add reference⾥,选择com,browser你的com,selectok,现在在你的bin⽬录下应该有⼀个sample_clw.dll了下⾯我们来⽤sample_clw的⽅法1. using System;2. using sample_clw;3. namespace CompConsole4. {5. /// <summary>6. /// Class1 的摘要说明。
7. /// </summary>8. class Class19. {10. /// <summary>11. /// 应⽤程序的主⼊⼝点。
12. /// Date:2003/6/2013. /// </summary>14. [STAThread]15. static void Main(string[] args)16. {17. //18. // TODO: 在此处添加代码以启动应⽤程序19. Console.Write ("=======Demo for Call com functions in c#=============\n");20. sampleClass sam = new sampleClass();21. //now we call functions22. //23. sam.SayHello();24. }25. }。
COM培训教程COM(Component Object Model)是一种用于组件间通信的架构,它可以实现不同应用程序组件的互操作。
COM培训教程旨在向初学者介绍COM的基本概念和使用方法,以帮助他们快速入门并开始开发自己的COM组件。
第一部分:COM概述(约200字)COM是一种面向对象的技术,它允许开发人员将代码模块化并以可重用的方式进行组合。
COM组件可以是任意编程语言编写的,只要它们符合COM的规范,就可以在不同的应用程序中进行调用和使用。
COM的核心概念是接口(Interface)。
接口定义了COM组件提供给其他组件调用的方法和属性。
通过接口,组件之间可以进行交互和通信。
COM组件还具有生命周期管理和对象实例化等基本特性。
第二部分:COM开发环境搭建(约300字)在开始COM开发之前,我们需要安装COM开发所需的工具和环境。
通常,COM开发需要使用Microsoft Visual Studio作为开发集成环境(IDE)。
Visual Studio提供了编译、调试和托管COM组件的功能。
除了IDE,我们还需要安装COM SDK(Software Development Kit),它包含了一些用于COM开发的工具和库。
COM SDK提供了COM组件的编译器、链接器和注册器等工具。
第三部分:COM组件编写(约400字)在这一部分,我们将学习如何编写一个简单的COM组件。
首先,我们需要定义COM组件的接口,接口定义了组件对外提供的方法和属性。
然后,我们需要实现接口,编写组件的具体功能代码。
接着,我们需要注册COM组件,使其可以在其他应用程序中被调用。
注册COM组件需要使用COM注册表,它是一个记录已注册组件信息的数据库。
我们可以使用COM SDK提供的注册器工具来执行注册操作。
最后,我们需要编译和部署COM组件。
编译COM组件需要使用COM编译器,它会将源代码转化为二进制文件。
部署COM组件需要将编译后的二进制文件复制到目标应用程序的目录,并在应用程序中进行配置。
C++调⽤com控件⽅法最近要求做⼀个C++调⽤com组件的DEMO。
由于⾃⼰对C++并⽆研究包括IDE⼯具。
后来在⽹上查阅了些资料,经过努⼒终于告⼀段落。
⽹上对于C++加载com组件的⽅法已经说的很多了,我就仅贴下我所使⽤的⽅法(不⽤注册dll,当然⽹上推荐了⼀些更简单也更有实际意义的使⽤⽅式):CLSID clsid;HRESULT hr1=CLSIDFromProgID(OLESTR("PTA.iTrusPTA"),&clsid);//获得dll控件的clsidtypedef HRESULT (__stdcall * pfnGCO) (REFCLSID, REFIID, void**);pfnGCO fnGCO = NULL;HINSTANCE hdllInst = LoadLibrary(L"PTAExt.dll"); //加载dllfnGCO = (pfnGCO)GetProcAddress(hdllInst, "DllGetClassObject"); //从dll中得到DllGetClassObjectif (fnGCO != 0){IClassFactory* pcf = NULL;HRESULT hr=(fnGCO)(clsid, IID_IClassFactory, (void**)&pcf); //创建⼯⼚if (SUCCEEDED(hr) && (pcf != NULL)){IiTrusPTA* pFoo = NULL;hr = pcf->CreateInstance(NULL, __uuidof(IiTrusPTA), (void**)&pFoo); //通过⼯⼚创建dll中IiTrusPTA接⼝//调⽤IiTrusPTA具体的业务操作if (SUCCEEDED(hr) && (pFoo != NULL)){ICertFilter *a = pFoo->Filter;ICertificatesPtr certs = pFoo->MyCertificates;long temp = certs->Count;if(temp>0){for(int i=1;i<=temp;i++){_variant_t cert = certs->Item[i];ICertificatePtr date = (ICertificatePtr)cert.pdispVal;_bstr_t name = date->CommonName;((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString(name);((CComboBox *)GetDlgItem(IDC_COMBO1))->SetCurSel(0);}}else{((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString(L"没有找到数字证书");((CComboBox *)GetDlgItem(IDC_COMBO1))->SetCurSel(0);}}pFoo->Release();}pcf->Release();}FreeLibrary(hdllInst);//释放dll资源整个流程就是通过LoadLibrary()加载dll,然后IClassFactory去创建com组件实例。
COM组件技术1 COM组件概述 (3)2 COM组件实例 (3) (3)2.1.1 VC6.0 创建COM组件 (3) (7) (9)2.2.4 使用.Net(VB)调用 (11)2.2.5 使用.Net(C#)调用 (13)2.2 .NET(C#)创建的COM组件及调用过程 (15)2.1.1 C# 创建COM组件 (15) (20) (22)2.2.4 使用.Net(VB)调用 (23)2.2.5 使用.Net(C#)调用 (25)3 佳衡电力抄表Com组件.........................................................错误!未定义书签。
1 COM组件概述COM是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术。
在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应用系统。
COM组件的优点:①可以将系统中的组件用新的替换掉,以便随时进行系统的升级和定制;②可以在多个应用系统中重复利用同一个组件;③可以方便的将应用系统扩展到网络环境下;④COM组件的特性是与语言无关和与平台无关。
因此,一经开发便可以使用不同的高级语言和开发工具调用。
并且,客源在此COM组件基础进行二次开发。
2 COM组件实例本部分将使用VC6.0创建COM组件。
并介绍如何在VC6.0、VB6.0、、C#中调用该COM组件。
2.1.1 VC6.0 创建COM组件1、在VC中新建“A TL COM AppWizard”工程,工程名称为“VCCOMTest”,并确认。
2、在服务器类型中,选择“动态链接库(DLL)”,完成3、选择菜单栏“插入”“A TL对象”,选择“Simple Object”,点击“Next”4、在上面C++“Short Name”后输入“COMTestInVC”,将会自动填充其余选项。
Attributes 部分按默认设置。
C#开发COM组件1、每个COM组件所有对外公布的⽅法都必须通过接⼝形式实现;2、由于.Net下编译的COM组件并等同于C编译的COM组件,所以存在必须在运⾏⽬标机器注册的情况,对此.Net下编译的COM组件必须为程序进⾏签名,即强命名密钥;步骤:1、新建⼀个类库项⽬(⽂件—新建—项⽬—类库【命名:PBDemo】)2、针对“注意第⼀点要求”,新建⼀个接⼝⽂件(项⽬右键—添加—新建项—接⼝【命名:IHK.cs】)3、 IHK.cs接⼝⽂件编码:int TestFunction(int num, string str1, string str2, double db);4、将Class1.cs 改名为:HKTest.cs (这步其实很啰嗦,不过⽂档都整理了,就这样写吧)提⽰框点击“是”,如下图5、 HKTest.cs 类⽂件编码:添加名称空间:using System.Runtime.InteropServices;实现接⼝、并在类头添加属性:[ClassInterface(ClassInterfaceType.None)]。
如下图6、在“解决⽅案资源管理器”中找到节点“Properties”打开AssemblyInfo.cs⽂件如下图7、将[assembly: ComVisible(false)]属性改成[assembly: ComVisible(true)]如下图8、项⽬右键—属性、或者双击“Properties”节点,进⼊到项⽬属性设置界⾯ 8.1、选择“应⽤程序”选项卡,点击“程序集信息”按钮,如下图8.2、勾选“使程序集COM可见”,确定。
如下图8.3、选择“⽣成”选项卡,在底部“输出”栏⽬下,勾选“为COM互操作注册”。
如下图8.4、选择“签名”选项卡。
8.4.1、勾选“为程序集签名”; 8.4.2、在“选择强名称密钥⽂件”的下拉框选择“<新建…>” 8.4.3、在“密钥⽂件名称”输⼊:PBDemo.snk(任意命名,snk后缀即可) 8.4.4、去掉“使⽤密码保护密钥⽂件”,确定。
C#编写COM组件1、新建⼀个类库项⽬2、将Class1.cs改为我们想要的名字问是否同时给类改名,确定3、修改Properties⽬录下⾯的AssemblyInfo.csComVisible属性设置为True4、项⽬菜单->MyLib属性找到“⽣成”选项卡往下看,找到“为 COM Interop 注册”勾上5、继续往下,找到“签名”选项卡勾上“为程序集签名”在下⾯的下拉框⾥⾯选择“ <新建...>”6、在弹出的对话框⾥⾯,输⼊MyLib。
或者随便取个名字去掉使⽤密码保护⽂件的选项7、开始编码,任何⼀个公开的类,必须有⼀个 I开通的接⼝定义using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;namespace MyLib { [ComVisible(true)] [Guid("2CBD3D76-35F1-4f9d-9C1B-9DBFEE412F76")] public interface IMyClass { void Initialize(); void Dispose(); int Add(int x, int y); } [ComVisible(true)] [Guid("EA2F140A-108F-47ae-BBD5-83EEE646CC0D")] [ProgId("MyLib.MyClass")] public class MyClass : IMyClass { public void Initialize() { //nothing todo } public void Dispose() { //nothing todo } public int Add(int x, int y) { return x + y; } }}8、GUID属性⾥⾯的那个字符串,在“⼯具”菜单下⾯,“创建 GUID”选择 Registry Format,然后复制注意在[Guid("....... 这个⾥⾯要去掉GUID前后的花括号9、编译它在命令提⽰符下⾯,进⼊Dll所在的⽬录⽤ gacutil /i MyLib.dll 将这个DLL加⼊的全局缓存⾥然后⽤ regasm MyLib.dll 注册这个dll10、在javsScript⾥⾯试试.。
实验1. 编写COM组件并调用实验内容在VS2010环境中,使用C#语言编写一个简单的COM组件,然后在 中调用COM组件。
实验目的◆掌握COM组件的编写◆学会调用COM组件环境要求VS2010实验指导(一)C#编写COM组件步骤1:创建C#类库,名称为CLCOMTestInCSharp,如下图:注意:如果在win7下,VS2010要以管理员的身份运行步骤2:在“解决方案资源管理器”中,类“Class1.cs”更名为“CAdd.cs”,并在弹出的对话框选项中选择“是”。
如下图:步骤3:添加接口“IAdd”,并使类“CAdd”继承接口“IAdd”,代码如下:步骤4:在文档最上方添加命名空间“using System.Runtime.InteropServices ”的引用语句。
步骤5:通过菜单“工具”、“创建GUID”创建GUID,如下图:步骤6:“IAdd”接口上方使用该GUID步骤7:同样的方法在类“CAdd”的上方再生成添加一个GUID步骤8:完整代码如下:步骤9:打开“解决方案资源管理器”,打开“AssemblyInfo.cs”,将[assembly: ComVisible(false)]设为true。
步骤10:右击该类库项目,选择“属性”“生成”,将“为COM互操作注册”选中。
如图:步骤11:右击项目,“生成”。
将生成“CLCOMTestInCSharp.dll”、“CLCOMTestInCSharp.tlb”、“CLCOMTestInCSharp.pdb”三个文件(二)中调用C#编写的COM组件步骤1:使用创建“Windows窗体应用程序”项目,命名为“COMTest”。
如下图:步骤2:在窗体上添加一个Button,并将其Text属性设为“使用 调用C#创建的COM组件”步骤3:将“CLCOMTestInCSharp.dll”复制到程序目录,添加引用,选择“浏览”,如下图:步骤4:双击“Button”按钮,添加如下代码:步骤5:执行程序,结果如下图所示:实验报告●简述:COM组件开发步骤记录各个步骤,并截图(注意:各种命名要不同于本实验指导中的命名,以示区别)●实习过程中的技术问题及解决方法。
COM组件三个最基本的接口类//VC6中使用COM库的三种方法COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。
COM规范规定任何组件、任何接口都必须从IUnknown继承,IUnknown包含三个函数,分别是QueryInterface、AddRef、Release。
这三个函数是无比重要的,而且它们的排列顺序也是不可改变的。
QueryInterface用于查询组件实现的其它接口,说白了也就是看看这个组件的父类中还有哪些接口类,AddRef用于增加引用计数,Release用于减少引用计数。
引用计数也是COM中的一个非常重要的概念。
大体上简单的说来可以这么理解,COM组件是个DLL,当客户程序要用它时就要把它装到内存里。
另一方面,一个组件也不是只给你一个人用的,可能会有很多个程序同时都要用到它。
但实际上DLL只装载了一次,即内存中只有一个COM组件,那COM组件由谁来释放?由客户程序吗?不可能,因为如果你释放了组件,那别人怎么用,所以只能由COM组件自己来负责。
所以出现了引用计数的概念,COM维持一个计数,记录当前有多少人在用它,每多一次调用计数就加一,少一个客户用它就减一,当最后一个客户释放它的时侯,COM知道已经没有人用它了,它的使用已经结束了,那它就把它自己给释放了。
引用计数是COM编程里非常容易出错的一个地方,但所幸VC的各种各样的类库里已经基本上把AddRef的调用给隐含了,在我的印象里,我编程的时侯还从来没有调用过AddRef,我们只需在适当的时侯调用Release。
至少有两个时侯要记住调用Release,第一个是调用了QueryInterface以后,第二个是调用了任何得到一个接口的指针的函数以后,记住多查MSDN 以确定某个函数内部是否调用了AddRef,如果是的话那调用Release的责任就要归你了。
IUnknown的这三个函数的实现非常规范但也非常烦琐,容易出错,所幸的事我们可能永远也不需要自己来实现它们。
步骤1:创建项目Visual Studio .NET 2003本教程将带领您逐步骤通过一个非属性化ATL 项目,该项目创建一个显示多边形的ActiveX 对象。
此对象包括使用户得以更改组成多边形的边数的选项以及刷新显示的代码。
注意本教程创建与Polygon(多边形)示例相同的源代码。
如果您希望避免手动输入源代码,则可以从多边形示例摘要下载源代码。
然后,您可以一边参考Polygon 源代码一边阅读教程,或者用它来检查自己的项目中是否有错误。
使用“ATL 项目向导”创建初始ATL 项目1.在Visual Studio 开发环境中,在“文件”菜单上单击“新建”,然后单击“项目”。
2.单击“Visual C++ 项目”文件夹并选择“ATL 项目”。
3.键入Polygon作为项目名称:源代码的位置通常默认为My Documents\Visual Studio Projects,并且将自动创建一个新文件夹。
4.单击“确定”,“ATL 项目向导”随即打开。
5.单击“应用程序设置”以查看可用选项:6.在创建控件时,如果控件必须是进程内服务器,则将“服务器类型”保留为DLL。
7.本教程中将不使用属性,因此请确保没有选中“属性化”复选框。
8.将其他选项保留在它们的默认值,然后单击“完成”。
“ATL 项目向导”将通过生成若干个文件来创建项目。
可以通过展开Polygon 对象在解决方案资源管理器中查看这些文件。
下面列出了这些文件。
在下一步骤中,您将向项目添加控件。
步骤2:添加控件Visual Studio .NET 2003在此步骤中,您将向项目添加控件,生成此控件,并在Web 页中对其进行测试。
向ATL 项目添加对象1.在“类视图”中,右击“Polygon”项目。
2.指向快捷菜单上的“添加”,然后单击“添加类”。
即会出现“添加类”对话框。
左侧的树结构中列出了不同的对象类别:3.展开树结构并单击“ATL”文件夹。
4.从右侧的模板列表选择“ATL 控件”。
下面将pb10.5 创建com组件的过程举例如下1,新建project
2选择target
3下一步
4可以添加需要的pbl
5 可以修改名称
6 可以修改project名称
7 这是生成的com组件的接口的属性窗口,可以修改,也可以默认
8 这个就是生成的类
9
10
11 下一步
12前面信息的总览
13
这样就可以在n_genapp中编写自己需要的功能了
14最后编译程序就可以了
下面介绍生成的Dll如何在pb中调用,如果在生成的过程中没有选择编译后自动注册发布则就需要我们自己来注册了
通过cd找到dll所在的目录
用regsvr32来注册regsvr32 + dllName.dll 来注册.
Pb调用
最后附出在pb中要调用时所需要的主要代码
oleobject my_com
my_com = CREATE oleobject
my_com.ConnectToNewObject("PB105.n_genapp”) //需要处理的代码
my_com.DisconnectObject( )
DESTROY my_com。
一、新建工程1、安装VB6首先要安装VB6,可以下载绿色精简版。
2、打开安装好的VB6,选择,文件-新建工程-ActiveX DLL3、修改工程名和类名(可选)工程名改为activeTest,类名改为Main4、Helloworld此时,可以在类模块中写代码了:Public Function hello(ByVal msg As String) As StringMsgBox msgEnd Function5、保存工程先文件-保存工程,然后,文件-生成activeTest.dll(K)...6、注册activeX并找到classid打开cmd命令窗口(管理员方式运行),输入regsvr32 真实路径\activeTest.dll 开始菜单或运行窗口输入regedit,打开注册表编辑器。
ctrl+f弹出查询框,输入activeTest,查找如果上图没找到,就找下面的:7、Html调用,以下是html代码:<html xmlns="/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script type="text/javascript">function press(){var o = document.getElementById("cwgIE");//使用fireFox时,换成cwgo.hello("hello world!");}</script></head><body><object id="cwg" TYPE="application/x-itst-activex" clsid="{0BAF68D9-9B0C-4540-8F94-D70AEF6945B4}"></object> <object id="cwgIE" classid="clsid:0BAF68D9-9B0C-4540-8F94-D70AEF6945B4"></object><button onclick="press()">press</button></body></html>二、调用COM组件1、增加模块,准备调用COM组件右键工程,添加模块,命名为ComMd2、输入调用代码Public pramaObj As ObjectPublic Sub init(Appcode As Long, Appmsg As String)Dim paramid As Stringparamid = "yinhai.interface"On Error GoTo errorSet pramaObj = CreateObject(paramid)If pramaObj Is Nothing ThenErr.Description = "对象不存在,请确认动态库已正确注册!"GoTo errorEnd IfpramaObj.yh_interface_init Appcode, AppmsgGoTo successerror:Appcode = -2Appmsg = Err.Descriptionsuccess:End SubPublic Sub callInter(code As String, jysrXml As String, Businesssequence As String, Businessvalidate As String, Outputxml As String, Appcode As Long, Appmsg As String)On Error GoTo errorIf pramaObj Is Nothing ThenErr.Description = "对象不存在,请确认动态库已正确注册!"GoTo errorEnd IfpramaObj.yh_interface_call code, jysrXml, Businesssequence, Businessvalidate, Outputxml, Appcode, Appmsg GoTo successerror:Appcode = -2Appmsg = Err.Descriptionsuccess:End Sub3、Main模块写调用方法Public Function comInit() As StringDim Appcode As LongDim Appmsg As StringDim ret As Stringinit Appcode, AppmsgcomInit = CStr(Appcode) + "^" + AppmsgEnd FunctionPublic Function comCall(ByVal jybh As String, ByVal jysrXml As String) As StringDim Businesssequence As StringDim Businessvalidate As StringDim Outputxml As StringDim Appcode As LongDim Appmsg As StringcallInter jybh, jysrXml, Businesssequence, Businessvalidate, Outputxml, Appcode, AppmsgcomCall = CStr(Appcode) + "^" + Appmsg + "^" + Businesssequence + "^" + Businessvalidate + "^" + Outputxml End Function4、最后,JS调用console.log(Init());三、注意事项1、在不准备制作cab的情况下,怎么保持classid不变?编译好一次程序后,修改工程属性,使用二进制兼容模式。
如何在C#中调⽤COM组件⼀、引⾔下⾯就从⼀个具体的实例来看看在.NET 中是如何调⽤COM组件的。
⼆、如何在C#中调⽤COM组件——访问Office 互操作对象 因为Office产品中使⽤了很多COM组件,下⾯就演⽰通过调⽤Office中的COM对象来创建Word⽂档并保存创建的⽂档到⽂件⽬录下的例⼦(在新建的控制台程序⾥添加”Microsoft.Office.Interop.Word 14.0.0.0 “ 这个引⽤,14.0.0.0版本是对应于Office 2010的⼀个互操作程序集, 12.0.0.0版本则是对应于Office 2007的互操作程序集,如果你电脑中只安装了Office 2007的话,就只能找到 12.0.0.0的版本的,如果安装了Office 2010的话,就可以同时找到这两个版本。
)。
具体代码如下:using System;// 添加额外的命名空间using Microsoft.Office.Interop.Word;namespace COM互操作性{class Program{static void Main(string[] args){// 调⽤COM对象来创建Word⽂档CreateWordDocument();}private static void CreateWordDocument(){// 启动Word并使Word可见Application wordApp = new Application() { Visible = true };// 新建Word⽂档wordApp.Documents.Add();Document wordDoc = wordApp.ActiveDocument;Paragraph para = wordDoc.Paragraphs.Add();para.Range.Text = "欢迎你,进⼊Learning Hard博客";// 保存⽂档object filename = @"D:\learninghard.doc";wordDoc.SaveAs2(filename);// 关闭WordwordDoc.Close();wordApp.Application.Quit();}}}运⾏结果为:此时在所指定的⽂件⽬录中就可以看到你刚才创建的Word⽂档了。
C++COM编程-COM编程⼊门实践1. COM编程基础COM是⼀种规范,⽽不是实现。
当使⽤C++来实现时,COM组件就是⼀个C++类,⽽COM接⼝就是继承⾄IUnknown的纯虚类,COM组件就是实现相应COM接⼝的C++类。
COM规范规定,任何组件或接⼝都必须从IUnknown接⼝中继承⽽来。
IUnknown定义了3个重要函数,分别是QueryInterface、AddRef和Release。
其中,QueryInterface负责组件对象上的接⼝查询,AddRef⽤于增加引⽤计数,Release⽤于减少引⽤计数。
引⽤计数是COM中的⼀个⾮常重要的概念,它很好地解决了组件对象地⽣命周期问题,即COM组件何时被销毁,以及谁来销毁地问题。
除了IUnknown接⼝外,还有另外⼀个重要地接⼝,即IClassFactory。
COM组件实际上是⼀个C++类,对于组件地外部使⽤者来说,这个类名⼀般不可知,那么如何创建这个类地的例?由谁来创建?COM规范规定,每个组件都必须实现⼀个与之对应的类⼯⼚(Class Factory)。
类⼯⼚也是⼀个COM组件,它实现了IClassFactory接⼝。
在IClassFactory的接⼝函数CreateInstance中,才能使⽤new操作⽣成⼀个COM组件类对象实例。
COM组件有3种类型:①进程内组件(CLSCTX_INPROC_SERVER)②本地进程组件(CLSCTX_LOCAL_SERVER)③远程组件(CLSCTX_REMOTE_SERVER)在接⼝成员函数中,字符串变量必须⽤Unicode字符指针,这是COM规范的要求。
2. COM组件开发实现⼀个COM组件,需要完成以下⼯作:COM组件接⼝COM组件实现类COM组件创建⼯⼚COM组件注册与取消注册本⽂以⼀个例⼦作为说明,COM组件提供了⼀个SayHello的接⼝函数,将“Hello COM”打印输出。
2.1 创建COM组件接⼝COM组件接⼝是⼀个继承IUnknown的抽象类:1// IComTest.h2#pragma once3 #include <Unknwn.h>4// interface id,COM组件接⼝唯⼀标识5static const WCHAR* IID_IComTestStr = L"{213D1B15-9BBA-414A-BAB6-CA5B6CEF0006}";6static const GUID IID_IComTest = { 0x213D1B15, 0x9BBA, 0x414A, { 0xBA, 0xB6, 0xCA, 0x5B, 0x6C, 0xEF, 0x00, 0x06 } }; 7class IComTest :public IUnknown8 {9public:10virtual int _stdcall SayHello() = 0;11 };2.2 创建COM组件实现类COM组件类是⼀个实现了相应COM组件接⼝的C++类,注意:⼀个COM组件可以同时实现多个COM接⼝。
功能要求:实现C++COM组件在UCML平台下可以用类或对象的形式调用方法属性功能实现:测试文件:GsRetailCom.dll;使用到的开发工具:UCML , VS2010_C#实现过程:一:创建类库在VS2010下,创建类库文件,二:添加C++Com组件将C++Com组件放入类库项目下的bin\Debug中三:注册C++Com组件进入命令行工具(CMD)跳转至C++Com所在的路径下输入regsvr32 GsRetailCom.dll 回车,提示注册成功四:生成C#类库打开VS2010,执行添加引用引用成功!注意:将dll属性“嵌入互操作类型”改为false进入编程界面,引入C++Com命名空间,using GsRetailCom;创建调用函数:public static string GetStr(){GsRetailCom.CoGsRecClass cogs = new CoGsRecClass();cogs.CostItems = "牛¡ê牛¡ê";cogs.StartDate = "201200";cogs.ShopTable = "";cogs.ItemTable = "";cogs.StartDate = "";cogs.EndDate = "";cogs.TempTable = "";cogs.RecType = "";cogs.CostItems = "";cogs.ColorSize = true;cogs.Cost = true;cogs.Detail = true;cogs.CurDate = true;string str = cogs.SQL;return str;}点击运行生成类库五:UCML调用C++Com封装的C#Dll然后将生成的文件,放入UCMLProject\BPObject\bin目录下打开UCML 引入dll打开BPO 引入命名空间右键BPO 创建“添加服务端操作函数”调用函数的按钮测试成功!。
COM编程⼀、COM组件基础1.程序的编写⽅式 1) ⾯向过程的结构化编程 ⾃顶向下的编程⽅式(流程图) 2) ⾯向对象的编程 以对象或以类为中⼼,更符合⼈的思维习惯,通过模拟现实情况完成软件的编写。
(类图) 3) ⾯向组件的编程 将⼀些功能直接封装成可以执⾏的⼆进制模块,类似于搭积⽊的⽅式。
更适合⼤型项⽬,功能需求频繁发⽣变更的项⽬的开发,功能的复⽤,复⽤性更⾼的。
2. 组件及组件的特点 组件就是可以执⾏的⼆进制代码,可以为系统,软件或者其他组件提供相应的功能。
特点:1. ⼆进制代码,可以执⾏2. 动态加载和卸载3. 和具体的编程语⾔⽆关3. 组件的标准 COM提供可组件编写的彼标准,任何开发的语⾔编写组件时。
都要遵循这个标准。
⼆、COM接⼝1.接⼝Win API –Win32应⽤程序编程接⼝(函数库) C语⾔接⼝就是函数、 C++语⾔,接⼝就是类的公有函数集合 DLL的接⼝就是它所输出的那些函数 COM接⼝就是⼀组纯虚函数集合,是⼀个包含⼀个函数指针数组的内存结构,每个数组元素包含的是⼀个由组件所实现的函数的地址。
2.C++接⼝的实现 1.定义纯虚函数,不能有任何成员变量和⾮纯虚函数 2.基于纯虚类,派⽣实现类 3.添加创建对象的函数,并使⽤接⼝返回创建的对象 引⼊c++接⼝之后,当功能的提供者发⽣变化时,功能的使⽤者代码不⽤修改,两者之间的耦合性降低了。
Dll接⼝的实现 功能的提供者放到动态库中和功能的使⽤者分开两个不⽤的⼯程 1.创建Win32 dll的⼯程 2.添加头⽂件XXX.h,在⽂件中添加接⼝的定义 3.在⼯程的实现⽂件中添加实现类以及创建对象的函数1. 导出创建对象的函数,通过添加def⽂件导出该函数Dll 接⼝的使⽤ 调出导出函数的步骤:1. 加载动态库,LoadLibrary获得句柄。
2. 获取导出函数的函数地址,GetProcAddress3. 调⽤导出函数,创建对象,返回接⼝。
COM组件编写与调用1、在VS2005中,C#编写DLL并使用C++调用2、在VS2005中C#编写的COM组件,使用VC6.0调用3、在VC6.0中编写COM组件,使用VS2005 C#调用4、在VC6.0中编写COM组件,使用VC6.0调用其中每个类型都写了两个程序,一个为COM组件程序,一个为调用程序程序实现:1、在VS2005中,C#编写DLL并使用C++调用(1)C#编写DLL程序建立C#编写的DLL程序AddDll,项目类型为:类库程序代码:using System;using System.Collections.Generic;using System.Text;namespace AddDll{public class Add{public int iadd(int a, int b){int c = a + b;return c;}}}(2)C++编写调用程序建立C++的Win32控制台应用程序UseDll,项目类型为:Win32控制台应用程序配置:右键点击解决方案资源管理器中的UseDll,选择“属性”,将公共语言运行库支持设置为“公共语言运行库支持(/clr)”图一公共语言运行库设置程序代码:#include "stdafx.h"#include "stdio.h"#using "..\debug\AddDll.dll"using namespace AddDll;int _tmain(int argc, _TCHAR* argv[]){int result;Add ^add = gcnew Add();result = add->iadd(10,90);printf("%d",result);scanf("%s");return 0;}2、在VS2005中C#编写的COM组件,使用VC6.0调用(1)VS2005中使用C#编写COM组件建立C#编写的COM组件,项目类型为类库配置:右键点击解决方案资源管理器中的AddCom,选择“属性”,选择“生成”,选择“为COM Interop注册(_P)”打开AssemblyInfo.cs文件,设置[assembly: ComVisible(true)]这用就可以生成AddCom.tlb文件图二COM生成设置程序代码:using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;namespace AddCom{//可以通过//菜单的“工具/guid生成”。
//注意要选择De fine Guid{….}格式,并全//部保存下来,保存到哪都行,记事本呀什么的。
//因为在做VC程序/////////的时候要用到的。
[Guid("298D881C-E2A3-4638-B872-73EADE25511C")]public interface AddComInterface{[DispId(1)]int iadd(int a, int b);[DispId(2)]float ladd(float a, float b);}[Guid("2C5B7580-4038-4d90-BABD-8B83FCE5A467")][ClassInterface(ClassInterfaceType.None)]public class AddComService : AddComInterface{public AddComService(){}public int iadd(int a, int b){int c = 0;c = a + b;return c;}public float ladd(float a, float b){float c = 0;c = a + b;return c;}}}(2)VC6.0编写调用程序使用VC6.0编写建立MFC应用程序UseCom,项目类型为MFC AppWizard(exe)在stdafx.h添加:#import "AddCom.tlb"using namespace AddCom;程序代码:void CUseComDlg::OnButtonUse(){// TODO: Add your control notification handler code hereint dresult;float fresult;CString strResult;CoInitialize(NULL);//NULL换成0也可以AddCom::AddComInterfacePtrp_Add(__uuidof(AddComService));dresult = p_Add->iadd(1,2);fresult = p_Add->fadd(1.2,2.3);strResult.Format("int:%d\nfloat:%f",dresult,fresult);MessageBox(strResult,"计算结果",MB_OK);CoUninitialize();}3、在VC6.0中编写COM组件,使用VS2005 C#调用(1)VC6.0编写COM使用VC6.0建立COM组件,工程类型:ATL COM AppWizard程序代码:接口:interface IAdd : IDispatch{[id(1), helpstring("method iadd")] HRESULT iadd([in]int a, [in]int b, [out]int * c);[id(2), helpstring("method fadd")] HRESULT fadd([in]float a, [in]float b, [out]float * c);[id(3), helpstring("method isub")] HRESULT isub([in]int a, [in]int b, [out]int * c);};实现:STDMETHODIMP CAdd::iadd(int a, int b, int *c){// TODO: Add your implementation code here*c = a + b;return S_OK;}STDMETHODIMP CAdd::fadd(float a, float b, float *c){// TODO: Add your implementation code here*c = a + b;return S_OK;}STDMETHODIMP CAdd::isub(int a, int b, int *c){// TODO: Add your implementation code here*c = a - b;return S_OK;}(2)VS2005使用C#编写调用程序(网站程序)使用VS2005建立网站UseCom配置:在解决方案资源管理器中的主目录点击右键,选择添加引用,选择COM,添加刚刚建立的AddCom 1.0 Type Library在程序中要using编写的COM组件:using ADDCOMLib;图三引用COM程序代码:using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using ADDCOMLib;public partial class _Default : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){}protected void ButtonCom_Click(object sender, EventArgs e) {Add add = new Add();int iresult;float fresult;int sresult;add.IAdd(10, 20, out iresult);add.fadd((float)1.2,(float)2.3, out fresult);add.isub(100, 10, out sresult);TextBoxResult.Text = iresult.ToString();TextBoxRe2.Text = fresult.ToString();TextBoxRe3.Text = sresult.ToString();}}4、在VC6.0中编写COM组件,使用VC6.0调用(1)VC6.0编写COM组件使用VC6.0建立COM组件,工程类型:ATL COM AppWizard程序代码:接口:interface IAdd : IDispatch{[id(1), helpstring("method iadd")] HRESULT iadd([in]int a, [in]int b, [out]int * c);[id(2), helpstring("method fadd")] HRESULT fadd([in]float a, [in]float b, [out]float * c);[id(3), helpstring("method isub")] HRESULT isub([in]int a, [in]int b, [out]int * c);};实现:STDMETHODIMP CAdd::iadd(int a, int b, int *c){// TODO: Add your implementation code here*c = a + b;return S_OK;}STDMETHODIMP CAdd::fadd(float a, float b, float *c){// TODO: Add your implementation code here*c = a + b;return S_OK;}STDMETHODIMP CAdd::isub(int a, int b, int *c){// TODO: Add your implementation code here*c = a - b;return S_OK;}(2)VC6.0编写调用程序使用VC6.0建立MFC应用程序UseCOM,调用刚刚建立的COM组件将上面程序AddCom生成的AddCom.dll放入本程序的工程目录和程序生成目录中在StdAfx.h中加入:#import "AddCom.dll" no_namespace程序代码:void CUseComDlg::OnBUTTONUse(){// TODO: Add your control notification handler code hereCString strResult;CoInitialize(NULL);//NULL换成0也可以IAddPtr m_add = NULL;HRESULT hr = S_OK;hr = m_add.CreateInstance(__uuidof(Add));int d_a = 90;int d_b = 10;int d_c;int d_d;float f_a = 1;float f_b = 2;float f_c;m_add->_IAdd(d_a,d_b,&d_c);m_add->fadd(f_a,f_b,&f_c);m_add->isub(d_a,d_b,&d_d);strResult.Format("返回结果:%d; %f; %d",d_c,f_c,d_d);MessageBox(strResult,"结果",MB_OK);m_add.Release();m_add = NULL;CoUninitialize();}。