e股脑电脑教程网
  • 首 页
  • 操作系统
  • 应用软件
  • 下载工具
  • 影音视频
  • 办公软件
  • 媒体制作
  • 网站建设
  • 平面设计
  • 数据库
  • 程序开发
  • 视频教程
编辑推荐: | 文章搜索:
您现在的位置: e股脑 >> 程序开发 >> ASP.net教程 >> 用托管C++编写Windows服务 >> 教程正文
 
教程搜索
 
 
相关教程
  • C++/CLI实战——HELLO
  • VC编写简单的序列号(SN)填
  • Visual Studio 2005体验泛
  • C++/CLI基本数据类型探索
  • 用托管C++编写Windows服务
  • Visual C++ 2005图像编程
  • Visual C++ 2005图像编程
  • Visual C++ 2005图像编程
  • 把其他C/C++编译器集成到
  • VC.NET实现清爽便利的Win
  • C++:最强大的.NET语言之
  • C++:最强大的.NET语言之
  • C++:最强大的.NET语言之
  • C++:最强大的.NET语言之
  • Visual C++2005中开发自定
  • C++/CLI程序进程之间的通
 
 
赞 助 商
 
 
用托管C++编写Windows服务
  • 来源:e股脑
  • 点击次数:
  • 更新时间:2007-8-9

多年以来,只要提到编写Windows服务,就会想到用Visual C++编写,同时,这也是其中一件C++程序员可以做,而VB程序员不可以做的事情。以前,我们只称其为"服务"或"NT服务",现在,它们被命名为"Windows服务",而且用VB.NET或C#也可以很容易地编写。

但是,如果你想用托管C++来编写呢?毕竟,大多数有经验的Visual C++程序员都会写过一两个服务,也会知道怎样完成一个类似的工程。假设你有一个必须要一直运行以提供服务的程序,且连接着一些远程电脑,如果不想编写一本使用手册,告诉客户要记得在每次重启电脑之后重新运行此程序,你就应该使它成为一个服务;又假设你有一个用于删除过期数据库记录的便利维护工具,如果不想让管理员每周都亲手运行它一次,你就应该使它成为一个服务。看起来挺吸引人的,那就让我们开始吧。

创建服务工程

以下要做的事情非常简单:打开Visual Studio.NET,创建一个新的工程,在Visual C++工程下,选择Windows服务(.NET)。接下来,为这个服务取一个方便在电脑的服务列表中查找到的名字,在此为CGNotifier。向导会创建一个继承自System::ServiceProcess::ServiceBase的类并打开设计视图,在此,你可放入一个计时器、一个数据库连接,或其他不可见的组件。

让我们转到代码视图中看一下生成的代码,在此有一个构造函数与一个Dispose方法,这两个你都可以忽略,还有一对重载的方法:OnStart()和OnStop)。在OnStart()中,可编写服务所需的代码。服务中一个重要的范畴是使用"事件引发对象",例如System::IO::FileSystemWatcher的一个实例,一般可在OnStart()中创建这些对象,在本例中,你可为类加入事件方法,并处理在服务运行期间,由这些对象引发的事件。另有一种服务,它们对发生的事情不作反应,只在每天或每周的特定时间,执行一些特定的任务,这些服务平时通常处于休眠状态,但因为它们的工作状态是持续的,所以不应该停止它们,或者可以把它们放入一个循环中,在特定的时间检查它们是否已被停止。

OnStart()方法是服务的开始之处,并且会在执行完后返回,在此方法完成之前,服务一般不会显示为"已启动"。这就意味着,不能在OnStart()中放入一个经常使用的循环,或从别处直接调用的任何方法。最直接的方法是设置好一个单独的方法,并在一个新线程中调用它,如下所示:

private:

bool stopping;

int loopsleep; //毫秒

Threading::Thread* servicethread;

protected:

//设置好服务应做的工作

void OnStart(String* args[])

{

Threading::ThreadStart* threadStart =new Threading::ThreadStart(this,mainLoop);

servicethread = new Threading::Thread(threadStart);


servicethread->Start();

}

void mainLoop()

{

loopsleep = 1000; //毫秒

stopping = false;

while (!stopping)

{

Threading::Thread::Sleep(loopsleep);

}

}

这个循环将会一直运行,直到服务停止,因为OnStop()设置了停止标志:

void OnStop()

{

stopping = true;

}

如果你增加loopsleep值,则会在停止时,增加服务的响应时间。

安装服务

