用C#创建COM对象

2016-02-19 16:58 5 1 收藏

清醒时做事,糊涂时读书,大怒时睡觉,无聊时关注图老师为大家准备的精彩内容。下面为大家推荐用C#创建COM对象,无聊中的都看过来。

【 tulaoshi.com - 编程语言 】

  在本篇文章中,我们将讨论下面的问题:

  使用C#创建一个简单的COM对象(使用COM的Interop特性)。

  从VC++客户端软件中访问COM。客户端软件使用了TypeLibrary(.TLB文件)。

  为了简单和方便开发人员使用、测试起见,我们使用了SQLSERVER数据库软件的缺省安装中的Northwind数据库。

  修改COM对象中SQLServer的名字,与SQLServer连接。

  我们已经创建了连接数据库用的分别为scott、tiger的用户名和口令,我们可以使用它或者其他现有的用户名和口令。

  第一部分:用C#创建简单的COM对象

  COM对象是ClassLibrary类,它生成DLL文件。要在VS开发环境中创建一个简单的COM对象,我们可以依次选择文件->;新创建->;工程->;VisualC#工程->;类库,然后创建一个名字为Database_COMObject的工程。

  需要注意的是:在COM中调用VC#对象需要下面的条件:

  类必须是public性质。

  特性、方法和事件必须是public性质的。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  特性和方法必须在类接口中定义。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  事件必须在事件接口中定义。

  不是在这些接口中定义的public性质的类成员不能被COM访问,但它们可以被其他的.NET Framework对象访问。要让COM能够访问特性和方法,我们必须在类接口中定义它们,使它们具有DispId属性,并在类中实现这些特性和方法。这些成员定义时的顺序也就是它们在COM中顺序。要让COM访问类中的事件,必须在事件接口中定义这些事件,并赋予它们DispId属性。事件接口不应当由类完成,类只实现类接口(它可以实现不止一个接口,但第一个接口是缺省接口),应当在缺省接口中实现需要让COM访问的方法和特性,方法和特性必须被标识为public性质,并符合在类接口中的定义。需要让COM访问的事件也在缺省的类接口中完成,它们也必须被标识为public性质,并符合事件接口中的定义。

  在接口名字之前,每个接口需要一个GUID特性。要生成变个唯一的Guid,需要运行guidgen.exe工具软件,并选择注册表格式 下面是一个类界面:

  

[Guid(";694C1820-04B6-4988-928F-FD858B95C880";)]public interface DBCOM_Interface{[DispId(1)]void Init(string userid , string password);[DispId(2)]bool ExecuteSelectCommand(string selCommand);[DispId(3)]bool NextRow();[DispId(4)]void ExecuteNonSelectCommand(string insCommand);[DispId(5)]string GetColumnData(int pos);} 

  COM事件接口:

// 事件接口Database_COMObjectEvents[Guid(";47C976E0-C208-4740-AC42-41212D3C34F0";),InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]public interface DBCOM_Events{} 

  下面是实际的类定义:

  

[Guid(";9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E";),ClassInterface(ClassInterfaceType.None),ComSourceInterfaces(typeof(DBCOM_Events))]public class DBCOM_Class : DBCOM_Interface{ 

  需要注意的是,在类的前面,需要设置下面的特性:

  

ClassInterface(ClassInterfaceType.None),ComSourceInterfaces(typeof(DBCOM_Events))] 

  ClassInterfaceType.None表示没有为该类生成类接口,如果没有明确地实现接口,类只能通过IDispatch提供后期绑定访问。用户希望通过明确地由类实现的接口使外部对象能够访问类的功能,这也是推荐的ClassInterfaceAttribute的设置。

  ComSourceInterfaces(typeof(DBCOM_Events))]确定许多作为COM事件向外部对象提供的接口。在本文的例子中,我们不对外部对象开放任何事件。

  下面是COM对象完整的源代码:

  

