Windows 服务开发平时不太受人关注,毕竟那是高大上的项目类型,平常需求也用不上,很多老掉牙的家伙也只知有WinForm,仍不知有WPF,更别说Windows 服务了,正如陶渊明所写的,“不知有汉,无论魏晋”。

通常,就算要让程序开机启动,多数也只考虑设置一个启动项,也很少去想到开发Windows服务。如果程序需要自动启动,并且希望在后台完成一些东东,其实使用Windows服务也不错的。

正因为用的人少,那么说的人更少了,使得不了解它,想学又找不到资料的人也多。没事,老周没什么资本,唯一值得骄傲就是颜值低,尤其是脸皮长得稍厚一些,所以,就让老周写几篇烂博客,看看能不能给大家解惑,传道授业愧不敢当,解几个简单的惑还是可以的。

其实,Windows服务也是一个Windows标准程序,也是编译为.exe的,运行时在任务管理器中也是有进程的,但它与一般的可执行文件也有不同,至少你不能直接双击运行服务。服务隶属于系统对象,因此在你运行服务前,需要向系统注册它。就好比你坐公交要先买票一样(包括刷卡,无人售票等),当然,个别另类人种是不买票的,后门上再从后门下。

一个服务项目可以包含多个服务,就是说你建立一个应用程序项目,你可以在里面根据你的需要,声明多个服务。实现服务的方法是从ServiceBase派生出一个自定义的类,然后重写相关的虚方法,来定义你的代码,当然,不是全部虚方法都要重写,你只写你觉得需要的方法。不要问我ServiceBase类在哪个命名空间,自己打开“对象浏览器”去找,“对象浏览器”是个好用的东西,老周每天都会看它一眼,特别好看,比你到网上下载的那些文笔拙劣的垃圾小说好看,不信你去看看。

举个地球人都知道的例子,假设你需要在服务启动时打开某个端口,去监听客户端的连接请求,那么,你可以重写OnStart方法;当服务被停止时关闭监听,重写OnStop方法;当服务被暂停时向所有客户端发送一条服务器放假的消息,请重写OnPause方法;如果你希望在关机的时候做一些处理,比如清空犯罪痕迹,可以重写OnShutdown方法,当系统即将关机,并且你的服务还在运行的时候,这个方法就会被调用。

扯的太空洞了,是吧,那就来点年货,反正也快过年了。咱们就从头到尾做一遍,看看你能不能掌握。

要上厕所的赶紧上,下面开始干活。

1、在VS中新项一个空项目,我知道VS中就有Windows服务的项目模板,但,为了让大伙伴能够更好地理解,咱们从空白开始。

2、因为项目是空的,所以里面连毛都没有,为了让项目看起来比较像样,先来设置一下项目的基本属性,估计这个很少人会注意,因为平时我们建项目时,连属性文件都由VS帮我们建好了。在项目节点上右击,选择属性。然后在应用程序页上,填好需要的东西,你可以随便填,不用客气。

注意,在输出类型那里选择“Windows应用程序”,不要选控制台应用程序,因为服务是没有界面的,就是一个进程。而且,在Win 7以上的系统中(其实是Vista时代就是了),是禁止服务和桌面交互的。我也赞成这样做,老周特别讨厌那些服务动不动就弹出个窗口,相当恶心。服务进程就是做逻辑处理的,BS有UI的服务。

3、点击“程序集信息”按钮,填上相关信息,自己喜欢填什么就填什么。

填完后确定,就会自动生成AssemblyInfo.cs文件。然后保存并关闭项目属性窗口。

4、添加下面三个引用,不用我教了。先加这么几个,等不够用时再加。

5、好,现在可以开始了,我们来做第一个服务,服务名称叫HuiJi,显示名为“灰机”.

    public class HuiJiService : ServiceBase
{
public HuiJiService()
{
ServiceName = "HuiJi";
} protected override void OnStart(string[] args)
{
Trace.WriteLine($"{this.ServiceName} - 正在起飞。");
} protected override void OnStop()
{
Trace.WriteLine($"{this.ServiceName} - 正在降落。");
}
}

由于ServiceName属性是ServiceBase类的公共属性,所以,你可以像我这样,在类的构造函数中设置,也可以不设置,等到在Main入口点中实例化HuiJiService时再赋值,公共属性在类外部可以访问。

6、好,这么个简单的服务做好了,然后我们要在Main入口点中运行它。

        static void Main()
{
SV.HuiJiService hj = new SV.HuiJiService();
// 调用静态方法运行指定服务
ServiceBase.Run(hj);
}

一定要记住,在Main中要调用Run静态方法来运行你想要运行的服务,这个很重要,不要忘了。如果只有一个服务,就只传一个服务实例给它,如果你要运行N个服务,就传一个服务数组进去。

