ATL 服务程序
ATL基本使用

A TL基本使用这一部分将重点介绍ATL的基本使用过程。
由于ATL已经被集成在Microsoft Visulal Studio的Visual C++开发环境中,因此要使用A TL必须先安装Visual C++。
在下面的讨论中有关COM的基本知识请参阅有关的文档,这里不再详细说明。
给出的图是在Microsoft Windows 98平台下Visual Studio 6.0的使用示意图。
使用A TL开发一个COM应用基本可以分为以下几个步骤:创建一个新的A TL工程,并对工程的选项进行适当的配置。
向新创建的工程添加新的ATL类,并对该类进行一些初始配置工作。
根据COM应用的基本要求向新的ATL类加入新的接口定义,并实现相应的接口成员函数。
编译连接工程,注册COM应用。
下面将根据这些步骤依次介绍ATL的基本使用过程。
1. 创建工程首先启动Visual C++集成开发环境,选择“File”菜单下的“New...”命令,在“New”对话框中选择“Project”页,如图1所示。
图1 创建新工程界面示意图选择“A TL COM AppWizard”项,这是创建A TL工程的AppWizard向导入口。
然后在“Project name”编辑框中输入工程的名字,单击“OK”按钮,进入AppWizard对话框。
如图2所示。
图2 ATL COM AppWizard对话框示意图在AppWizard对话框中主要的设置选项有:COM服务程序的类型:- 动态连接库(Dynamic Linking Library)最终产生一个动态连接库(DLL)形式的COM服务程序;- 应用程序(Executable application)最终产生一个可执行程序类型(EXE)的COM服务程序;- NT服务(NT Service):产生一个以NT服务方式运行的COM服务程序。
允许嵌入Proxy/Stub代码。
由Microsoft提供的MIDL编译IDL文件以后,将产生用于对象调度(Marshaling)的Proxy/Stub的代码。
CC++STL ATL WTL之间的联系和区别

【C/C++】STL,ATL,WTL之间的联系和区别STL即 Standard Template Library (标准模板库)STL是惠普实验室开发的一系列软件的统称。
它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。
现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。
STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map 等,STL也是算法和其他一些组件的集合。
这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。
STL的目的是标准化组件,这样你就不用重新开发它们了。
你可以仅仅使用这些现成的组件。
STL现在是C++的一部分,因此不用额外安装什麽。
它被内建在你的编译器之内。
因为STL的list是一个简单的容器,所以我打算从它开始介绍STL如何使用。
如果你懂得了这个概念,其他的就都没有问题了。
另外,list容器是相当简单的,我们会看到这一点。
这篇文章中我们将会看到如何定义和初始化一个list,计算它的元素的数量,从一个list里查找元素,删除元素,和一些其他的操作。
要作到这些,我们将会讨论两个不同的算法,STL通用算法都是可以操作不止一个容器的,而list 的成员函数是list容器专有的操作。
STL容器可以保存对象,内建对象和类对象。
它们会安全的保存对象,并定义我们能够操作的这个对象的接口。
放在蛋架上的鸡蛋不会滚到桌上。
它们很安全。
因此,在STL容器中的对象也很安全。
我知道这个比喻听起来很老土,但是它很正确。
STL算法是标准算法,我们可以把它们应用在那些容器中的对象上。
ATL与WTL学习

