项目中有些时候需要写服务,一般我们都是先创建控制台程序,测试,运行,成功之后再创建windows服务程序,这样好麻烦啊,有没有简单的控制台程序直接变成Widnows服务,经过查找,找到了Topshelf。Topshelf是一个托管使用.NET框架编写的服务的框架,简化了服务的创建,允许开发人员创建一个简单的控制台应用程序,可以使用Topshelf作为服务安装。

使用NSSM工具将exe封装为服务

根据下面的评论,增加了这一部分的内容,NSSM是一款比较好用的将exe封装为服务的工具

1.下载NSSM官网https://nssm.cc/,download
2. 解压
3. 在cmd中找到nssm.exe
例如:E:\nssm-2.24\nssm-2.24\win64>

4. 安装服务
安装服务:nssm install <servicename>

写的控制台程序需要注意,不要一闪而过,也就是运行控制台程序的时候,控制台不会自己关闭,自己关闭意味着程序结束,服务启动之后也会结束,所以最后的 Console.ReadKey();还是需要的。

启动服务:nssm start <servicename>
停止服务:nssm stop <servicename>
重启服务: nssm restart <servicename>
服务删除:nssm remove <servicename>

这个工具的使用是根据下面的评论来的,比较好用,但是也有点小缺点,就是程序都需要写在main中,需要控制好运行的顺序,如果要服务开始的时候运行什么,中间运行什么,停止的时候运行什么,这个程序就没办法控制了,如果是一般的服务用工具就可以了,如果比较复杂,需要做流程控制,可以参考下面的程序。

Topshelf介绍

Topshelf是一个托管使用.NET框架编写的服务的框架。简化了服务的创建,允许开发人员创建一个简单的控制台应用程序,可以使用Topshelf作为服务安装。原因很简单:调试控制台应用程序比使用服务要容易得多。一旦应用程序经过测试并可以投入生产,Topshelf便可以轻松地将应用程序作为服务进行安装。这是一个开源的项目,项目地址,Nuget上可以搜到响应的库。

Topshelf使用

1.创建控制台程序
2.安装Topshelf,在Nuget上搜下
3.安装NLog、NLog.Config,目的是为了看日志,可以清楚的知道服务在运行,可以不要
NLog.Config简单配置

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log"> <!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables
-->
<variable name="myvar" value="myvalue"/> <!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets> <!--
add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
--> <!--
Write events to a file with the date in the filename.
-->
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets> <rules>
<!-- add your logging rules here --> <!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
-->
<logger name="*" minlevel="Debug" writeTo="f" />
</rules>
</nlog>

4.代码实现

class Program
{
private static readonly Logger logger = LogManager.GetLogger("Program");
static void Main(string[] args)
{
logger.Info($"Main主程序{DateTime.Now}");
var rc = HostFactory.Run(x => //1.启动程序
{
logger.Info($"主程序{DateTime.Now}");
x.Service<TownCrier>(s => //2.设置服务类型
{
s.ConstructUsing(name => new TownCrier()); //3.创建服务实例
s.WhenStarted(tc => tc.Start()); //4.启动程序
s.WhenStopped(tc => tc.Stop()); //5.停止程序
});
x.RunAsLocalSystem(); //6.本地系统运行 x.SetDescription("超级简单的windows服务"); //7.windows服务的描述
x.SetDisplayName("SimpleWindowsService 服务"); //8.windows服务的显示名称
x.SetServiceName("SimpleWindowsService"); //9.windows服务的服务名称
}); var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); //11.退出程序
Environment.ExitCode = exitCode; }
} public class TownCrier
{
private static readonly Logger logger = LogManager.GetLogger("logTest");
readonly Timer _timer; //System.Timers不要引用错误
public TownCrier()
{
_timer = new Timer() { AutoReset = true };
_timer.Elapsed += (sender, eventArgs) =>
{
Console.WriteLine($"It is {DateTime.Now} and all is well");
logger.Info($"It is {DateTime.Now} and all is well");
};
}
public void Start() { _timer.Start(); }
public void Stop() { _timer.Stop(); }
}

必须有启动方法(Start)和停止方法(Stop)

4. 运行控制台程序,也可以是调试,效果如下

5. 程序调试运行成功,一切ok,现在可以安装服务了,以管理员身份运行cmd找到对应路径,开始安装

安装:SimpleWindowsService.exe install

查看服务

启动:SimpleWindowsService.exe start

服务已经运行,查看运行情况,日志

卸载:SimpleWindowsService.exe uninstall

可以看到服务已经没有了

停止:SimpleWindowsService.exe stop
停止之后可以再次启动,这个功能不介绍了,卸载服务的时候会调用这个方法。