尽管这个服务什么也不做,但你仍可对它进行安装、启动和停止。为简化安装过程,可在工程中加入一个安装程序,这可在设计视图中完成(如果你喜欢,可在设计视图中打开属性窗口,并修改ServiceName属性;而向导会在工程名后加上WinService,这最好在添加安装程序之前完成,否则,就需要在多处修改服务名。),鼠标右键单击设计视图,选择添加安装程序。这将创建一个服务安装程序和一个服务过程安装程序,并显示在设计视图中,以供你设置它们的属性。

如果已经阅读了有关Windows服务的 .NET文档,你可能会想为什么要添加一个安装程序呢?难道不可以自动添加吗?实际上,如果是使用VB或C#,是可以自动添加的,而C++却不行。

服务过程安装程序只有一个比较让人感兴趣的属性:服务所运行的账户。单击serviceProcessInstaller1选择它,打开其属性窗口。默认情况下,账户属性为User,这意味着在安装服务时,将会提示输入一个ID和密码,而且服务将会运行于user权限下--这在服务运行于system账户时非常有用。通常有三个选项:LocalSystem是服务被安装于未运行Windows 2003的电脑上时的唯一选择;如果服务是面向Windows 2003的,那么LocalService的权限更少,因为是更好的选择;而NetworkService允许服务验证另一台电脑,所以只在需要使用它(例如,一个服务加载了一个web页),相反,在使用公共web服务时,就不需要作为NetworkService运行,因为它不需验证远程电脑。

而服务安装程序中需要注意的属性是StartType:手动、自动、禁用。在此例中为手动。

现在,可以生成服务,并准备安装了。打开Visual Studio命令提示符,定位到工程的Debug文件夹,输入以下命令:

InstallUtil CGNotifier.exe

以下是屏幕的输出:

Microsoft (R) .NET Framework Installation utility

Version 1.1.4322.573

Copyright (C) Microsoft Corporation 1998-2002.

All rights reserved.

Exception occurred while initializing the installation:


System.IO.FileLoadException: Unverifiable image 'CGNotifier.exe'

cannot be run.

这真是难以理解,不是吗?在C++中编写可验证代码向来都是不可能的,且非常难以实现。为什么工程向导创建了一个服务,但却没有提示你代码必须为可验证的呢?其实不必使你的服务程序产生可验证代码。

打开解决方案资源管理器,找到并打开相应的 .cpp文件,你将会发现隐藏在此的一个main()函数--正是这个main()函数以一种"聪明"的方式为你调用了InstallUtil,并产生了整个的"可验证代码"问题。现在回到命令提示符窗口,像以下这样安装服务:

CGNotifier.exe -Install

你可看到服务轻松、流畅地安装上去了。

为进行测试,现在打开"计算机管理",并展开"服务和应用程序"项,选择"服务",你可看到新安装上去的服务:右键单击它选择启动。一旦服务启动,切换回Visual Studio,选择服务器资源管理器查看此服务:依次选择视图、服务器资源管理器,展开你的计算机名,再展开服务,你将看到一个新服务,而带有的绿色三角形表明它正在运行。

在服务器资源管理器中右击此服务,选择停止。现在,请在"事件查看器"中查看事件记录,可看到二个日志记录:一个告诉你服务已启动,而另一个告诉你服务已停止。如果你不想产生事件日志记录,请在服务的设计视图中修改AutoLog属性为False。

卸载服务

如果你从Debug目录中安装此服务,在对它进行修改期间,并不需要卸载,把它停止,重新生成,再启动就行了。但是,如果你想卸载它,请回到Visual Studio命令提示符窗口,定位到Debug目录,输入以下命令:

CGNotifier.exe -Install /u

现在,服务就会从"服务器资源管理器"和"计算机管理"的服务列表中消失了,也许,需要刷新列表才能看到变化。

唤醒后做一些事情

当然,以上所示的服务到目前为止并不能做任何事情,为把它变成一个"在设定时刻唤醒"的服务,第一步应在工程中加入一个配置文件,示例如下:

<configuration>

<appSettings>

<add key="runhour" value="22" />

</appSettings>

</configuration>

另外,还需要复制带应用程序名如app.config文件到目标工程目录(Debug或Release):

copy app.config $(ConfigurationName)\$(TargetFileName).config

为了读取配置,可在OnStart()或mainLoop()中循环之前加入相应的代码,在此倾向于尽可能地保持OnStart()为空,因此在mainLoop()中加入以下代码:

String* sHour = Configuration::ConfigurationSettings::


AppSettings->get_Item(&quo

[1] [2] 下一页

  • 上一篇教程: Visual C++ 2005图像编程之属性设置栏
  • 下一篇教程: C++/CLI基本数据类型探索
  •  

    关于本站 | 广告联系 | 版权声明 | 使用帮助

    Copyright © 2004-2008 www.egunao.com All rights reserved.