using System;using System.Runtime.InteropServices;using System.IO;using System.Text;using System.Data.SqlClient;using System.Windows.Forms ;namespace Database_COMObject{[Guid(";694C1820-04B6-4988-928F-FD858B95C880";)]public interface DBCOM_Interface{[DispId(1)]void Init(string userid , string password);[DispId(2)]bool ExecuteSelectCommand(string selCommand);[DispId(3)]bool NextRow();[DispId(4)]void ExecuteNonSelectCommand(string insCommand);[DispId(5)]string GetColumnData(int pos);}// 事件接口Database_COMObjectEvents[Guid(";47C976E0-C208-4740-AC42-41212D3C34F0";),InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]public interface DBCOM_Events{}[Guid(";9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E";),ClassInterface(ClassInterfaceType.None),ComSourceInterfaces(typeof(DBCOM_Events))]public class DBCOM_Class : DBCOM_Interface{private SqlConnection myConnection = null ;SqlDataReader myReader = null ;public DBCOM_Class(){}public void Init(string userid , string password){try{string myConnectString = ";user id=";+userid+";;password=";+password+";;Database=NorthWind;Server=SKYWALKER;Connect Timeout=30";;myConnection = new SqlConnection(myConnectString);myConnection.Open();MessageBox.Show(";CONNECTED";);}catch(Exception e){MessageBox.Show(e.Message);}}public bool ExecuteSelectCommand(string selCommand){if ( myReader != null )myReader.Close() ;SqlCommand myCommand = new SqlCommand(selCommand);myCommand.Connection = myConnection;myCommand.ExecuteNonQuery();myReader = myCommand.ExecuteReader();return true ;}public bool NextRow(){if ( ! myReader.Read() ){myReader.Close();return false ;}return true ;}public string GetColumnData(int pos){Object obj = myReader.GetValue(pos);if ( obj == null ) return ";"; ;return obj.ToString() ;}public void ExecuteNonSelectCommand(string insCommand){SqlCommand myCommand = new SqlCommand(insCommand , myConnection);int retRows = myCommand.ExecuteNonQuery();}}} 

  在创建COM对象前,我们必须向COM Interop注册该对象。右击方案管理器中的工程名字,点击快捷菜单上的属性选项,然后再点击配置->;创建,扩展output小节,将Register for COM Interop选项的值设置为true。这样,一个COM对象就能够与可管理性应用程序进行交互。

  为了使COM对象能够被外部对象调用,类库组合必须有一个强名字。创建强名字需要用到SN.EXE名字:

sn -k Database_COM_Key.snk打开AssemblyInfo.cs,并修改下面一行的内容:[assembly: AssemblyKeyFile(";Database_COM_Key.snk";)] 

  创建对象。创建对象会生成一个可以被导入到可管理性或非可管理性代码中的类库。

  第二部分:使用Visual C++创建访问COM对象的客户端软件

  使用VC++开发环境创建一个简单的工程。

  使用#import directive导入类型库。

  在界面中创建一个Smart Pointer,从接口中执行COM类提供的功能。确保在应用程序加载时添加CoInitialize()调用:

CoInitialize(NULL);Database_COMObject::DBCOM_InterfacePtr p(__uuidof(Database_COMObject::DBCOM_Class));db_com_ptr = p ;db_com_ptr->;Init(";scott"; , ";tiger";); 

  下面的代码对Customers数据库表执行一个SQL命令,返回给定ID的客户的信息:

char cmd[1024];sprintf(cmd , ";SELECT COMPANYNAME , CONTACTNAME ,CONTACTTITLE , ADDRESS FROM CUSTOMERS WHERE CUSTOMERID = '%s'"; , m_id );const char *p ;bool ret = db_com_ptr->;ExecuteSelectCommand(cmd);if ( ! db_com_ptr->;NextRow() ) return ;_bstr_t mData = db_com_ptr->;GetColumnData(3);p = mData ;m_address = (CString)p ;

来源:http://www.tulaoshi.com/n/20160219/1613701.html

延伸阅读
.NET技术是微软大力推广的下一代平台技术,自从.NET技术架构的正式发布,此项技术也逐渐走向成熟和稳定。按照微软的平台系统占有率,我们不难想象得到,在未来的一两年内.NET技术必定会势如破竹一般的登上主流的技术平台,而一个新的技术平台得以快速发展的最重要的前提是:他不会彻底的摒弃以前的技术,这一点对于.NET技术来说指的就是COM...
如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类。 我们可以把Mutex看作一个出租车,乘客看作线程。乘客首先等车,然后上车,最后下车。当一个乘客在车上时,其他乘客就只有等他下车以后才可以上车。而线程与Mutex对象的关系也正是如此,线程使用Mutex.WaitOne()方法等...
   持久对象 (persistent objects)广泛应用于游戏、分布式数据库系统、多媒体以及图形应用程序中。目前C++并不直接支持持久性(persistence)(但有一些在C++未来版本中添加持久性和反射(reflection)的建议)。 !-- frame contents -- !-- /frame contents -- 持久对象可以在创建它的程序的作用域之外保持自身状态。...
开发基于.Net平台上的程序员是很难从本质上把Visual C#和ActiveX组件联起来,虽然在使用Visual C#开发应用程序时,有时为了快速开发或者由于.Net FrameWork SDK的不完整,还需要借助ActiveX。但即使如此,也很难把二者联系起来。其中的原因就是能够被Visual C#直接使用文件和通过Visual C#生成的可执行程序只可能是托管的文件。而Active X...
在编写多线程程序时无可避免会碰到线程的同步问题。什么是线程的同步呢? 举个例子:假如在一个公司里面有一个变量记录某人T的工资count=100,有两个主管A和B(即工作线程)在早一些时候拿了这个变量的值回去 ,过了一段时间A主管将T的工资加了5块,并存回count变量,而B主管将T的工资减去3块,并存回count变量。好了,本来T君可以得到102块...

经验教程

23

收藏

64
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部