.NET Windows Service to complement a Clarion Desktop Application

So, I have a need for a something to run background tasks. Ideally I would like to configure Point-to-Site VNet connections for each database and centralize things in Azure somewhere (Azure functions anyone?!) but that hit against the reality and logistics of different organisations and their policies pretty quickly :slight_smile:

Windows task scheduler was considered but the idea was dropped pretty quickly. It could be made to work I suppose but setup configuration and maintenance looks like a real PITA.

I have made a Windows Service before using SelfService from Capesoft which works well enough but this was a new application and it felt like a good opportunity to explore other options and continue to grow outside of Clarion if it made sense to do so.

The results so far are pretty amazing and I thought it might be nice to share some of the process!

Goals

This solution needed to cover one primary requirement and meet basic acceptance criteria.

Requirement: Perform an action on a schedule.
Acceptance Criteria:

  • Solution must be able to operate in independently within the clients network .
    (Not require the Clarion desktop application to be running)
  • Solution must have minimal support impact.
    (Don’t force the support staff to work too hard!)
  • Solution must be secure and reliable.
    (obviously)
  • Solution must be accountable
    (i.e. we need to be able to report exactly what is happening and be able to understand and trust that reporting!)

It isn’t anything too formal but it can be nice to outline a few things like that in advance I think.

Implementation

Auto Updates (stretch goal!)

Something I had wanted to investigate was auto (self) updating the service too but for now that is not a priority. There is a thing called wyBuild that kept coming up which looks interesting though and once the service has matured I may come back to it. See AutomaticUpdater tutorial for Windows Services and Console Apps for more in case you are curious.

Windows Service

Building a Windows Service in C# doesn’t look too hard. There is a Windows Service project template and a whole raft of help out there on the internets. First hit in google for me is the MSDN article Walkthrough: Creating a Windows Service Application in the Component Designer

However, I wanted something more… managed. Or abstracted or whatever.

http://topshelf-project.com/

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.

Documentation is great, examples are clear. There appears to be a bunch of people using it and I was able to find answers to all my questions about this.

  1. Create a C# Console project
  2. Add the nuget package
  3. Add a little bit of code. Their example works fine for starters.

This is my implementation:

    class Program
    {
        static void Main(string[] args)
        {
            HostFactory.Run(x =>
            {
                x.Service<JobHost>(s =>
                {
                    s.ConstructUsing(name => new JobHost());
                    s.WhenStarted(tc => tc.Start());
                    s.WhenStopped(tc => tc.Stop());
                });
                x.SetServiceName("MyScheduler");
                x.SetDisplayName("MyScheduler");
                x.SetDescription("Sample MyScheduler Host");
            });
        }
    }

Whatever is in JobHost is your service magic. That’s it!
From Visual Studio you just run it as a console app for development then when you are ready, install it as a service using the whatever you need from the extensive command-line vocabulary.

MyScheduler.exe install --sudo --interactive

--sudo - Prompts for UAC if running on Vista/W7/2008

WHAT? So cool! :star:

--interactive - The service will prompt the user at installation for the service credentials

You can of course call it from an installer or whatever and various things can be defaulted via code instead of needing the command line option. Check out the other options.

Diagnostic Logging

Running as a service kinda sucks for debugging and for seeing what on earth is going on. From the outset I knew I wanted seriously helpful logging.

Topshelf supports several standard .NET logging frameworks. Their documentation is actually little light in this aspect, there are in fact a bunch more Logging integrations.

I looked at NLog and Log4Net but just for fun decided to go with Serilog. Well, actually I decided to go for Serilog because the available “sinks” seem really nice.

  1. Install Serilog from nuget. Use the UI or just PM> Install-Package Serilog
  2. Install the Topshelf.Serilog PM> Install-Package Topshelf.Serilog

Setup of Serilog is well documented and easy enough. This is what I did:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.RollingFile(AppDomain.CurrentDomain.BaseDirectory + "logs\\TripsScheduler-{Date}.log")
    .WriteTo.ColoredConsole()
    .CreateLogger();
Log.Information("Hello, world!");

Works great, I can see what is happening!

When running as a Windows Service the same information is logged to file. Or Azure App Insights, or Amazon or ElasticSearch or Glimpse or Loggly or… or… etc! See the big List of available sinks

Background Tasks

And this is the whole point right!

Sure, you can use a bunch of different techniques but, blurgh!

If you think you can just write a background task yourself, it’s likely you’ll get it wrong. I’m not impugning your skills, I’m just saying it’s subtle. Plus, why should you have to?
– https://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx

^ Great post, go read it. Very helpful.

How about - The Dangers of Implementing Recurring Background Tasks In ASP.NET

I looked at a few options and Hangfire seemed to be well recommended and a bit of a stand out. How hard can it be? Not hard! :slight_smile:

Hangfire
An easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required.

Backed by persistent storage. Open and free for commercial use.

  • Fire-and-forget jobs
  • Delayed jobs
  • Recurring jobs
  • Continuations

Heaps more, this should do what I right now as well as when the users are for a bunch more crazy things to happen.

It took me about 10 minutes to implement.

  1. Install a couple of packages
    PM> Install-Package Hangfire.Core
    PM> Install-Package Hangfire.SqlServer
  2. Specify a GlobalConfiguration for the SqlServer storage.
  3. Add a RecurringJob !

Hangfire automagically detects your logging framework so there is zero extra work to be done there.

There was a bit of extra work to get it to integrate nicely with Topshelf but only a few lines and it was pretty obvious what to do from the documentation.

The one thing that took a bit of extra work was getting the self-hosted dashboard working.

WHAT?!

Yes, Hangfire comes with a built-in dashboard to show you what is going on. So awesome.

The main dashboard:

Recurring Jobs

Details of Jobs

Full source code of my implementation:

Conclusions?!

I am currently very, very happy with this starting point for my new service. It looks like it will be rock solid and be a great foundation. Now all I need to do is implement the actual “Do Stuff” work. Hmm…!!! :slight_smile:

This post adds some interesting detail for the Topshelf / OWIN design:

https://blog.uship.com/shippingcode/self-hosting-a-net-api-choosing-between-owin-with-asp-net-web-api-and-asp-net-core-mvc-1-0/

Oh, these also helped me get going with Hangfire:

https://brosteins.com/2016/02/14/setting-up-the-hangfire-dashboard-in-a-windows-service/

(posting here as a bookmark for later study!)

1 Like