第一部分 - ATL 中的 GUI 类•下载示例工程 - 45.5 KB本章内容•README.TXT•本系列介绍•第一部分介绍•ATL 背景知识o ATL 和 WTL 的历史o ATL 风格的模板•ATL 窗口类•定义窗口实现o填充消息映射•高级消息映射链和嵌入(Mix-in)类•ATL EXE 的结构o VC 6 的情形o VC 7 的情形•ATL 中的对话框•就要到 WTL 了,我保证!•修订历史README.TXT在继续或者在本文的讨论板块中发布帖子之前,我希望你能先阅读以下内容。
本系列原来是为 VC 6 用户写的,介绍 WTL 7.0 的内容。
现在 VC 8 已经出来了,我觉得也到了更新本系列来介绍VC 7.1 的时候了。
;)(不过,VC 7.1 的从 6 到 7 的自动转换工作并不是总能平滑地完成,所以 VC 7.1 的用户在试着使用示例源代码的时候可能会遭遇失败)因而,我将继续下去,持续更新本系列。
文章将更新到可以反映 WTL 7.1 的特性,并会在下载的源代码中包括 VC 7.1 的工程。
针对 VC 2005 用户的重要提示:VC 2005 的 Express 版本并不附带 ATL 或者 MFC,因此不能使用此版本编译ATL 或者 WTL 工程。
如果你在使用 VC 6,那你就需要有 Platform SDK。
没有它你将不能使用 WTL。
你可以使用Web 安装版本或者下载 CAB 文件或者是ISO 映像,然后在本地运行安装程序。
请使用工具把 SDK 的 include 以及 lib 目录加入到 VC 的搜索路径中,该工具可以在 Platform SDK 程序组中的Visual Studio Registration文件夹下找到。
即使你在用 VC 7,使用最新的 Platform SDK 仍然是一个好主意,因为你可以得到最新的头文件和库。
你需要有 WTL。
可以从微软下载版本 7。
在文章"Introduction to WTL - Part 1"以及"Easy installation of WTL"中有一些关于安装的提示。
如何用ATL编写Windows服务

如何⽤ATL编写Windows服务有时候,我们需要⾃⼰写的程序在没有⽤户登陆的情况下,只要Windows系统启动就运⾏,那我们可以把我们的程序写成⼀个Windows服务。
服务是能够为各种⽤户(包括本地⽤户和远程⽤户)所⽤的,拥有⽤户授权级进⾏管理的能⼒,并且不论⽤户是否物理的与正在运⾏该应⽤程序的计算机相连都能正常执⾏。
下⾯,先⽤VC6做⼀个简单的例⼦说明如何⽤ATL来编写Windows服务程序。
⾸先,我们新建⼀个Project。
如图⼀所⽰,选择 "ATL COM AppWizard",⼯程名为:ServiceDemo。
图⼀点击 "OK ", 出现图⼆,选择Service [EXE]。
点击 Finish。
图⼆ 完成以上的步骤,⼀个"什么也不做"的服务就完成了!编译… 打开"控制⾯板"->"管理⼯具"->"服务",嗯?我们写的服务怎么没有在服务管理器(service control manager ,简称(SCM))⾥⾯列出来呢?呵呵,被我骗了?不要着急,我们还需要做⼀些⼯作。
⾸先先⼤概介绍⼀下向导为我们⽣成的代码: 程序的进⼊点是全局函数_tWinMain, 仔细看⼀下这个函数,我们会发现当我们运⾏程序时,可以加上参数,例如: ServiceDemo/RegServer 或者 ServiceDemo -RegServer,这个是⽤来本地服务器注册(Register as Local S Register as Service erver);ServiceDemo / Service 或者 ServiceDemo -Service,这个是服务的注册(Register as Service);ServiceDemo /UnRegServer 或者 ServiceDemo -UnRegServer ,这个是服务的删除。
ATL创建一个COM服务

g Model(线程模式),我们保持默认的 Apartment Model 就好。对于"Int erface(接口)",选择“Dual”。最后,是我们不关心的"Aggregation(集合) ",点击“No”选项。我们不需要关心底下的三个选项。点击 OK 确定就可以了。
第三步:添加一个方法 如果您现在在工作区点击“类视图”选项卡, 您将看到向导已经在这里添加了一堆 东西。我们要做的第一件事就是添加一个方法。我们可以通过右键点击“IFirst_ ATL”然后选择”Add Method“轻松添加。
默认选择 (Simple Object)就是我们需要的。点击“下一步”,您将看到"ATL Object Wizard Properties("ATL Object Wizard 属性)"窗口。在“Shor t Name”中输入"First_ATL",您将看到向导会自动为您填写其他的输入栏。点 击上端的"Attributes(属性)"选项卡,将显示下列选项。第一个是 Threadin
简介
本教程的目的在于, 给读者一个关于使用 ATL 创建一个 COM 服务的方法的初步印 象,并且让读者在使用 VC++或者 VB 编程的时候,学会调用这个服务。本教程仅 仅是为了 VC++程序员中的初学者设计,因此笔者不打算深入介绍 COM 的细节, 也不打算增加您学习 IDL 之类的负担。笔者希望展示的是使用 ATL 创建一个“简 单”COM“对象方法简单易用,并且希望因此能让初学者对此感兴趣而深入学习。
第四步:编译 DLL
你相信么,现在已经我们已经用 ATL 建立好一个可以执行的 COM 服务了!当 然,还要编译一下。在 VC++的环境中按 F7 就可以了。编译器会“吱嘎吱嘎” 一会儿——计算机在注册你的 DLL,以便让其他程序可以使用。接下来,我们 试一下。
深入学习ATL

