来新公司学习接手新项目,拿到代码打开解决方案看到里面竟然有40几个工程,有点吃惊。具体看代码也有很多之前没见过的写法,上了几天火。

有件事就没太搞明白,按照文档的说法上层很多软件都要调用IO服务器,但看程序安装目录,IO服务器其实是一个exe程序,按照我之前的印象,能被别的程序调用的也得是动态库、静态库或者服务。实在想不通exe程序怎么作为接口被别的程序调用的。

结果昨天研究了一天,想通了,这个IO服务器其实就是COM组件。

按照网上的说法:COM component(COM组件)是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术。在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应用系统。由此带来的好处是多方面的:可以将系统中的组件用新的替换掉,以便随时进行系统的升级和定制;可以在多个应用系统中重复利用同一个组件;可以方便的将应用系统扩展到网络环境下;COM与语言,平台无关的特性使所有的程序员均可充分发挥自己的才智与专长编写组件模块。

COM组件可以是dll或者exe或者服务的形式。

按照这个思路,代码就看懂了不少,之所以解决方案里有那么多工程,也不过是因为划分了很多动态库和COM组件。

又花了些时间,写了个小程序来实现最简单的exe形式COM组件的生成与调用,如下:

首先建立一个ALT工程:

在类视图里,为工程添加ALT的类,和接口:

这里定义了类,和对应的接口(Interface),注意ProgID要写,待会程序调用com接口时,要通过ProgID找com组件

之后项目目录如下,在.idl文件里有com接口(interface),里面还定义了com组件的id等等不赘述了,实现类在ATLTest.cpp里,其对应关系都是vs自动搭建的。

接下来还是在类视图里具体添加方法(接口和实现):

方法内部写程序,逻辑是两数求和:

STDMETHODIMP CCATLTest::ATLTestFunc0(SHORT num1, SHORT num2, SCODE* pRetNum)
{
*pRetNum = num1 + num2;
return S_OK;
}

然后编译会出错,那是因为执行com组件注册命令时候,缺乏管理员权限,

重新启动vs,以管理员权限运行即可。

接下来建一个mfc项目,这不是今天主题就不赘述了,

在界面上简单填个按钮和输入框,写个两数求和的图形界面demo,

具体的求和的方法要调用com组件。

mfc项目里添加com接口,在类向导里选择添加类,选atl,选TypeLib中的MFC类:

之后可以选取前面定义的Lib:

加入COM接口文件后,就可以调用了,注意我下面的写法:

void CATLMfcClientDlg::OnBnClickedGetRetButton()
{
CoInitialize(NULL);
CATLTest myCom;
if (!myCom.CreateDispatch(_T("ATLTest.math.1")))
{
MessageBox(L"组件注册失败");
return;
}
CString strNum1,strNum2;
// 获取用户输入的数字
this->numInput1.GetWindowTextW(strNum1);
this->numInput2.GetWindowTextW(strNum2);
// 调用COM接口,两数求和
short ret = myCom.ATLTestFunc0(_wtoi(strNum1),_wtoi(strNum2));
WCHAR buf[];
_itow(ret,buf,);
// 显示结果
this->numRet.SetWindowTextW(buf);
CoUninitialize();
return;
}

运行效果:

上面有说的简略的地方,具体可以看我上传git的源码:

https://github.com/SonnAdolf/MyAtlExeComDemo

额外内容:

动态链接库和COM组件的区别

1动态链接库的表现形式只能是dll[变态该名的除外], COM组件的表现形式可以是dll也可以是exe。

     注:其实字体、驱动等也算是动态链接库的一种,这里略去...

2 动态链接库的生成和编译器及系统相关,在Windows/Linux下系统,需要分别编译才能使用。

COM组件是二进制编码,在Windows和Linux下可以直接使用,不需要重新编译。

3 COM组件是按照COM规范实现的dll或者exe;动态链接库是一个可以导出函数的函数集合。

4 动态链接库只能在本机被调用,COM组件支持分布式使用。

