使用Topshelf部署Windows服务

新建一个控制台应用程序,使用Nuget安装TopShelf:

nuget Install-Package Topshelf

测试代码:

在Main中输入:

            //FileInfo fi = new FileInfo(".//log4net.config");
            FileInfo fi = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config");
            XmlConfigurator.ConfigureAndWatch(fi);
            HostFactory.Run(x =>
            {
                x.Service<MyService>(s =>
                {
                    s.ConstructUsing(name => new MyService());
                    s.WhenStarted(tc => tc.Start());
                    s.WhenStopped(tc => tc.Stop());
                });
                x.RunAsLocalSystem();                           

                x.SetDescription("Sample Topshelf Host");
                x.SetDisplayName("Stuff");
                x.SetServiceName("Stuff");
                x.UseLog4Net();
            });

自定义服务MyService:

    public class MyService
    {
        readonly Timer _timer;
        readonly ILog _log = LogManager.GetLogger(typeof(MyService));
        public MyService()
        {
            _timer = ) { AutoReset = true };
            _timer.Elapsed += new ElapsedEventHandler(OnTick);
            _timer.Elapsed += (sender, eventArgs) => Console.WriteLine("It is {0} and all is well", DateTime.Now);
        }
        protected virtual void OnTick(object sender, ElapsedEventArgs e)
        {
            _log.Debug("Tick:" + DateTime.Now.ToLongTimeString());
        }
        public void Start()
        {
            _log.Info("Service is Started");
            _timer.Start();
        }
        public void Stop()
        {
            _log.Info("Service is Stopped");
            _timer.Stop();
        }
    }

TopShelf支持使用Log4net,使用Nuget安装Topshelf.Log4Net:

nuget Install-Package Topshelf.Log4Net

在项目根目录下新增log4net.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  </configSections>
  <log4net>
    <!--定义输出到文件中-->
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <!--定义文件存放位置-->
      <file value="log\\"/>
      <!--是否追加到文件,默认为true,通常无需设置-->
      <appendToFile value="true"/>
      <!--多线程时采用最小锁定-->
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <!--变换的形式为日志大小-->
      <!--这种情况下MaxSizeRollBackups和maximumFileSize的节点设置才有意义-->
      <!--<rollingStyle value="Size"/>-->
      <!--每天记录的日志文件个数,与maximumFileSize配合使用-->
      <!--<MaxSizeRollBackups value="/>-->
      <!--每个日志文件的最大大小-->
      <!--可用的单位:KB|MB|GB-->
      <!--不要使用小数,否则会一直写入当前日志-->
      <!--<maximumFileSize value="2MB"/>-->

      <!--变换的形式为日期,这种情况下每天只有一个日志-->
      <!--此时MaxSizeRollBackups和maximumFileSize的节点设置没有意义-->
      <rollingStyle value="Date"/>

      <!--每分钟写一个文件-->
      <!--<datePattern value="yyyyMMdd-HHmm" />-->
      <!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->

      <datePattern value="yyyyMMdd\\HH'.txt'"/>
      <staticLogFileName value="false"/>
      <param name="/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%newline %n记录时间:%date %n描述:%message"/>
        <!--<conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n出错类:%logger property: [%property{NDC}] - %n错误描述:%message%newline %n"/>-->
      </layout>
    </appender>

    <!--定义输出到MySql中-->
    <!--注意 Mysql.data 引用属性中复制本地一定要选True-->
    <appender name="AdoNetAppender_MySql" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="/>
      <param name="ConnectionType" value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"/>
      <param name="ConnectionString" value="server=localhost;database=test;uid=root;pwd=maocaiming;"/>
      <commandText value="INSERT INTO mylog111 (log_datetime,log_thread,log_level,log_logger,log_message,Exception) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)"/>
      <parameter>
        <parameterName value="@log_date"/>
        <dbType value="DateTime"/>
        <layout type="log4net.Layout.RawTimeStampLayout"/>
      </parameter>
      <parameter>
        <parameterName value="@thread"/>
        <dbType value="String"/>
        <size value="/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@log_level"/>
        <dbType value="String"/>
        <size value="/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logger"/>
        <dbType value="String"/>
        <size value="/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%logger"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message"/>
        <dbType value="String"/>
        <size value="/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%message"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@exception"/>
        <dbType value="String"/>
        <size value="/>
        <layout type="log4net.Layout.ExceptionLayout"/>
      </parameter>
    </appender>
    <root>
      <!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
      <!--比如定义级别为INFO,则INFO级别向下的级别,比如DEBUG日志将不会被记录-->
      <!--如果没有定义LEVEL的值,则缺省为DEBUG-->
      <level value="ALL"/>
      <!--文件形式记录日志-->
      <appender-ref ref="RollingLogFileAppender"/>
      <!--<appender-ref ref="AdoNetAppender_MySql"/>-->
    </root>
  </log4net>
</configuration>

这里需要注意的是:

此文件需要始终复制到输出目录;

//FileInfo fi = new FileInfo(".//log4net.config");
FileInfo fi = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config");

如果采用上面的配置的话在调试的时候会写日志,可是在部署成服务时就不写日志了。

使用Log4net还需注意的是这个配置文件如果取的路径不正确的话是不会生成日志的,而且此时程序并不会抛异常。

调试程序的时候直接运行即可。

安装服务的话可以用管理员权限打开Cmd,定位到程序所在目录,使用下面命令安装即可:

TopShelfService.exe install

注意中间是空格,卸载同理:

TopShelfService.exe uninstall

如果嫌打开CMD定位啥的麻烦的话,可以直接在应用程序上点击右键创建快捷方式,打开快捷方式属性,在目标的后面直接添加空格和install,再创建一个卸载的快捷方式,在目标后面添加空格和uninstall,注意如果是win7系统,需要更改快捷方式兼容性中以管理员身份运行此程序,当然,如果把程序部署到另外的服务器上的话可能快捷方式的路径会改变。

上一篇:PHP实现QQ登录的开发教程


下一篇:Extjs中创建Tree菜单【一】