Pages

Showing posts with label blog. Show all posts
Showing posts with label blog. Show all posts

Thursday, September 10, 2020

Topshelf: Getting started guide - Run .net core console application as windows service

Introduction

For people that don't know what Topshelf is.

"Topshelf is a framework for hosting services written using the .NET framework.
The creation of services is simplified, allowing developers to create a simple console application that can be installed as a service using Topshelf.
The reason for this is simple: It is far easier to debug a console application than a service.
And once the application is tested and ready for production, Topshelf makes it easy to install the application as a service."

Source

This "Topshelf: Getting started guide" post will explain the basics and how to use Topshelf with:
  • .NET Core 3.1
  • Topshelf 4.2.1
  • Serilog 2.9.0

  • Source code

    You can find the source code of this post on: https://github.com/gergroen/Topshelf-getting-started-guide

    Post summary

  • Installing NuGet
  • Create service class
  • Configure logging and windows service
  • Control the windows service
  • The result

  • Installing NuGet

    First create a .Net core console project and install the next nuget packages.
  • Serilog
  • Serilog.Sinks.Console
  • Serilog.Sinks.File
  • Topshelf
  • Topshelf.Serilog

  • Create service class

    Create a Service class. In this example the implementation has only log lines
    but here you can add your own functionality for the windows service.
    using Serilog;
    
    namespace Topshelf.GettingStarted
    {
        public class Service
        {
            public void Start()
            {
                Log.Information("Started");
            }
    
            public void Stop()
            {
                Log.Information("Stopped");
            }
        }
    }
    

    Configure logging and windows service

    Logging and the windows service are configured in the Program.Main.
    using System;
    using Serilog;
    
    namespace Topshelf.GettingStarted
    {
        class Program
        {
            static void Main(string[] args)
            {
                Log.Logger = new LoggerConfiguration()
                    .WriteTo.Console()
                    .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
                    .CreateLogger();
    
                var rc = HostFactory.Run(x =>
                {
                    x.Service(s =>
                    {
                        s.ConstructUsing(name => new Service());
                        s.WhenStarted(tc => tc.Start());
                        s.WhenStopped(tc => tc.Stop());
                    });
                    x.RunAsLocalSystem();
    
                    x.SetDescription("Topshelf Getting Started");
                    x.SetDisplayName("Topshelf.GettingStarted");
                    x.SetServiceName("Topshelf.GettingStarted");
                    x.UseSerilog();
                });
    
                var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());
                Environment.ExitCode = exitCode;
            }
        }
    }
    

    This is the result when we run the console application.

    Control the windows service

    To control the windows service we create the next batch files.

    _install-service.bat
    "%~dp0Topshelf.GettingStarted" install
    _start-service.bat
    "%~dp0Topshelf.GettingStarted" start
    _stop-service.bat
    "%~dp0Topshelf.GettingStarted" stop
    _uninstall-service.bat
    "%~dp0Topshelf.GettingStarted" uninstall
    Set the "Copy to output directory" of the batch files to "Copy if newer".

    The result

    Now you can run _install-service.bat as Administrator to install the application as windows service.
    If you open the Services console you will see the application in the list.

    Useful links:

    Source code
    Topshelf documentation

    Wednesday, September 2, 2020

    Developer blog: Getting started guide - Stackoverflow code styling for blog posts

    Stackoverflow.com use google-code-prettify as syntax highlighter.
    To use google-code-prettify on Blogger.com you have to add the following css to your template:
    /* Pretty printing styles. Used with prettify.js. */
    
    /* SPAN elements with the classes below are added by prettyprint. */
    .pln { color: #000 }  /* plain text */
     
    @media screen {
      .str { color: #800000 }  /* string content */
      .kwd { color: #00008b }  /* a keyword */
      .com { color: #808080 }  /* a comment */
      .typ { color: #2b91af }  /* a type name */
      .lit { color: #800000 }  /* a literal value */
      /* punctuation, lisp open bracket, lisp close bracket */
      .pun, .opn, .clo { color: #000 }
      .tag { color: #800000 }  /* a markup tag name */
      .atn { color: #ff0000 }  /* a markup attribute name */
      .atv { color: #0000ff }  /* a markup attribute value */
      .dec, .var { color: #000 }  /* a declaration; a variable name */
      .fun { color: #000 }  /* a function name */
    }
    
    /* Use higher contrast and text-weight for printable form. */
    @media print, projection {
      .str { color: #060 }
      .kwd { color: #006; font-weight: bold }
      .com { color: #600; font-style: italic }
      .typ { color: #404; font-weight: bold }
      .lit { color: #044 }
      .pun, .opn, .clo { color: #440 }
      .tag { color: #006; font-weight: bold }
      .atn { color: #404 }
      .atv { color: #060 }
    }
    
    /* Put a border around prettyprinted code snippets. */
    pre.prettyprint 
    { 
      background-color:#eeeeee;
      font-family:Consolas; 
      font-size:10.5pt; 
      overflow:auto;
      padding:5px;
    }
    
    /* Specify class=linenums on a pre to get line numbering */
    ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */
    li.L0,
    li.L1,
    li.L2,
    li.L3,
    li.L5,
    li.L6,
    li.L7,
    li.L8 { list-style-type: none }
    /* Alternate shading for lines */
    li.L1,
    li.L3,
    li.L5,
    li.L7,
    li.L9 { background: #eee }
    
    
    Also you have to add the following javascript between the <head></head> tags of your blog.
      <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
    
    And add onload='prettyPrint()' in the body tag.
    <body onload='prettyPrint()'>
    
    Now you can create posts with code snippets stackoverflow.com style.
    You need to add your code between <pre class="prettyprint"> and </pre>.
    <pre class="prettyprint lang-cs">
    
    // A Hello World! program in C#.
    using System;
    namespace HelloWorld
    {
        class Hello 
        {
            static void Main() 
            {
                Console.WriteLine("Hello World!");
    
                // Keep the console window open in debug mode.
                Console.WriteLine("Press any key to exit.");
                Console.ReadKey();
            }
        }
    }
    
    </pre>
    
    The result of the code snippet is:
    // A Hello World! program in C#.
    using System;
    namespace HelloWorld
    {
        class Hello 
        {
            static void Main() 
            {
                Console.WriteLine("Hello World!");
    
                // Keep the console window open in debug mode.
                Console.WriteLine("Press any key to exit.");
                Console.ReadKey();
            }
        }
    }