Building Simple Windows Services Using Topshell Components

Posted by SilveR316 on Tue, 16 Jul 2019 19:32:12 +0200

Many times we are discussing whether we need to understand the underlying principles of a component or a language. In fact, I personally feel that everyone has their own views on this issue, and the way they choose will be different depending on their personal circumstances. I personally feel that no matter what we learn, we should try to understand the corresponding principles and source code. Understanding the underlying is not to let you write something similar, so you can not write it out. Rewriting one needs to modify the entire underlying structure. Understanding the underlying knowledge is only to enable you to write business code, choose the appropriate way, so that the underlying and business layer can work together to achieve the best efficiency. Either way is good or bad, and it needs the right choice.

If you think the above statement of the landlord is incorrect, or some are incorrect, you should be forgiven, because it is meaningless to argue a point of view, and those who think it is right will understand it themselves, and those who think it is incorrect can be ignored. There is no need to spend time and energy discussing such matters.

Above is bullshit, let's get down to the point. Hangfire, a component used to set timed tasks and so on, was introduced earlier, and Topshelf, another component, was introduced here.

Overview of Topshell Components

Topshell is the Windows service framework of. NET platform. Topshell can easily create Windows services, test services, debug services, and eventually install them into Windows Service Control Manager (SCM). Topshelf supports interaction details by allowing developers to focus on service logic rather than on built-in services in the. NET framework. Developers do not need to understand the complex details of service classes, perform installation through InstallUtil, or learn how to attach debuggers to services for troubleshooting.

Creating a Windows service is similar to creating a console application. After the console application is created, a single service class with common Start and Top methods is created. There are many ways of service operation, automatic, automatic (delay), manual and disabled startup options for local systems, local services, network services, username/password or service credentials prompted during installation. Service startup dependencies include SQL Server, MSMQ, and other multi-instance service installation service recovery options with different service names, including restart, reboot, or run programs. Topshell works with Mono to deploy services to Linux. The service installation function is currently limited to Windows.

II. Description of Topshell Usage

After introducing the background overview of the corresponding component, here we will introduce how to use this component. There is another way to use this component, both in the HostFactory class. Here's a specific way to use it.

1. Configuring a new service host

      HostFactory.New(x =>
                {
                    // You can define services that do not require interface dependencies, just for the sake of
                    //In this example, it is shown that it is not used.
                    x.Service<SampleSansInterfaceService>(s =>
                        {
                            s.ConstructUsing(() => new SampleSansInterfaceService());
                            s.WhenStarted(v => v.Start());
                            s.WhenStopped(v => v.Stop());
                        });
                });

2. Configure and run the new service host, handle any exceptions and write them to the log

   HostFactory.Run(x =>
                {
                    x.UseLog4Net("log4net.config");
                    x.UseAssemblyInfoForServiceInfo();
                    bool throwOnStart = false;
                    bool throwOnStop = false;
                    bool throwUnhandled = false;
                    x.Service(settings => new SampleService(throwOnStart, throwOnStop, throwUnhandled), s =>
                    {
                        s.BeforeStartingService(_ => Console.WriteLine("BeforeStart"));
                        s.BeforeStoppingService(_ => Console.WriteLine("BeforeStop"));
                    });
                    x.SetStartTimeout(TimeSpan.FromSeconds(10));
                    x.SetStopTimeout(TimeSpan.FromSeconds(10));
                    x.EnableServiceRecovery(r =>
                        {
                            r.RestartService(3);
                            r.RunProgram(7, "ping google.com");
                            r.RestartComputer(5, "message");

                            r.OnCrashOnly();
                            r.SetResetPeriod(2);
                        });
                    x.AddCommandLineSwitch("throwonstart", v => throwOnStart = v);
                    x.AddCommandLineSwitch("throwonstop", v => throwOnStop = v);
                    x.AddCommandLineSwitch("throwunhandled", v => throwUnhandled = v);
                    x.OnException((exception) =>
                    {
                        Console.WriteLine("Exception thrown - " + exception.Message);
                    });
                });

3. Topshell configuration operation method

3. Topshell Core Object Resolution

Undertake the above, introduce the relevant background and routine operations, and here introduce some methods of a core object.

  1.HostFactory.New():

public static Host New(Action<HostConfigurator> configureCallback)
        {
            try
            {
                if (configureCallback == null)
                    throw new ArgumentNullException("configureCallback");
                var configurator = new HostConfiguratorImpl();
                Type declaringType = configureCallback.Method.DeclaringType;
                if (declaringType != null)
                {
                    string defaultServiceName = declaringType.Namespace;
                    if (!string.IsNullOrEmpty(defaultServiceName))
                        configurator.SetServiceName(defaultServiceName);
                }
                configureCallback(configurator);
                configurator.ApplyCommandLine();
                ConfigurationResult result = ValidateConfigurationResult.CompileResults(configurator.Validate());
                if (result.Message.Length > 0)
                {
                    HostLogger.Get(typeof(HostFactory))
                              .InfoFormat("Configuration Result:\n{0}", result.Message);
                }
                return configurator.CreateHost();
            }
            catch (Exception ex)
            {
                HostLogger.Get(typeof(HostFactory)).Error("An exception occurred creating the host", ex);
                HostLogger.Shutdown();
                throw;
            }
        }

This method is used to configure a new service host. The method accepts a parameter Action < Host Configurator > configuration method call. The method returns the Host object to represent the Topshell service host and is ready to run. CongureCallback. Method. DeclaringType; used to get the class that declares the member. declaringType.Namespace; used to get the namespace for getting System.Type. Validate Configuration Result. CompileResults (configurator. Validate ()); used to validate configuration results.

   2.HostFactory.Run():

public static TopshelfExitCode Run(Action<HostConfigurator> configureCallback)
        {
            try
            {
                return New(configureCallback)
                    .Run();
            }
            catch (Exception ex)
            {
                HostLogger.Get(typeof(HostFactory))
                          .Error("The service terminated abnormally", ex);
                HostLogger.Shutdown();
                
                return TopshelfExitCode.AbnormalExit;
            }
        }

This method is a static method that configures and runs a new service host, handles any exceptions and writes them to the log. This method receives a parameter Action < Host Configurator > configureCallback configuration method call and returns the exit code of the process returned by the main method of the application.

IV. Summary

This is how to use Topshelf components to create simple Windows services. Here is a simple introduction, not a very in-depth introduction. If you need to know more, you can see the source code. After all, it is an open source free component, but also a very good component.

Topics: C# Windows network SQL Linux