创建最简单的exe形式COM组件并在MFC程序调用的更多相关文章

  1. IOS开发之小实例--创建一个简单的用于视频录制和回放的应用程序

    前言:还是看了一下国外的入门IOS文章:<Create a Simple App for Video Recording and Playback>,主要涉及视频录制和回放的功能的基本实现 ...

  2. C#调用Exe文件的方法及如何判断程序调用的exe已结束

    很简单的代码就可以实现C#调用EXE文件,如下: 引入using System.Diagnostics; 调用代码: Process.Start(exe文件名); 或直接 System.Diagnos ...

  3. WCF服务二:创建一个简单的WCF服务程序

    在本例中,我们将实现一个简单的计算服务,提供基本的加.减.乘.除运算,通过客户端和服务端运行在同一台机器上的不同进程实现. 一.新建WCF服务 1.新建一个空白解决方案,解决方案名称为"WC ...

  4. IntelliJ IDEA 15 部署Tomcat及创建一个简单的Web工程

    一.部署Tomcat 二.创建一个简单的Web工程 2.1创建一个新工程 创建一个新工程 设置JDK及选择Web Application (创建的是Web工程) 点击Next,选择工作空间,起个工程名 ...

  5. 如何创建一个简单的struts2程序

    如何创建一个简单的Struts2程序 “计应134(实验班) 凌豪” 1.创建一个新的Web项目test(File->new->Web Project) 2.Struts2框架的核心配置文 ...

  6. WCF入门, 到创建一个简单的WCF应用程序

    什么是WCF?  WCF, 英文全称(windows Communication Foundation) , 即为windows通讯平台. windows想到这里大家都知道了 , WCF也正是由微软公 ...

  7. Java多线程的创建与简单使用

    一.线程的基本概念 什么是线程:Thread 进程内部的一个执行单元,它是程序中一个单一的顺序控制流程. 线程又被称为轻量级进程(lightweight process) 如果在一个进程中同时运行了多 ...

  8. Python框架学习之用Flask创建一个简单项目

    在前面一篇讲了如何创建一个虚拟环境,今天这一篇就来说说如何创建一个简单的Flask项目.关于Flask的具体介绍就不详细叙述了,我们只要知道它非常简洁.灵活和扩展性强就够了.它不像Django那样集成 ...

  9. 使用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(二)(代码篇)

    这篇是上一篇的延续: 用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(一) 源代码在github上可以下载,地址:https://github.com/guoxia ...

随机推荐

  1. java之Arrays.asList

    使用Arrays.asList()的原因无非是想将数组或一些元素转为集合,而你得到的集合并不一定是你想要的那个集合. 而一开始asList的设计时用于打印数组而设计的,但jdk1.5开始,有了另一个比 ...

  2. Java虚拟机学习笔记(三)--- 生存还是死亡

    即便是可达性分析中不可达的对象,也不代表该对象一定被回收,一个对象被“宣判死刑”需要经过两次标记,第一次是被可达性算法标记为不可用,然后进入第二次筛选,筛选条件是对象是否有必要执行finalize() ...

  3. Linux文件及目录管理

    1.Linux文件目录树 /:根目录,linux文件系统的最顶端和入口 bin:存放用户二进制文件(如:ls,cd,mv等),实则/user/bin的硬链接(相当于Windows系统的快捷方式) bo ...

  4. 世纪龙校招java开发一、二面 面经

    头一天做的笔试,涉及到计组基本知识,还有几道智力题.java部分很简单(真的很简单有点基础就划过了) 第二天收简历 在隔壁教室等 叫到你 你就去面试 一面:先自我介绍 1 == 和 equals区别( ...

  5. R语言中如何找出在两个数据框中完全相同的行(How to find common rows between two dataframe in R?)

    I would like to make a new data frame which only includes common rows of two separate data.frame. ex ...

  6. React 多副本问题

    Element ref was specified as a string (MySider) but no owner was set. This could happen for one of t ...

  7. 构建docker虚拟化平台

    安装epel-release扩展包 yum install epel-release -y 安装docker yum install docker-ce 启动docker systemctl star ...

  8. linux_密钥

    使用密钥文件.       这里假设主机A(192.168.100.3)用来获到主机B(192.168.100.4)的文件.   在主机A上执行如下命令来生成配对密钥: ssh-keygen -t r ...

  9. 三行脚本让 asp.net core 附加进程调试不再头痛

    在将项目升级到 asp.net core 2.2 后,很少使用 IIS Express 运行项目了,基本都是控制台运行或者写个脚本批量启动要运行的接口(多个输出项目),一直以为是我机器的 bug 关于 ...

  10. k8s西游记 - 切换网络插件IP池

    前言 最近在另一个k8s集群中,搭建了kong网关,在配置OIDC插件时,希望使用Memcahe代替Cookie来存储会话信息,于是把部署在同一局域网Memcahe的内网IP,比如:192.168.1 ...