How TopShelf solves a specific problem very elegantly.

A lot of our architecture is based on windows services. One of the issues with this setup is that we would have to install those windows services on our developer machines. Something we are not really fond of, especially since they won't be used for the bigger part of our work. We just want to run the services related to the specific problem we are trying to solve.

To work around this inconvenience, we would create a project containing some general code and next to that project there is a console application project and a windows service project. You can imagine that this causes a lot of overhead in the solution. For each service we would have three projects instead of only the one we actually need. I have seen this approach before and one more than one occasion, and was never really a big fan of it.

But now we have a more elegant solution. It's name is TopShelf.

How to use TopShelf

I won't explain all  the details. It's definitely worth reading the documentation at http://topshelf-project.com/.
What you will read here is a brief description of how we use it.

Creating a new project

The project we create is a 'console application' where Program is our startup object. My apologies for the nasty black marking (using Snipping Tool and I rather don't mention too much internal details).

Where to get TopShelf?

We get TopShelf from Nuget. Simply use the 'Package Manager UI' or run the following command in the 'Package Manager Console':

Install-Package Topshelf -Version 3.1.1

Creating the service

Before telling you how host your services using the Topshelf Hosting Framework we have to create the service.
The service looks like this.

namespace <YOURNAMESPACE>
{
    public class Service
    {
        public Service()            
        { 
        }

        public void Start()
        {
             /* DO WORK HERE */
        }

        public void Stop()
        {
            /* DO CLEANUP HERE */
        }
    }
}

It's important to properly dispose of objects you created or threads you have started when calling Stop(). On more than one occasion we write multithreaded services and if we don't cleanup threads nicely in this phase, we might get sharing violations when we try to copy over a new version of the service.

Hosting the service

The final thing we need to do is the actual hosting of this service using TopShelf. This happens in the Program.cs file.

using Topshelf;

namespace <YOURNAMESPACE>
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            HostFactory.Run(x =>
            {
                x.Service<Service>(s =>
                {
                    s.ConstructUsing(() =>
                    {
                        Bootstrapper.Run();
                        return new Service();
                    });
                    s.WhenStarted(tc => tc.Start());
                    s.WhenStopped(tc => tc.Stop());
                });

                x.SetDisplayName("<YOUR SERVICE DISPLAY NAME>");
                x.SetServiceName("<YOUR SERVICE NAME>");
                x.SetDescription("<YOUR SERVICE DESCRIPTION>");

                // Service Identity

                x.RunAsLocalSystem();

                // Advanced Settings

                //// Specifies that the service supports the shutdown service command, allowing the services control manager to quickly shutdown the service.
                x.EnableShutdown();

                // Service recovery plan
                x.EnableServiceRecovery(rc =>
                {
                    rc.RestartService(1); // restart the service after 1 minute
                });
            });
        }
    }
}

It's very important that you run all initialization logic for your service in the ConstructUsing block. Running it outside of the Topshelf initialization might lead to unexpected behavior.
Our initialization happens in a Bootstrapper static class. So this is called first thing when entering the ConstructUsing method.

All other options are described either in code, and a lot more can be found on the TopShelf documentation site.

And the result is what exactly?

As a developer we can simply debug the console application. No windows service is installed. When working on a specific issue we can run the services by running their console variant. On our servers we can copy the bin output and by running a simple command the service is installed and configured. No more need to create a service installation file.

"Path to your.exe" install

Other calls we often make are 'stop' and 'start'. This is very handy stuff when you integrate this in your continuous delivery story.

Installing RabbitMQ on Windows

A brief post on how to install RabbitMQ on your Windows server.

Install Erlang

Erlang is a programming language used to build massively scalable soft real-time systems with requirements on high availability. Some of its uses are in telecoms, banking, e-commerce, computer telephony and instant messaging. Erlang's runtime system has built-in support for concurrency, distribution and fault tolerance.

http://www.erlang.org/

  1. Download the binary for your system.
    There are 32 bit and 64 bit binaries available.
  2. Copy the binary to the server (if you haven't downloaded it directly from the server of course) and run it.
  3. Choose components, Documentation is not required and can be unchecked.

  4. Choose installation location, default installation should be ok.

  5. Choose the start menu location.

  6. When you continue and choose 'Install' Visual C++ 2010 components will be installed.
    Go ahead and install them.

  7. Once this is done, Erlang installation continues and should finish successfully.
  8. Remote the setup binary from your system.

 Erlang is installed and is running. We can now install RabbitMQ.

 

Install RabbitMQ

RabbitMQ provides robust messaging for applications. It is easy to use and runs on all major operation systems. It supports a huge number of developer platforms, is open source and commercially supported.

http://www.rabbitmq.com/

  1.  Download the windows binary.
  2. Choose the components to install.

  3. Choose the installation location.

  4. The installation completes.
  5. Don't forget to remove the setup binary (I just like my servers clean).

Installing the RabbitMQ Management Plugin

By default you can manage your rabbitmq installation using the command prompt. There is an other option and that is the Administration plugin which provides an HTTP-based API for management and monitoring your RabbitMQ installation, along with a browser-based UI and a command line tool.

http://www.rabbitmq.com/management.html

  1. Start a RabbitMQ commandprompt.
    This should be available through the start menu.

  2. The command to install the management plugin is:
    rabbitmq-plugins enable rabbitmq_management
    The result should ask you to restart the RabbitMQ for changes to take effect.

  3. Restart RabbitMQ as asked. Advised way is to stop and start the RabbitMQ service.
    Either through the ‘windows services’-snapin, or using the RabbitMQ options in the start menu.

 

You can now browse to your RabbitMQ administration page by pointing the browser's url to:
http://<server-name>:15672 where 15672 is the default port.

The default username is 'guest' and the default password is 'guest'.

Congratulations, you have now installed RabbitMQ and can investigate the administration options in detail.