C# 开发 Windows 服务程序最简单的方式-Topshelf

一、概述

一直以来,我都在追求以最简单的方式写程序。这里的最简单是指利用强大的工具。

这种想法主要来源于三年前我服务过的一个客户。他们的IT经理就一直在部门内部强调“你所想到的,别人都想已经想到而且做到了,学会寻找比学会创造更加重要。”这种话虽略显极端,但在程序这个领域里却有着重要意义。像很多知名的开源软件,都是无数人智慧的结晶。扯远了~

本文写作的目的是,记录一种最简单开发 Windows 服务的方式– Topshelf 。使用前先下载依赖文件: Topshelf.dll Topshelf.4.2.0.zip 或者直接通过 Nuget 安装:Install-Package Topshelf

Topshelf 官方网站: http://topshelf-project.com/

Topshelf 文档地址: https://topshelf.readthedocs.io/en/latest/index.html

二、程序实例

C# 直接创建控制台项目,覆盖 Program.cs 文件为如下代码:

usingSystem;usingSystem.Timers;usingTopshelf;namespaceTopshelfDemo{publicclassTownCrier{readonlyTimer _timer;publicTownCrier(){            _timer =newTimer(1000) { AutoReset =true};//1秒执行一次_timer.Elapsed += (sender, eventArgs) => Console.WriteLine("It is {0} and all is well", DateTime.Now);        }publicvoidStart(){ _timer.Start(); }publicvoidStop(){ _timer.Stop(); }    }publicclassProgram{publicstaticvoidMain(){varrc = HostFactory.Run(x =>            {                x.Service(s =>                {                    s.ConstructUsing(name =>newTownCrier());                    s.WhenStarted(tc => tc.Start());                    s.WhenStopped(tc => tc.Stop());                });                x.RunAsLocalSystem();//服务器使用内置账户运行x.SetDescription("Sample Topshelf Host");//服务的描述信息x.SetDisplayName("Stuff");//服务的显示名称x.SetServiceName("Stuff");//服务的名称(最好不要包含空格或者有空格属性的字符)。Windows 服务名称不能重复。//x.SetInstanceName("MyService");//实例名称:主要用于命令行部署多实例时进行区分。效果是:Stuff$MyService});varexitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());            Environment.ExitCode = exitCode;        }    }}

这段代码就是 Topshelf 官网文档中的实例代码。

直接启用运行,效果如下。每秒输出一条语句。到这里实现输出的字符串的 Windows 服务程序就开发完成了。

下面看如何安装、运行、停止和卸载服务。

1. 程序安装:

假设运行程序存放到以下路径:

用管理员方式打开命令行窗口,在 exe 所在路径下执行:TopshelfDemo.exe install 安装服务。

在服务窗口中可以查看到安装完成的服务。

命令行窗口中会涉及到的命令(以程序 server.exe 举例,自行替换):

安装服务 server.exe install

启动服务 server.exe start

停止服务 server.exe stop

卸载服务 server.exe uninstall

2. 注意事项

这里要注意:必须使用管理员方式运行命令行窗口!!否则会提示错误信息:The Stuff service can only be installed as an administrator

到这里为止,开发及安装 Windows 服务已经完成了!下面介绍写自定义设置,可看可不看。

三、Topshelf 自定义项说明

1. 服务的启动模式

可以指定多种服务的启动模式,这些选项只在服务安装后有效。

HostFactory.New(x =>{x.StartAutomatically();// 服务自动启动x.StartAutomaticallyDelayed();// 服务自动启动(延时启动) -- 需要 .NET 4.0 或以上版本x.StartManually();// 手动启动服务x.Disabled();// 服务禁用状态});

2. 指定服务运行的身份

HostFactory.New(x =>{    x.RunAs("username","password");//使用指定用户名和密码运行服务,用户名中包含域:domain\username 或者 username@suffix.com//x.RunAsPrompt();//安装服务时,提示输入用户名和密码用于启动服务//x.RunAsNetworkService();//使用内置的 NETWORK_SERVICE 账户运行服务//x.RunAsLocalSystem();//使用本地系统账户运行//x.RunAsLocalService();//使用本地服务账户运行});

3. 自定义安装或卸载时执行的动作

这些操作允许在服务安装或卸载的过程中执行用户指定的方法。这里需要特别注意,一定是服务安装或卸载时有效!方法中可以使用服务的实例名称、服务名称等。

HostFactory.New(x=>{    x.BeforeInstall(settings=>{ ... });//安装服务前执行x.AfterInstall(settings=>{ ... });//安装服务后执行x.BeforeUninstall(()=>{ ... });//卸载服务前执行x.AfterUninstall(()=>{ ... });//卸载服务后执行});

4. 指定依赖的服务

可以指定服务依赖项,以便在依赖服务启动之前不会启动服务。这是由 windows 服务控制管理器管理的,而不是由 Topshelf 本身管理的。

HostFactory.New(x =>{x.DependsOn("SomeOtherService");});//对于知名的服务,有很多内置的扩展方法,包括:HostFactory.New(x =>{x.DependsOnMsmq();// Microsoft Message Queueingx.DependsOnMsSql();// Microsoft SQL Serverx.DependsOnEventLog();// Windows Event Logx.DependsOnIis();// Internet Information Server});

5. 支持服务管理器暂停、继续、关闭等

HostFactory.New(x =>{x.EnablePauseAndContinue();//允许服务控制管理器向服务传递暂停和继续命令x.EnableShutdown();//允许服务控制管理器快速关闭服务x.OnException(ex =>    {//此功能为服务运行时引发的异常提供回调。此回调不是处理程序,也不会影响 Topshelf 已经提供的默认异常处理程序//它旨在为触发外部操作如异常记录等});});

6. 服务恢复选项

HostFactory.New(x =>{x.EnableServiceRecovery(r =>    {//恢复操作按指定的顺序执行,上一个操作运行后执行下一个操作//可以执行多少个操作是有限制的 (基于操作系统),通常是 2-3 个操作。r.RestartComputer(5,"message");r.RestartService(1);// 1分钟后重启服务//因为最多执行3个操作,最后一个将会执行后续所有的失败r.RunProgram(7,"ping google.com");// 运行程序,例如 notepad.exer.SetResetPeriod(1);// 将重置间隔设置为一天});});

看我主页简介免费C++学习资源,视频教程、职业规划、面试详解、学习路线、开发工具

每晚8点直播讲解C++编程技术。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,774评论 0 27
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,719评论 0 10
  • 0x0000000A 1、主要是由于安装了有缺陷或不兼容的硬件(BIOS)、驱动程序、软件产生。2、当系统升级WI...
    Muscleape阅读 2,443评论 0 3
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,084评论 1 32
  • Linux习惯问题: 在vim编辑时,按了ctrl + s后,再按ctrl + q就可以继续执行了。ctrl + ...
    光着脚的鞋阅读 4,480评论 0 16