当前位置: 首页 > 编程日记 > 正文

【译文转帖】用C#写COM组件 Building COM Objects in C#

说明:

我是一个C#程序员,但是有一次一个需求只能用C/C++去写,恰好需要读取的数据存放在DB(SQL CE v3)里面,而我又不会C/C++(关键是用OleDB访问DB,这个实在是繁琐),所以催生了用C#写一个COM组件,用C/C++去调用的想法.可谓,很傻很天真.但是也是一种思路,如果MS提供C API的话,问题就简单多了.可是事实是,MS自己的.NET CF用着C API,给用户却暴露着COM API.....OK,言归正传.

主要内容:

  • 用C#创建一个简单的COM组件(通过COM Interop)
  • 用VC++写一个客户端去访问COM组件.客户端用TLB文件.

本着易于使用的目的,我把Northwind导入到了SQLServer,然后测试了我的代码.(the sake of simplycity这个不知道啥意思,难道是由于出现纸尿布....).

  • 修改COM组件里面的机器名为你的SQL Server的机器名.(2005以上需要 机器名\实例名)
  • 当然我在里面也创建了一个用户scott密码是tiger,用来连接数据库.你可以选择这个用户名,或者重新建一个.

Part I: 用C#创建一个简单的COM组件

COM对象是一种类库.COM组件将产生DLL文件.在VS环境里面创建COM组件请选择....

File->New->Project->VisualC# Projects ->Class Library.

创建一个名为Database_COMObject的类库工程.

请记住:想要把C#对象当作COM对象需要以下几点...

  • class必须是public的
  • 属性,方法和事件必须是public
  • 属性和方法必须在Interface里面定义
  • 事件必须在事件的接口中

未在接口中定义的成员,而在实现里面是public的成员,对COM是不可见的,但是对其他的.NET程序是可见的.为了把属性和方法暴露给 COM,你必须在接口中定义他们,并且把他们用DispId属性标记,在class里面实现(.....).在接口里面定义的成员只是为了使用 vtable(虚函数表).要想暴露事件,你也必须把成员定义在事件接口里面并且标记DispId属性.类不需要实现此接口(???).类可以实现接口 (一个类可以实现多个接口,只有第一个接口才是默认的接口.).暴露给COM的那些属性方法其实就在类的实现里面.他们必须被标记为public,而且要符合接口里面的定义.Also, declare the events raised by the class here. They must be marked public and must match the declarations in the events interface. (这两句不知道具体的含义,代码里面也没看出端倪.)

每一个接口都要有一个GUID属性(我当时上学的时候,把他叫属性属性,或者定制属性,现在也不清楚到底叫什么..).你可以用guidgen.exe来产生一个GUID值.

这个接口就长这个样子:

    [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);}

[Guid("694C1820-04B6-4988-928F-FD858B95C880")]
publicinterfaceDBCOM_Interface
{
[DispId(1)]
voidInit(stringuserid , stringpassword);
[DispId(2)]
boolExecuteSelectCommand(stringselCommand);
[DispId(3)]
boolNextRow();
[DispId(4)]
voidExecuteNonSelectCommand(stringinsCommand);
[DispId(5)]
stringGetColumnData(intpos);
}

COM事件:

    // // Events interface 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);}// Events interface 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那里注册.

打开Solution Explorer->Properties->Configuration->Build->Expand the output section->Register for COM Interop改为True.

(我在VS 2008里面貌似不是这么操作的,工程上面点右键->属性->Build->最下面的Output->Register for COM Interop改为True).

表明,我要把Managed程序导出一个COM对象,并且COM对象可以和我们的托管程序交互.

为了(真正)导出COM对象,程序集还需要强命名,可以用sn.exe生成一个StrongName:

sn -k Database_COM_Key.snk

在AssemblyInfo.cs文件里面修改:

[assembly: AssemblyKeyFile("Database_COM_Key.snk")]

编译这个对象.会产生一个tlb文件,通过这个可以使Managed代码和Native代码都能访问你的COM对象.

Part II : 用VC++创建一个客户端去访问这个COM对象