那么,是不是这样就能运行了呢。非也,虽然我们写好了服务,但操作系统不知道你这是啥玩意儿,你得写安装程序类,这样在向系统注册时,安装工具才会去查找安装器,对服务进行安装。

7、服务需要两个(至少)安装器,一个是安装服务本身,另一个用来安装服务进程。要注意的是,服务和服务进程是不同的,服务就是我们刚刚写的从ServiceBase类派生的那个,而服务进程就是我们这个应用的.exe文件运行时的进程。

哪怕你只有一个服务,至少也有两个安装器——服务和服务进程。如果有三个服务要安装,就要定义四个安装器(三个服务安装,一个进程安装),每个服务安装器只能对应一个服务。

正因为要>=2安装器,所以要从Installer类派生出来一个类,在里面实例化好各种安装器,然后统一加入到Installers集合中,这样,在安装服务时,安装工具就会自动扫描这个集合里面的安装器,逐个进行安装。

    public class MyInstaller : Installer
{
ServiceInstaller svinstaller = null; //服务安装器
ServiceProcessInstaller processinstaller = null; //进程安装器
public MyInstaller()
{
// 实例化安装器
svinstaller = new ServiceInstaller();
// 设置的服务名称必须和自定义服务的名字相同
svinstaller.ServiceName = "HuiJi";
// 服务描述
svinstaller.Description = "23世纪触发式新型飞机。";
// 设置显示名称
svinstaller.DisplayName = "飞机";
// 启动方式为自动
svinstaller.StartType = ServiceStartMode.Automatic;
// 实例化进程安装器
processinstaller = new ServiceProcessInstaller();
// 设置帐户类型为本地系统,通常用这个
// 如果是远程服务,应指定登录的用户名和密码
processinstaller.Account = ServiceAccount.LocalSystem; // 把安装器添加到集合中
this.Installers.Add(svinstaller);
this.Installers.Add(processinstaller);
}
}

安装服务用ServiceInstaller,而且,必须必须注意,安装器上ServiceName指定的服务名字,必须要和刚才在Main中运行的服务的名字相同,不然,无法正确安装,也无法启动服务。

刚才我们定义服务的名字叫 HuiJi,所以这里也要指明为 HuiJi。

服务进程要用 ServiceProcessInstaller 来安装,实例化后,要指定它的帐户类型,对于在本机运行的服务,用LocalSystem就可以了(本地系统帐户)。一个应用程序用一个ServiceProcessInstaller就可以了,你用多个也没用,不信你可以试试在 Installers 集合中添加N个 ServiceProcessInstaller 实例,最后你发现,只有第一个进去的才会有效,其他的靠边站。而且,一个应用程序安装多个服务进程也没什么用。

最后,不要忘了把两个安装器添加进 Installers 集合中。

8、最关键一步,在刚铡定义的自定义安装类上应用RunInstaller特性,并且把参数设为true,这样做表示这个类是用于给安装工具发现,并且扫描安装的,这一步不能少,少了就无法安装。

    [RunInstaller(true)]
public class MyInstaller : Installer
{

好了,包含一个服务的应用程序做好了,下面看看如何注册和运行它了。

首先,生成应用项目,不要直接运行,因为它不是普通的.exe。

然后,要知道,安装服务用到一个叫 InstallUtil.exe 的工具,这个工具在 C: \ Windows \ Microsoft.NET \ Framework 下面,自己去找。找到了随便你怎么弄,最把这个exe所在目录加入到系统变量path中,这样,你就很轻松地用了。

到项目生成目录 \ bin \ Debug 下面,确认已成功生成了.exe 文件,然后在文件管理器左上角的菜单中 文件 ,“打开命令提示符” -- 以管理员身份打开命令提示符。

然后输入installUtil xxxx.exe ,回车。如图。

看到提示安装成功,说明服务已经装上了。现在打开系统的本地服务管理器窗口,可以看到刚才的服务了。

现在,你可以启动和停止服务了。

我们刚刚是通过Trace来输出跟踪信息的,那如何调试呢。

首先,关掉VS,再以管理员身份运行VS,然后再打开你的项目。

接着,到服务管理器中,启动服务。

回到VS,执行菜单 调试 -- 附加到进程。选择我们服务应用程序的进程。

然后附加调试器,接着再把服务停止,再启动,你就会看到 输出 窗口中的跟踪信息了。

测试完后,可以把刚刚的服务卸载掉,你可以用 sc delete 服务名 命令来删掉。不过,最好还是用刚才的 installUtil 工具来卸载。很简单,只要加一个 /u 参数就可以了。比如:installUtil /u xxxx.exe。

然后,你再到服务管理器窗口刷新一下,刚刚的服务就不见了,被卸载了。

做完这个练习后,你应该知道 Windows 服务怎么耍了,至少基本的步骤你懂了。

示例源代码  :http://files.cnblogs.com/files/tcjiaan/sampleServiceapp.zip

编写Windows服务疑问1:操作过程的更多相关文章

