Hosting in a Windows Service

Component: NServiceBus
NuGet Package NServiceBus (7-pre)
This page targets a pre-release version and is subject to change prior to the final release.

Code walk-through

This sample shows how to host NServiceBus as a Windows service in process with support for streamlined debugging experience from Visual Studio.

NServiceBus comes with a host executable that abstracts much of the hosting complexity. Its features include installation, un-installation and configuring the Windows service. It provides these features though custom code and the use of libraries like TopShelf. Since the NServiceBus Host is a general solution with dependencies there are some things to keep in mind while using it.

The sample is a console application whose Main entry point detects if the application is run in interactive mode or not. When run in interactive mode, the service is manually created and invoked as any other C# class instance, otherwise the Run method is called to invoke the base ServiceBase class API.

static void Main()
    using (var service = new ProgramService())
        if (ServiceHelper.IsService())

        Console.Title = "Samples.WindowsServiceAndConsole";

        Console.WriteLine("Bus started. Press any key to exit");


The OnStart method, manually called when running in interactive mode and automatically called by the Windows service when running as a service, configures the Endpoint Instance:

protected override void OnStart(string[] args)

async Task AsyncOnStart()
    var endpointConfiguration = new EndpointConfiguration("Samples.WindowsServiceAndConsole");
    endpointInstance = await Endpoint.Start(endpointConfiguration)
    // run any startup actions on the bus
    var myMessage = new MyMessage();
    await endpointInstance.SendLocal(myMessage)

When the interactive application is shut down or the Windows service is stopped, the OnStop method is called to perform the required clean up:

protected override void OnStop()


To detect if the current process is running as a service the parent process is checked.

Since Environment.UserInteractive always returns true on .NET Core, ServiceHelper.IsService() is used to provide a dual console/service experience, i.e. this process can be executed from the command line or run as a Windows service. Note that if there is no intention to target .NET Core, then Environment.UserInteractive can be used.
static class ServiceHelper
    public static bool IsService()
        using (var process = GetParent(Process.GetCurrentProcess()))
            return process != null && process.ProcessName == "services";

    static Process GetParent(Process child)
        var parentId = 0;

        var handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        if (handle == IntPtr.Zero)
            return null;

        var processInfo = new PROCESSENTRY32
            dwSize = (uint) Marshal.SizeOf(typeof(PROCESSENTRY32))

        if (!Process32First(handle, ref processInfo))
            return null;

            if (child.Id == processInfo.th32ProcessID)
                parentId = (int) processInfo.th32ParentProcessID;
        } while (parentId == 0 && Process32Next(handle, ref processInfo));

        if (parentId > 0)
            return Process.GetProcessById(parentId);
        return null;

    static uint TH32CS_SNAPPROCESS = 2;

    public static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);

    public static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    public struct PROCESSENTRY32
        public uint dwSize;
        public uint cntUsage;
        public uint th32ProcessID;
        public IntPtr th32DefaultHeapID;
        public uint th32ModuleID;
        public uint cntThreads;
        public uint th32ParentProcessID;
        public int pcPriClassBase;
        public uint dwFlags;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szExeFile;

Service Management

Management is done using the Service Control tool.

See also windows-service installation.


sc.exe create nsbSample binpath= "\"[Full Directory]\Sample.exe\""


sc.exe delete nsbSample

.NET Core

.NET Core has some extra caveats to consider when using it in a Windows service.


The ServiceBase functionality is provided by the System.ServiceProcess.ServiceController package.

Via a self contained exe

To use the installation approach described above, a self contained exe is required. dotnet-publish can be used to produce an exe from a .NET Core console project. This can be done by using the following command from the Package Manager Console:

dotnet publish WindowsServiceHosting.Core.sln --framework netcoreapp2.0 --runtime win10-x64

Sample.Core.exe will then exist in Sample\bin\Debug\netcoreapp2.0\win10-x64\publish.

Via dotnet.exe

A .NET Core console application project will, by default, produce a dll. The console application can be executed via the dotnet command. When used with sc create this equates to the following command:

sc.exe create nsbSample binpath= "\"C:\Program Files\dotnet\dotnet.exe\" \"[Full Directory]\Sample.Core.dll\""


Related Articles

Last modified