Topshelf的其他功能

安装动作之前:Topshelf允许指定在安装服务之前执行的操作。请注意,只有在安装服务时才会执行此操作。

HostFactory.New(x =>
{
x.BeforeInstall(settings => { ... });
});

安装动作后:Topshelf允许指定在安装服务后执行的操作。请注意,只有在安装服务时才会执行此操作。

HostFactory.New(x =>
{
x.AfterInstall(settings => { ... });
});

在卸载操作之前:Topshelf允许指定在卸载服务之前执行的操作。请注意,只有在卸载服务时才会执行此操作。

HostFactory.New(x =>
{
x.BeforeUninstall(() => { ... });
});

卸载操作后:Topshelf允许指定在卸载服务后执行的操作。请注意,只有在卸载服务时才会执行此操作。

HostFactory.New(x =>
{
x.AfterUninstall(() => { ... });
});

异常:为服务运行时抛出的异常提供回调。此回调不是处理程序,不会影响Topshelf已提供的默认异常处理。它旨在提供对触发外部操作,日志记录等的抛出异常的可见性。

HostFactory.New(x =>
{
x.OnException(ex =>
{
// Do something with the exception
});
});

其他的一些功能,如果需要可以查看英文官网文档

定时任务的服务

一般的服务都没有这么简单,一般都需要定时任务,这里的定时任务服务用到了FluentScheduler,FluentScheduler定时器介绍 ,这篇文章对FluentScheduler定时器进行了详细的介绍,这里不再介绍,只展示使用。

/// <summary>
/// 用MySchedule的任务定时功能
/// </summary>
public class MyJob {
private static readonly Logger logger = LogManager.GetLogger("MyJob");
public MyJob() { }
public void Start()
{
logger.Info($"MySchedule启动 {DateTime.Now}");
JobManager.Initialize(new MySchedule());
}
public void Stop()
{
logger.Info($"MySchedule停止 {DateTime.Now}");
JobManager.Stop();
}
} /// <summary>
/// 定时器
/// </summary>
public class MySchedule : Registry
{
private static readonly Logger logger = LogManager.GetLogger("MySchedule");
public MySchedule()
{
SetNewsSchedule();
} /// <summary>
/// 设置任务
/// </summary>
private void SetNewsSchedule()
{
//获取链接发送邮件
Schedule(() =>
{
logger.Info($"MySchedule运行 {DateTime.Now}");
}
).ToRunNow().AndEvery().Milliseconds();
}
}

控制台程序调用

class Program
{
private static readonly Logger logger = LogManager.GetLogger("Program");
static void Main(string[] args)
{
logger.Info($"Main主程序{DateTime.Now}");
var rc = HostFactory.Run(x => //1.启动程序
{
logger.Info($"主程序{DateTime.Now}");
x.Service<MyJob>(s => //2.设置服务类型
{
s.ConstructUsing(name => new MyJob()); //3.创建服务实例
s.WhenStarted(tc => tc.Start()); //4.启动程序
s.WhenStopped(tc => tc.Stop()); //5.停止程序
});
x.RunAsLocalSystem(); //6.本地系统运行 x.SetDescription("超级简单的windows服务"); //7.windows服务的描述
x.SetDisplayName("SimpleWindowsService 服务"); //8.windows服务的显示名称
x.SetServiceName("SimpleWindowsService"); //9.windows服务的服务名称
});
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); //11.退出程序
Environment.ExitCode = exitCode; }
}

服务安装两步走,管理员cmd,SimpleWindowsService.exe install, SimpleWindowsService.exe start

总结

1. 写控制台程序

2.管理员cmd,SimpleWindowsService.exe install

3.启动服务SimpleWindowsService.exe start

4.卸载服务SimpleWindowsService.exe uninstall