  1. 编写Windows服务疑问2:探索服务与安装器的关系

    首先,来弄两个服务,一个叫“飞机”,一个叫“火车”. public class FeiJiService : ServiceBase { public FeiJiService() { Service ...

  2. C#编写windows服务

    项目要求: 数据库用有一张表,存放待下载文件的地址,服务需要轮训表将未下载的文件下载下来. 表结构如下: 过程: VS--文件-->新建项目-->windows-->windows服 ...

  3. 使用C语言编写windows服务一般框架

    原文:使用C语言编写windows服务一般框架 编写windows服务和编写windows应用程序一样,有一些回调函数必须填写且向windows 服务管理器(service manager)进行注册, ...

  4. C#编写Windows 服务

    C#编写Windows 服务 Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时 ...

  5. python实现编写windows服务

    使用python编写windows服务 最近测试服务器上经常发生磁盘空间不足,每次手动清除比较麻烦,所以写个windows服务定时清理下.中间也遇到过几个坑,一起记录下来. 1.python实现win ...

  6. C# 编写windows服务及服务的安装、启动、删除、定时执行任务

    一.编写windows服务 1.VS2017  - 创建服务Myservice 2.创建好项目之后 --- >> 双击 Service1.cs  ---- >>  出现一个设计 ...

  7. c# 编写windows 服务,并制作安装包

    对服务的认识有很多个阶段. 第一阶段:当时还在用c++,知道在一个进程里while(True){},然后里面做很多很多事情,这就叫做服务了,界面可能当时还用Console控制台程序. 第二阶段:知道了 ...

  8. 手把手教用C#编写Windows服务 并控制服务 安装、启动、停止、卸载

    Windows服务 Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动, ...

  9. 第八篇--编写Windows服务

    编写service服务参考网址:https://blog.csdn.net/nodeathphoenix/article/details/24181509 vc获得显示器状态(捕获息屏.亮屏网址):h ...

随机推荐

  1. 《Web 前端面试指南》1、JavaScript 闭包深入浅出

    闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

  2. Fabio 安装和简单使用

    Fabio(Go 语言):https://github.com/eBay/fabio Fabio 是一个快速.现代.zero-conf 负载均衡 HTTP(S) 路由器,用于部署 Consul 管理的 ...

  3. 如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

    阅读目录 前言 如何在一个项目中实现多个上下文的业务 售价上下文与购买上下文的集成 结语 一.前言 前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西.比如促销.会员价等,在我们的 ...

  4. python自动化测试(2)-自动化基本技术原理

    python自动化测试(2) 自动化基本技术原理 1   概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...

  5. 记一个mvn奇怪错误: Archive for required library: 'D:/mvn/repos/junit/junit/3.8.1/junit-3.8.1.jar' in project 'xxx' cannot be read or is not a valid ZIP file

    我的maven 项目有一个红色感叹号, 而且Problems 存在 errors : Description Resource Path Location Type Archive for requi ...

  6. MVC常遇见的几个场景代码分享

    本次主要分享几个场景的处理代码,有更好处理方式多多交流,相互促进进步:代码由来主要是这几天使用前端Ace框架做后台管理系统,这Ace是H5框架里面的控件效果挺多的,做兼容也很好,有点遗憾是控件效果基本 ...

  7. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  8. Openfiler配置RAC共享存储

    将 Openfiler 用作 iSCSI 存储服务器,主要操作步骤如下: 1.设置 iSCSI 服务 2.配置网络访问 3.指定物理存储器并对其分区 4.创建新的卷组 5.创建所有逻辑卷 6.为每个逻 ...

  9. Maven多模块,Dubbo分布式服务框架,SpringMVC,前后端分离项目,基础搭建,搭建过程出现的问题

    现互联网公司后端架构常用到Spring+SpringMVC+MyBatis,通过Maven来构建.通过学习,我已经掌握了基本的搭建过程,写下基础文章为而后的深入学习奠定基础. 首先说一下这篇文章的主要 ...

  10. jQuery个性化图片轮播效果

    jQuery个性化图片轮播效果 购物产品展示:图片轮播器<效果如下所示> 思路说明: 每隔一段时间,实现图片的自动切换及选项卡选中效果,鼠标划入图片动画停止,划出或离开动画开始 两个区域: ...