We first introduce the benefits of using it, the following discussion reference from other great God.
topshelf is a way to create windows services, compared to the original implement ServiceBase, Install.Installer more simple and convenient, we only need a few lines of code to achieve the development of windows services.
topshelf support itself on windows and linux mono deployed at installation, it is also open source.
topshelf relatively speaking native, debugging more convenient, the console may be in the form of direct f5 debugging during development, deployment as a service of publishing command.
Still another feature is useful supports multiple instances of the deployment, so that the service can be deployed in a plurality of opposing a machine. Similar tools have instsrv and srvany.
There is a multi-instance advantage is that disaster recovery, when more than one service deployment, so that any instance of a service hung up, the remaining can continue.
Examples may be a plurality of standby mode, the standby main hanging service will be performed. Can also be a way to achieve load balancing, multi-instance process to seize the lock or distributed lock, who gets who performed.
The first to write specific steps:
// Create a new console application
// use Nuget installation Topshelf, select the latest version usable
// use Nuget installation NLog and NLog.config, select the latest version can be used for printing logs Nlog requires a configuration file, see NLog .config
// initial configuration file, create AppConfigHelper classes, inheritance ConfigurationSection (need to reference the System.Configuration assembly)
// perfect App.Config configuration file, read App.Config profile, specific view AppConfigHelper class
// create a registration service class TopshelfRegistService, initialization Topshelf registration
// our goal is simply to make a print service log file
// compile and build the project into the bin \ Debug directory to find xxx.exe execute the install command, Windows service was born
// Note: If you are prompted to start as an administrator appeared, re-start as administrator cmd
// followed directly on the code and screenshots
Uninstall the service:
When we start the service successfully print out the log shows every success
Program structure is very simple, as shown below:
Next, we direct the implementation code, I will give the order follow these steps:
1, Program main program code
1 namespace ProcessPrintLogService 2 { 3 class Program 4 { 5 public static readonly Logger log = LogManager.GetCurrentClassLogger(); 6 private static readonly AppConfigHelper config = AppConfigHelper.Initity(); 7 static void Main(string[] args) 8 { 9 TopshelfRegistService.Regist(config, true); 10 } 11 } 12 }
2.AppConfigHelper class for reading the configuration file, use the configuration files the way you can make the post-service applied to multiple applications
namespace ProcessPrintLogService { public class AppConfigHelper: the ConfigurationSection { Private static AppConfigHelper _AppConfig = null ; Private static Readonly Object LockThis = new new Object (); /// <Summary> /// acquire the content acquisition section configured current node // singleton mode /// </ Summary> /// <Returns> </ Returns> public static AppConfigHelper Initity () { IF (_AppConfig == null) { Lock (LockThis) { IF (_AppConfig == null ) { // Get app.config file section configuration node _AppConfig = (AppConfigHelper) ConfigurationManager.GetSection ( " AppConfigHelper " ); } } } return _AppConfig; } // create a AppConfigHelper node // attribute are: ServiceName, Desc and so on .... // introduce here properties tab: ConfigurationProperty it can get value from value property name in the configuration file //可以参考文章https://www.cnblogs.com/liunlls/p/configuration.html /// <summary> /// 服务名称 /// </summary> [ConfigurationProperty("ServiceName", IsRequired = true)] public string ServiceName { get { return base["ServiceName"].ToString(); } internal set { base["ServiceName"] = value; } } /// <summary> /// 描述 /// </summary> [ConfigurationProperty("Desc", IsRequired = true)] public string Description { get { return base["Desc"].ToString(); } internal set { base["Desc"] = value; } } } }
3.Topshelf component registration service
namespace ProcessPrintLogService { /// <Summary> /// topshelf component registration service /// </ Summary> Internal class TopshelfRegistService { /// <Summary> /// Register inlet /// </ Summary> /// <param name = "config"> profile </ param> /// <param name = "isreg"> is registered </ param> public static void the Regist (config AppConfigHelper, BOOL isreg = to false ) { // herein may be used HostFactory .Run () instead of HostFactory.New () var Host = HostFactory.New (X => { x.Service <QuartzHost> (S => { // by new QuartzHost () to build a service instance s.ConstructUsing (name => new new QuartzHost ()); // if the service What are executed after starting s.WhenStarted (tc => tc.Start ()); // What to perform when the service stops s.WhenStopped (tc => tc.Stop ()); // execute what services will be suspended when the s. WhenPaused (w => w.Stop ()); // What to perform when the service continues s.WhenContinued (W => w.Start ()); }); IF ! (isreg) return ; // default not register @ service account with the local system to run x.RunAsLocalSystem (); // description information and services x.SetDescription (config.Description); // display the name of the service x.SetDisplayName (config.ServiceName); // name of the service (best not to include spaces or characters with spaces attributes) Windows service name can not be repeated. x.SetServiceName (config.ServiceName); }); host.Run (); // Start Service If HostFactory.Run () method is not required } } /// <Summary> /// custom service /// </ Summary> Internal class QuartzHost { public Readonly Logger LogManager.GetLogger = log ( " QuartzHost " ); public QuartzHost () { var -Service = AppConfigHelper.Initity () ; } // service start public void start () { the try { Task.Run (() => { log.info ($ ' service start success! "); }); } The catch (Exception EX) { Task.Run (() => { log.Fatal (EX, $ " service start failed error message:! {0} " , EX); }); the throw ; } } // service stops public void the stop () { Task.Run (() => { log.Trace ( " service end Job " ); }); } } }
4.App.config profile
<? xml Version = " 1.0 " encoding = " UTF-8 " ?> <the Configuration> <-! This node must be placed in the uppermost -> <configSections> <Section name = " AppConfigHelper " of the type = " ProcessPrintLogService. AppConfigHelper, ProcessPrintLogService " /> </ configSections> <-! TopSelf service configuration file -> < AppConfigHelper ServiceName = " Process_PrintLogService " Asc = " log Print services " /> <! - database connection string -> <connectionStrings> <add name="ConnectionString" connectionString="123123123"/> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> </configuration>
5.Nlog.config log configuration file
<? xml Version = " 1.0 " encoding = " UTF-8 " ?> <nlog xmlns = " http://www.nlog-project.org/schemas/NLog.xsd " xmlns: xsi = " HTTP: // the WWW .w3.org / 2001 / XMLSchema-instance " > <targets> <- of the type =! " file | console " property is set the log output destination is the " file " (file) or " console " (console) -> <-! fileName = " $ {} the basedir / logs / ShortDate} {$ / $ {Level} / {$} .log CallSite "Set the path and name of journaling file -> " <-! Layout =${longdate} ${level} ${callsite}:${message}" 设置日志输出格式--> <target name="t1" type="File" fileName="${basedir}/logs/${shortdate}/${level} ${callsite}.log" layout="${longdate} ${level} ${callsite}:${message}" archiveAboveSize="3145728" archiveNumbering="Rolling" concurrentWrites="false" keepFileOpen = " to true " maxArchiveFiles = " 20 is " /> <-! to the console -> <target name = " T2 " type = " Console " layout = " $ {$ {Level of longdate}}} $ {CallSite : the message $ {} " /> </ Targets> <rules> ! <- * If fill, then all of the Logger will use this rule, the log information at all levels are written to" t1 "and" t2 " these two goals in -> <Logger name = " * " writeTo = " T1, T2 " /> </rules> </nlog>
That's all the code examples of this, this you may have a problem that I want to perform my regular job? For example, a few perform every day, or once every few minutes to perform, and so on, then how do we do it?
The answer is to use: Quartz.net, then I will use Quartz.net achieve the above timing tasks.
references:
https://www.jianshu.com/p/f2365e7b439c