控制台程序秒变Windows服务(Topshelf)的更多相关文章

  1. 如何将控制台程序包装成windows服务

    1. 新建一个项目,或者从选择当前解决方案--右键-添加--新建项目 2. 选择(项目类型)Visual C#项目,(模板)Windows 服务,填写要创建的服务名称(修改默认的WindowServi ...

  2. 控制台程序转化为windows服务

    首先我们创建一个控制台应用程序WriteLog,然后添加windows服务LogService 新增的windows服务切换到代码视图,我这边用log4net进行的日志的记录 OnStart方式是服务 ...

  3. 将一个应用程序添加做成windows服务

    需求来源: 在服务器端运行的一个应用程序,为完成客户端路径分析等功能: 此应用程序只需要运行着就可以,没有界面等要求: 因此,考虑把此应用程序添加到服务器端电脑管理的服务中,可以启动和停止. 这里添加 ...

  4. 使用instsrv.exe+srvany.exe将应用程序安装为windows服务[转]

      转自:http://qingmu.blog.51cto.com/4571483/1248649 一.什么是instsrv.exe和srvany.exe instsrv.exe.exe和srvany ...

  5. 使用wrapper将java程序注册程windows服务后不生效

    使用wrapper将java程序注册程windows服务后不生效 使用add.bat或test***.bat测试通过了, 然后使用install***.bat注册后cmd显示注册成功. 但是程序到了运 ...

  6. 利用Topshelf把.NET Core Generic Host管理的应用程序部署为Windows服务

    背景 2019第一篇文章. 此文源于前公司在迁移项目到.NET Core的过程中,希望使用Generic Host来管理定时任务程序时,没法部署到Windows服务的问题,而且官方也没给出解决方案,只 ...

  7. C#判断程序是由Windows服务启动还是用户启动

    在Windows系统做网络开发,很多时候都是使用Windows服务的模式,但在调度阶段,我们更多的是使用控制台的模式.在开发程序的时候,我们在Program的Main入口进行判断.最初开始使用Envi ...

  8. 将bat文件或exe程序注册成windows服务

    命令行使用sc命令.关于sc命令的详解,请自行查看帮助(sc /?),在此只简单提及如何加入系统服务功能.加入服务:sc create ServiceName binPath= 路径 start= a ...

  9. 使用srvany.exe把程序安装成windows服务的方法

    http://mazhihui.iteye.com/blog/1294431 srvany.exe是什么? srvany.exe是Microsoft Windows Resource Kits工具集的 ...

随机推荐

  1. WPF ListView控件设置奇偶行背景色交替变换以及ListViewItem鼠标悬停动画

    原文:WPF ListView控件设置奇偶行背景色交替变换以及ListViewItem鼠标悬停动画 利用WPF的ListView控件实现类似于Winform中DataGrid行背景色交替变换的效果,同 ...

  2. WPF 打印实例

    原文:WPF 打印实例      在WPF 中可以通过PrintDialog 类方便的实现应用程序打印功能,本文将使用一个简单实例进行演示.首先在VS中编辑一个图形(如下图所示).      将需要打 ...

  3. Android中对sqlite加密--SQLCipher

    原文:Android中对sqlite加密--SQLCipher android中有些时候会将一些隐私数据存放在sqlite数据库中,在root过的手机中通过RE就能够轻松的打开并查看数据库所有内容,所 ...

  4. 【全面解禁!真正的Expression Blend实战开发技巧】第五章 从最常用ButtonStyle开始 - ImageButton

    原文:[全面解禁!真正的Expression Blend实战开发技巧]第五章 从最常用ButtonStyle开始 - ImageButton 本章围绕ImageButton深入讨论,为什么是Image ...

  5. Win10《芒果TV》更新v3.8.70周年版:升级高级配色、自动切换夜间模式

    官宣!光阴似箭,已过三年时光,我们一起从最初的青涩变成更加成熟起来,同呼吸共命运,匠心依旧,感恩有你,Win10版<芒果TV>全平台同步更新周年版v3.8.70,升级高级配色,新增自动切换 ...

  6. Win10《芒果TV》商店版更新v3.1.3.0:优化应用速度,支持会员卡兑换

    在微软秋季Win10/Surface新品发布会热潮之后,<芒果TV>UWP版迅速更新v3.1.3版,优化应用启动速度,支持会员卡券兑换,新增全网搜索.记忆播放.消息推送等功能. 芒果TV ...

  7. MySQL半同步复制搭建

    默认情况下,MySQL 5.5/5.6/5.7和MariaDB 10.0/10.1的复制是异步的,异步复制可以提供最佳性能,主库把binlog日志发送给从库,这一动作就结束了,并不会验证从库是否接收完 ...

  8. jsp中的指令与动作

    JSP中的三种命令指令分别是page.include.taglib JSP中的动作元素包括:include.forward.useBean.getProperty.setProperty.plugin ...

  9. 获取其他进程的命令行(ReadProcessMemory其它进程的PPROCESS_PARAMETERS和PEB结构体)

    type   UNICODE_STRING = packed record     Length: Word;     MaximumLength: Word;     Buffer: PWideCh ...

  10. mysql自动安装教程说明

    这里只说明了思路和方法 我们在安装程序里面可能需要安装的时候将mysql一起安装,那么我们就按照下面的顺序思路来. 首先我们安装的电脑上可能已经安装了mysql,所以我们的mysql服务就起一个名字, ...