我已经在VC++6.0和VC++.NET下面访问呢过改COM对象.

创建一个简单的工程,通过 #import directive导入type library.

创建一个只能指针指向接口的实例,执行那些导出函数,确保在程序加载的时候执行CoInitialize().

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

下面的代码通过一个Customer ID去在Customer表中查询:

    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 ;

PS:

总算翻译完了....英语不好,有一些句子不能理解含义,英语好的童鞋推荐直接看e文.

我只能说我很悲剧,当初想法很好,只可惜,.NET CF下面,不支持用C#写一个COM组件.

我的口头禅就是:.NET CF除了慢,再没有其他优点.

转载于:https://www.cnblogs.com/SuperBrothers/archive/2012/10/29/2744933.html

相关文章:

apache 开启 gzip 压缩服务

2019独角兽企业重金招聘Python工程师标准>>> 1、打开 apache 的 "httpd.conf" 文件,找到以下这一行,将它前面的注释(#)去掉: LoadModule deflate_module modules/mod_deflate.so 2、在 httpd.con…

Scratch等级考试(二级)模拟题

青少年编程竞赛交流群已成立(适合6至18周岁的青少年),公众号后台回复【Scratch】或【Python】,即可进入。如果加入了之前的社群不需要重复加入。 微信后台回复“资料下载”可获取以往学习的材料(视频、代码、文档&…

找Java培训机构有哪些评判标准

想要学习java技术,找java培训机构是大多数人的选择,目前市面上的java培训机构有很多,用什么评判标准来找到时候自己的机构呢?来看看下面小编为大家介绍的找Java培训机构有哪些评判标准? 找Java培训机构有哪些评判标准? 1.师资力量的标准 我…

Josephus问题

目的&#xff1a;练习下单链表和指针 &#xff08;OS 10.7 Xcode 4.2&#xff09; 代码如下&#xff1a; 1 #include <stdio.h>2 #include <stdlib.h>3 4 typedef struct lnode5 {6 int data;7 struct lnode *next; 8 }lnode;9 10 int main(void) 11 …

Datawhale组队学习周报(第017周)

本周&#xff08;05月31日~06月06日&#xff09;&#xff0c;第 25 期组队学习一共有 3 门开源课程&#xff0c;共组建了 3 个学习群&#xff0c;参与的学习者有 292 人&#xff0c;其中 web开发入门教程 已经结营&#xff0c;另外两门课程也在结营筹划中。 第 26 期组队学习也…

给一个ul列表中点击到的li赋予样式

2019独角兽企业重金招聘Python工程师标准>>> 效果如下&#xff0c;点那个那个获取样式,之前已经有样式的取消。 代码如下&#xff0c;我是在菜鸟教程上在线编辑的&#xff0c;所以就这样喽~ if判断不加也行 <!DOCTYPE html> <html> <head> ​ <…

参加过java培训机构的学员如何找出路

java技术在互联网行业的发展&#xff0c;引起了越来越多人的关注&#xff0c;市面上的java培训机构也不计其数&#xff0c;很多人都比较想知道参加过java培训机构的学员如何找出路?对于这个问题&#xff0c;我们来看看下面的详细介绍就知道了。 参加过java培训机构的学员如何找…

pku The Windy's KM最小权匹配 or 最小费用最大流

http://poj.org/problem?id3686 题意&#xff1a; 给定n个玩具&#xff0c;有m个车间&#xff0c;给出每个玩具在每个车间的加工所需的时间mat[i][j]表示第i个玩具在第j个车间加工所需的时间&#xff0c;规顶只有第i个玩具在j车间完成时第j车间才能接受其他玩具来生产。求加工…

react按需加载(getComponent优美写法),并指定输出模块名称解决缓存(getComponent与chunkFilename)...

react配合webpack进行按需加载的方法很简单&#xff0c;Route的component改为getComponent&#xff0c;组件用require.ensure的方式获取&#xff0c;并在webpack中配置chunkFilename。const chooseProducts (location, cb) > { require.ensure([], require > { cb(null,…

【青少年编程】【二级】绘制方形螺旋

「青少年编程竞赛交流群」已成立&#xff08;适合6至18周岁的青少年&#xff09;&#xff0c;公众号后台回复【Scratch】或【Python】&#xff0c;即可进入。如果加入了之前的社群不需要重复加入。 微信后台回复“资料下载”可获取以往学习的材料&#xff08;视频、代码、文档&…

软件测试的发展空间大吗

软件测试的发展空间大吗?很多人都非常关心这个问题&#xff0c;软件测试在互联网行业的发展空间是非常大的&#xff0c;学习软件测试技术并不难&#xff0c;只要经过系统的软件测试培训都是可以学会的&#xff0c;下面来看看详细的介绍。 软件测试的发展空间大吗 早期&#xf…

vim windows linux文件格式转换

vim windows linux文件格式转换 set ff? #显示当前文件格式set ffunix #设置成unix格式set ffdos #设置成dos格式posted on 2012-11-02 09:43 一颗卤蛋 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/lyroge/archive/2012/11/02/2750689.html

NCEPU:线下组队学习周报(009)

线下组队学习 经过一段时间的准备&#xff0c;我们组织的线下组队学习逐步进入正轨。欢迎华北电力大学保定校区的伙伴加入进来大家一起学习一起成长。 我们开展组队学习的内容为&#xff1a; &#xff08;1&#xff09;周志华的《机器学习》&#xff08;西瓜书&#xff09; …

零基础学java培训怎么选择学校

java技术在互联网行业的快速发展&#xff0c;引起了很多人的关注&#xff0c;大家都想通过学习java技术来加入到这个行业&#xff0c;那么零基础学java培训怎么选择学校呢?如今市面上的java培训机构这么多&#xff0c;下面小编就来为大家详细的介绍一下吧。 零基础学java培训怎…

C++对象的内存布局1---基础篇----C++ 虚函数表解析

[-] 前言虚函数表一般继承&#xff08;无虚函数覆盖&#xff09;一般继承&#xff08;有虚函数覆盖&#xff09;多重继承&#xff08;无虚函数覆盖&#xff09;多重继承&#xff08;有虚函数覆盖&#xff09;安全性结束语附录一&#xff1a;VC中查看虚函数表附录 二&#xff1a…

iOS开发 关于启动页和停留时间的设置

引言: 在开发一款商业App时&#xff0c;我们大都会为我们的App设置一个启动页。 苹果官方对于iOS启动页的设计说明&#xff1a; 为了增强应用程序启动时的用户体验&#xff0c;您应该提供一个启动图像。启动图像与应用程序的首屏幕看起来非常相似。 当用户在主屏幕上点击您的应…

web前端培训:CSS中单行文本溢出显示省略号的方法

CSS中单行文本溢出显示省略号的方法你知道吗?在web前端技术学习中&#xff0c;这个问题其实是属于老生常谈了&#xff0c;因为css单行文本的应用是非常频繁的&#xff0c;比如网站最基本的文章列表&#xff0c;标题会很长&#xff0c;而显示列表的区域宽度却没有这么宽&#x…

如何使用pyecharts中自带的数据集?

如何使用 pyecharts 中自带的数据集&#xff1f; 我们在学习pyehcarts绘图的过程中&#xff0c;需要一些练习的数据。 pyecharts为我们提供了这样的数据集 – Faker&#xff0c;存储于 faker.py 文件中。 下面&#xff0c;我们就来详细介绍一下。 1. Faker中包含的数据集 …

Ext.app.controller的refs

简 单来说&#xff0c;就是4.0建议的MVC中controller引用组件的一种方式&#xff0c;selector中设置组件&#xff0c;可以用id、classname&#xff0c;但推荐用 ComponentQuery&#xff08;“组件检索”功能&#xff0c;这个也是4.0的新特性&#xff09;来定位组件。ref中设置引…

MBA 工商管理课程-风险型决策方法

&#xff08;二&#xff09;风险型决策方法 适用的条件 未来情况不止一种&#xff0c;管理者不知道到底哪种情况会发生&#xff0c;但知道每种情况发生的概率 常用方法&#xff1a; 决策树法&#xff1a;用树状图来描述各种方案在…

Python培训分享:python如何用cookie实现自动模拟登录?

本期教程Python培训教程为大家带来的是python如何用cookie实现自动模拟登录?据小编的了解&#xff0c;python实现cookie自动登录&#xff0c;目前来说有许多第三方库都可以直接使用&#xff0c;这里以常用的requests库为例简单介绍一下&#xff0c;整个过程非常简单&#xff0…

如何使用pyecharts中的主题样式?

如何使用pyecharts中的主题样式&#xff1f; pyechart为用户提供了一套使用方便的主题风格。 本篇图文将总结pyecharts.globals中ThemeType所有主题风格并进行详细的解释。 class _ThemeType:BUILTIN_THEMES ["light", "dark", "white"]LIGH…

乐意使人恐惧,源于自身的空虚

有一回我对稻草人说&#xff1a;“你总是孤独守望在这片寂寞的土地上&#xff0c;你一定厌倦了吧&#xff1f;” 稻草人回答道&#xff1a;“能使他人恐惧是一种深沉持久的快乐&#xff0c;对此我永远不会感到厌倦。” 我低头沉思&#xff0c;尔后说道&#xff1a;“的确如此&a…

Maven学习(一) - Maven基础

2019独角兽企业重金招聘Python工程师标准>>> Maven作为Java语言的构建和依赖管理工具&#xff0c;已经被广泛使用。但对于maven的pom.xml的配置以及插件的使用&#xff0c;大部分人也仅仅限于了解的程度。工欲善其事&#xff0c;必先利其器。在拖延了很久后&#xf…

Python培训就业方向有哪些

关注“Python培训就业方向有哪些”的同学&#xff0c;基本都是打算学习Python技术但是对于Python的就业还是很迷茫的&#xff0c;针对在这个问题&#xff0c;小编下面为大家做下简单的解析&#xff0c;希望能够帮助到大家。 Python培训就业方向有哪些? 1.Python自动化测试 熟悉…

linux下安装hadoop

关键词&#xff1a;Ubuntu;hadoop; 注意&#xff1a;开始这一步之前&#xff0c;需安装Oracle的jdk&#xff0c;参见&#xff1a; http://www.cnblogs.com/fengfengqingqingyangyang/archive/2012/11/06/2756981.html 1、下载hadoop的合适版本&#xff1a;http://labs.mop.com/…

谢文睿:西瓜书 + 南瓜书 吃瓜系列 5. 决策树

Datawhale南瓜书是经典机器学习教材《机器学习》&#xff08;西瓜书&#xff09;的公式推导解析指南&#xff0c;旨在让在学习西瓜书的过程中&#xff0c;再也没有难推的公式&#xff0c;学好机器学习。 以往内容&#xff1a; 西瓜书公式推导讲解来了&#xff01;0. 导学1. 一…

2017还有29天,你的目标实现了吗?|内有彩蛋

点开标题的&#xff0c;都有一颗大心脏。2017 就要这么过去了&#xff0c;细思极恐啊同志们&#xff0c;年初定下的目标&#xff0c;你实现了几个&#xff1f; 如果这里是一个树洞&#xff0c;你将对着它说点什么呢&#xff1f; 如果你敢留下感想&#xff0c;我们就敢让它上墙。…

Python培训分享:Python内置标准异常及其解析

本期小编为大家带来的Python培训教程是关于“Python内置标准异常及其解析”的内容&#xff0c;我们都知道&#xff0c;在Python技术运作下&#xff0c;总会出现一些Python无法正常处理的程序时就会发生一个异常。异常是一个事件&#xff0c;此事件是在程序执行过程中发生&#…

shell 语法简介(转载)

一、基本语法1.1、shell文件开头shell文件必须以下面的行开始&#xff08;必须方在文件的第一行&#xff09;&#xff1a; #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。 当编辑好脚本时&#xff0c;如果要执行该…