深入解析ATL(第二版ATL8.0)(1.11-1.13节)1.11 容纳控件1.11.1容纳控件利用 ATL 所支持的控件容纳,可实现容纳控件。
比如, CAxDialogImpl 中的Ax 两字就表示 ActiveX 控件,表示对话框具有容纳控件的能力。
在对话框中实现容纳控件,只需在对话框资源上点击右键,从弹出菜单选择 Insert ActiveX Control ,然后弹出一个对话框,列举了系统安装的所有控件,如图 1-17 所示。
图 1-17 插入 ActiveX 控件对话框插入控件后,点击控件可以在控件的属性窗口设置控件的属性。
如图 1-18 所示。
图 1-18 控件属性对话框在属性对话框的工具栏上点击控件事件按钮,还可以选择处理控件的事件,如图 1-19 所示。
图 1-19 选择处理的控件事件容纳对话框运行显示时,控件被创建,同时根据开发阶段设置的属性初始化控件。
图 1-20 显示了容纳了一个控件的对话框。
图 1-20 容纳 COM 控件的对话框ATL 不但提供了对话框的容纳控件功能,其他窗口也同样支持:声明为对话框资源的 UI 控件(称为复合控件);声明为 HTML 资源的 UI 控件(称为 HTML 控件)。
关于控件容器的更多信息请参考第十二章“控件容器”。
1.11.2 C++ COM 客户端至少在理论上, COM 与 C++ 是一致的。
一个 COM 接口直接映射为一个 C++ 的抽象类。
使用 COM 对象,仅仅需要使用 MIDL 编译器运行 IDL 文件,就可以生成一个头文件,里面包含有所有需要的信息。
所有的这一切都运行正常,直到 VB 团队询问他们也是否可以使用 COM 技术。
VB 开发人员通常不知道,也不想知道 C++ 语言。
IDL 也是一个与 C++ 传统语言相似的语言,其中也支持许多 C/C++ 的特性(比如数组和指针)。
VB 需要一种方法来存储这些 COM 对象的类型信息,以方便 VB 开发人员使用和理解它们。
COM原理及代码实例

原理基本概念介绍1.什么是COM(Component Object Modal)COM(Component Object Modal)是Microsoft组件对象模型的简称。
是一个说明如何建立可动态交替更新组件的规范。
简单地说,COM是一种跨应用和语言共享二进制代码的方法。
与C++不同,它提倡源代码重用。
A TL便是一个很好的例证。
源码级重用虽然好,但只能用于C++。
它还带来了名字冲突的可能性,更不用说不断拷贝重用代码而导致工程膨胀和臃肿。
2 .COM组件COM组件是由以Win32动态链接库(DLL)或可执行文件(EXE)发布的代码所组成。
3.为什么要学习COM传统的软件开发模式:传统的软件应用程序发布以后,使用者想得到更完善的软件或者去掉其中的某些内容,只有等软件提供商发布新的版本以后,使用者的这一梦想才能得以实现。
使用COM组件以后:软件开发人员可以在软件版本发布以后修改或者去掉软件某个不需要部分。
也及应用程序在更高的层次上定制,使得软件更具灵活性、动态性。
是未来应用软件开发的趋势。
4.COM的前身是OLE(Object Linking and Embedding)对象链接与嵌入。
5.组件:如积木一样,具有“块”的概念,可以动态的将他们插入或卸出应用程序。
这就需要两个条件:第一,组件必须动态链接(不因自己的位置改变而改变自身形式);第二,组件必须隐藏内部实现细节(独立与具体编程语言,二进制形式发布)。
每个组件相当于一个黑盒子,对外提供的只是接口(函数)。
如果接口没有发生任何变化时,对组件的修改几乎不会影响应用程序的其它部分。
提供服务的组件称为服务器组件,使用服务的组件称为客户组件。
1.2.完整的COM组件的接口实现实例#include <iostream>#include <objbase.h>using namespace std;void trace(const char * pMsg){cout<<pMsg<<endl;}// 抽象接口1interface InteX{virtual void _stdcall Fx1() = 0;virtual void _stdcall Fx2() = 0;};// 抽象接口2interface InteY{virtual void _stdcall Fy1() = 0;virtual void _stdcall Fy2() = 0;};// 抽象接口实现class CompA:public InteX,public InteY {public://实现接口InteXvirtual void _stdcall Fx1(){cout<<"CompA::Fx1"<<endl;}virtual void _stdcall Fx2(){cout<<"CompA::Fx2"<<endl;}//实现接口InteYvirtual void _stdcall Fy1(){cout<<"CompA::Fy1"<<endl;}virtual void _stdcall Fy2(){cout<<"CompA::Fy2"<<endl;}};// 客户程序int main(){trace("客户:创建组件的一个实例。
使用ATL创建COM组件

