C#使用Topshelf创建Windows服务

一、项目创建

创建一个控制台应用程序,项目右键->管理 NuGet 程序包->Topshelft及Topshelf.Log4Net。

二、Topshelf配置

一般来说,服务都会设置每隔多长时间执行一次任务,这里使用System.Threading.Timer来做个简单的日志记录,将日志写入到Debug\Log文件夹下。

2.1、Log4Net配置

新建一个log4net.config的配置文件,在其属性的复制到输出目录项下选择始终复制。

<?xml version="1.0" encoding="utf-8" ?><configuration>  <configSections>    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />  </configSections>  <log4net>    <!-- Console部分log输出格式的设定 -->    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">      <layout type="log4net.Layout.PatternLayout">        <conversionPattern value="%date [%thread] %-5level %logger - %message %newline" />      </layout>    </appender>    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">      <file value="Log\"/>      <appendToFile value="true"/>      <maxSizeRollBackups value="10"/>      <maximumFileSize value="1MB"/>      <rollingStyle value="Date"/>      <datePattern value='yyyy-MM-dd".log"' />      <staticLogFileName value="false"/>      <!--最小锁定模型以允许多个进程可以写入同一个文件-->      <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />      <layout type="log4net.Layout.PatternLayout">        <conversionPattern value="%date %-5level %logger - %message %newline"/>      </layout>    </appender>    <root>      <level value="ALL" />      <appender-ref ref="ConsoleAppender" />      <appender-ref ref="RollingLogFileAppender" />    </root>  </log4net></configuration>

2.2、TopshelfService

新建一个TopshelfService类:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using Topshelf;using Topshelf.Logging;namespace LinkTo.Test.TopshelfService{    public class TopshelfService : ServiceControl    {        private static readonly LogWriter logger = HostLogger.Get<TopshelfService>();        private static Timer timerAsync = null;        private readonly int dueTimeInterval = 1000 * 5; //单位:毫秒        private readonly int periodInterval = 1000 * 5;  //单位:毫秒        /// <summary>        /// 构造函数        /// </summary>        public TopshelfService()        {            timerAsync = new Timer(AutoAsyncCallback, null, Timeout.Infinite, Timeout.Infinite);        }        /// <summary>        /// 启动服务        /// </summary>        /// <param name="hostControl"></param>        /// <returns></returns>        public bool Start(HostControl hostControl)        {            try            {                logger.Info("HelloTopshelf Start");                timerAsync.Change(dueTimeInterval, periodInterval);            }            catch (Exception ex)            {                logger.Info(ex.Message);            }            return true;        }        /// <summary>        /// 停止服务        /// </summary>        /// <param name="hostControl"></param>        /// <returns></returns>        public bool Stop(HostControl hostControl)        {            try            {                logger.Info("HelloTopshelf Stop");                if (timerAsync != null)                {                    timerAsync.Change(Timeout.Infinite, Timeout.Infinite);                    timerAsync.Dispose();                    timerAsync = null;                }            }            catch (Exception ex)            {                logger.Info(ex.Message);            }            return true;        }        /// <summary>        /// 回调函数        /// </summary>        /// <param name="state"></param>        private void AutoAsyncCallback(object state)        {            try            {                timerAsync.Change(Timeout.Infinite, Timeout.Infinite);                logger.Info("AutoAsyncCallback执行开始");                Thread.Sleep(1000 * 10);            }            catch (Exception ex)            {                logger.ErrorFormat("AutoAsyncCallback执行异常:{0}", ex.Message);            }            finally            {                timerAsync.Change(dueTimeInterval, periodInterval);                logger.Info("AutoAsyncCallback执行结束");                logger.Info(Environment.NewLine);            }        }    }}

2.3、配置和运行宿主服务

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Topshelf;namespace LinkTo.Test.TopshelfService{    class Program    {        static void Main(string[] args)        {            HostFactory.Run(x =>            {                x.UseLog4Net("log4net.config");                x.RunAsLocalSystem();                x.Service(settings => new TopshelfService());                //服务的描述                x.SetDescription("你好,Topshelf!");                //服务的显示名称                x.SetDisplayName("Hello Topshelf Service");                //服务名称                x.SetServiceName("HelloTopshelf");            });        }    }}

三、安装与卸载

3.1、安装服务

在Debug文件夹下面,创建一个"安装服务.bat"的批处理文件:

@echo onrem 设置DOS窗口的背景颜色及字体颜色color 2frem 设置DOS窗口大小 mode con: cols=80 lines=25@echo offecho 请按任意键开始安装LinkTo.Test.TopshelfService服务rem 输出空行echo.pauseLinkTo.Test.TopshelfService installnet start HelloTopShelfpause

3.2、卸载服务

在Debug文件夹下面,创建一个"卸载服务.bat"的批处理文件:

@echo onrem 设置DOS窗口的背景颜色及字体颜色color 2frem 设置DOS窗口大小 mode con: cols=80 lines=25@echo offecho 请按任意键开始卸载LinkTo.Test.TopshelfService服务rem 输出空行echo.pausenet stop HelloTopShelfLinkTo.Test.TopshelfService uninstallpause

3.3、查看服务

在运行中输入"services.msc"进入服务,即可看到新建的HelloTopshelf服务:

四、添加管理员权限要求

项目右键->添加->新建项->应用程序清单文件。

将requestedExecutionLevel节点的level设置为"requireAdministrator"。

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
(0)

相关推荐