ATL COM 工程的产物
ATL COM AppWizrd 最终产生了什么?
下面的表格描述了一切:
文件
描述
.CPP
包含有进程内组件需要的 5 个导出函数
.DEF
.IDL
.RC Resource.h StdAfx.cpp StdAfx.h
DllMain,DllGetClassObjecDllRegisterServer,DllUnre gisterServer, DllCanUnloadNow。对于进程外组件则 实现了 WinMain()函数。 包含有 DLL 到处函数列表,这个文件只有在进程 内组件的工程中才有。 包含有描述接口的接口定义语言,这个文件需要使 用微软的 MIDL 编译器进行编译。 含有工程的资源信息。 资源文件的头文件。 包含有 StdAfx.h 和 Atlimpl.cpp 含有 ATL 需要的头文件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1. 新建项目。
1-1. 启动Visual Studio 2008。
选择File -> New -> Project...。
1-2. 在New Project 对话框中,选择Visual C++ 中的ATL Project 模板,写入项目名称:ShowjiSvc,点OK。
1-3. 在打开的ATL Project Wizard - ShowjiSvc 中,点Application Settings,选择Server type 为Service(EXE),点Finish。
2. 安装、卸载服务。
2-1. 编译项目。
2-2. 打开命令提示符,切换到编译后的目录,执行以下命令安装服务:ShowjiSvc /Service2-3. 打开服务管理,能找到一个名为ShowjiSvc 的服务,启动类型是Manual。
可以启动服务、停止服务。
2-4. 停止服务,然后用以下命令卸载服务:ShowjiSvc /UnRegServer3. 修改服务的配置。
3-1. 修改服务名称:在Resource View 中打开String Table,修改IDS_SERVICENAME 的Caption 为服务的名称:Showji Mobile Service。
3-2. 修改服务的描述:打开ShowjiSvc.cpp 文件,在CShowjiSvcModule 的声明中增加以下函数声明:HRESULT RegisterAppId(bool bService);再增加此函数的定义:HRESULT CShowjiSvcModule::RegisterAppId(bool bService = false) throw(){HRESULT hr = S_OK;BOOL res = __super::RegisterAppId(bService);if (bService){if (IsInstalled()){SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SERVICE_CHANGE_CONFIG);SC_HANDLE hService = NULL;if (hSCM == NULL)hr = AtlHresultFromLastError();else{hService = ::OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG);if (hService != NULL){::ChangeServiceConfig(hService, SERVICE_NO_CHANGE,SERVICE_AUTO_START,// 修改服务为自动启动NULL, NULL, NULL, NULL, NULL, NULL, NULL,m_szServiceName); // 通过修改资源IDS_SERVICENAME 修改服务的显示名字SERVICE_DESCRIPTION Description;TCHAR szDescription[1024];ZeroMemory(szDescription, 1024);ZeroMemory(&Description, sizeof(SERVICE_DESCRIPTION));lstrcpy(szDescription, _T("示例服务,by yangwei@"));Description.lpDescription = szDescription;::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION,&Description);::CloseServiceHandle(hService);}elsehr = AtlHresultFromLastError();::CloseServiceHandle(hSCM);}}}return hr;}3-3. 测试修改后的服务。
重新注册服务,在服务管理器中可以看到服务的新名称和描述,并且启动状态已经修改为Automatic。
测试成功后,注销服务。
4. 修改服务的进程安全设置。
打开ShowjiSvc.cpp,在CShowjiSvcModule 的声明中,找到InitializeSecurity 函数,修改如下:HRESULT InitializeSecurity() throw(){return CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE,RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL );}要根据自己的情况,做相关的安全性设置。
如果没有什么特殊的安全性要求,就按照上面的格式写就行了。
如果没有设置进程安全性的代码,那么VC 客户端创建对象的时候,会返回E_ACCESSDENIED 的错误。
VB 客户端的错误提示如下:实时错误'70': 拒绝的权限(Run-time error '70': Permission denied)。
5. 增加服务的初始化和释放操作。
打开ShowjiSvc.cpp,在CShowjiSvcModule 的声明中,增加以下声明:HRESULT PreMessageLoop(int nShowCmd);HRESULT PostMessageLoop();增加以上声明的相关定义:HRESULT CShowjiSvcModule::PreMessageLoop(int nShowCmd) throw() {HRESULT hr = __super::PreMessageLoop(nShowCmd);if (SUCCEEDED(hr)){// Add any custom code to initialize your service}return hr;}HRESULT CShowjiSvcModule::PostMessageLoop() throw(){HRESULT hr = __super::PostMessageLoop();if (SUCCEEDED(hr)){// Add any custom code to uninitialize your service}return hr;}在相关的描述位置增加自己的代码即可。
6. 为服务增加一个叫做MyMath 的示例组件。
6-1. 选中ShowjiSvc 项目,点菜单Project -> Add Class...,选择ATL 中的ATL Simple Object,点Add。
6-2. 在打开的ATL Simple Object Wizard - ShowjiSvc 对话框的Short name 中写入组件名称:MyMath。
其它名称会自动填好(当然您也可以修改)。
6-3. 在Option 中可以看到许多选项。
如果您搞不懂这些,就保留默认值吧(建议看一下COM 的相关书籍)。
6-4. 打开MyMath.rgs,为组件增加服务程序的ID(代码中的红色粗体部分):HKCR{ShowjiSvc.MyMath.1 = s 'M yMath Class'{CLSID = s '{37F47E87-7D33-43CD-B591-DA01023F90BC}'}ShowjiSvc.MyMath = s 'M yMath Class'{CLSID = s '{37F47E87-7D33-43CD-B591-DA01023F90BC}'CurVer = s 'ShowjiSvc.MyMath.1'}NoRemove CLSID{ForceRemove {37F47E87-7D33-43CD-B591-DA01023F90BC} = s 'M yMath Class'{ProgID = s 'ShowjiSvc.MyMath.1'VersionIndependentProgID = s 'ShowjiSvc.MyMath'ForceRemove 'Programmable'LocalServer32 = s '%MODULE%'val AppID = s '%APPID%''TypeLib' = s '{55E58774-E86F-4482-A521-38AE8C85FD1D}'}}}AppID 必须设置,否则客户端创建对象的时候会超时并报错误:80080005 server execution failed。
并且,系统日志中会出现一个错误:The server {uuid} did not register with DCOM within the required timeout. VB 客户端的错误提示如下:实时错误'429': ActiveX 部件不能创建对象(Run-time error '429': ActiveX component can't create object)。
7. 为MyMath 组件增加一个方法。
7-1. 在Class View 中,右击IMyMath,选择Add -> Add Method...。
7-2. 在打开的Add Method Wizard - ShowjiSvc 对话框中,输入Method name: Sum;Parameter type 选择LONG,Parameter name 写a,Parameter attributes 选择in,点一下Add;Parameter type 选择LONG,Parameter name 写b,Parameter attributes 选择in,点一下Add;Parameter type 选择LONG*,Parameter name 写s,Parameter attributes 选择retval,点一下Add;点Finish 添加这个方法。
7-3. 打开MyMath.cpp 文件,找到Sum 方法,修改如下:STDMETHODIMP CMyMath::Sum(LONG a, LONG b, LONG* s){*s = a + b;return S_OK;}8. 编译、注册、启动服务。
8-1. 编译代码。
8-2. 注册服务,执行以下命令行代码:ShowjiSvc /Service8-3. 启动服务,执行以下命令行代码:net start "Showji Mobile Service"当然,也可以在服务管理器中启动服务。