Simple WCF service hosted in Windows service

S

WFC services are a good way to spit a complex and demanding application into smaller parts and use more system resources, but not only. In the literature there are several information why you should use WFC (ex: Distributed apps in a local network etc)… In this example you will find a complete Visual studio project which hosts a wcf service inside a windows service.

Our service has two exposed methods (but you can add yours):
public string Echo(string text)
public string GetServiceName()

Moreover our Windows service will be able to install and uninstall itself directly by using startup args:
MyService.exe -install
MyService.exe -uninstall

Let’s Start

Open Visual Studio (2019) and create a new C# Windows Service project
Put your desired name of your project
  • Before start putting our code we have to perform some configurations as described below:
In the project properties: set the manifest to (Create application without a manifest)
Delete all the autogenerated files (Don’t worry we will create our own)

The first file we will create is the ServiceConfiguration.cs which will contain some information regarding our service that will be needed later on in the project

using System.Reflection;

namespace MyService
{
    public static class ServiceConfiguration
    {
        public static readonly string ServiceName = "MyService";
        public static readonly string ExecutingAssebmlyLocation = Assembly.GetExecutingAssembly().Location;
        public static readonly string UrlPort = "8000";
    }
}

The second file we will create is the ProjectInstaller.cs and it should contail all the information that the project needs to install and uninstall our service

using System;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;

namespace MyService
{
    [RunInstaller(true)]
    public class ProjectInstaller : Installer
    {
        private ServiceProcessInstaller process;
        private ServiceInstaller service;

        public ProjectInstaller()
        {
            process = new ServiceProcessInstaller();
            process.Account = ServiceAccount.LocalSystem;
            service = new ServiceInstaller();
            service.ServiceName = ServiceConfiguration.ServiceName;
            service.StartType = ServiceStartMode.Automatic;
            Installers.Add(process);
            Installers.Add(service);
        }

        public static bool Install()
        {
            try
            {
                ManagedInstallerClass.InstallHelper(new string[] {ServiceConfiguration.ExecutingAssebmlyLocation });
                StartService(ServiceConfiguration.ServiceName, 7000);
            }
            catch
            {
                return false;
            }
            return true;
        }

        public static bool Uninstall()
        {
            StopService(ServiceConfiguration.ServiceName, 7000);
            try
            {
                ManagedInstallerClass.InstallHelper(new string[] { "/u", ServiceConfiguration.ExecutingAssebmlyLocation });
            }
            catch
            {
                return false;
            }
            return true;
        }

        public static void StartService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(timeoutMilliseconds));
            }
            catch (Exception ex)
            {
                //....
            }
        }

        public static void StopService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);
            try
            {
                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(timeoutMilliseconds));
            }
            catch (Exception ex)
            {
                //....
            }
        }
    }
}

Now we will create the WCFService.cs which will contain our actual service

using System.ServiceModel;

namespace MyService
{
    [ServiceContract(Namespace = "http://MyService")]
    public interface IWCFService
    {
        [OperationContract]
        string Echo(string text);
        [OperationContract]
        string GetServiceName();
    }

    public class WCFService : IWCFService
    {
        public string Echo(string text)
        {
            return text;
        }

        public string GetServiceName()
        {
            return ServiceConfiguration.ServiceName;
        }
    }
}

And finally, our last file WService.cs hosting the source code of the Window Service

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceProcess;

namespace MyService
{
    public class WService : ServiceBase
    {
        public ServiceHost serviceHost = null;
        public WService()
        {
            ServiceName = ServiceConfiguration.ServiceName;
        }

        public static void Main(string[] args)
        {
            if (args != null && args.Length != 0 && args[0].Length >= 1 && (args[0][0] == '-' || args[0][0] == '/'))
            {
                switch (args[0].Substring(1).ToLower())
                {
                    default:
                        break;
                    case "i":
                        ProjectInstaller.Install();
                        break;
                    case "u":
                        ProjectInstaller.Uninstall();
                        break;
                }
            }
            else
            {
                ServiceBase.Run(new WService());
            }
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                if (serviceHost != null)
                    serviceHost.Close();

                Uri httpBaseAddress = new Uri($"http://{System.Net.Dns.GetHostName()}:{ServiceConfiguration.UrlPort}/{ServiceConfiguration.ServiceName}/service");

                serviceHost = new ServiceHost(typeof(WCFService), httpBaseAddress);

                WSHttpBinding wsHttpBinding = new WSHttpBinding();
                wsHttpBinding.MaxReceivedMessageSize = 70000;
                wsHttpBinding.MessageEncoding = WSMessageEncoding.Text;

                serviceHost.AddServiceEndpoint(typeof(IWCFService), wsHttpBinding, "");
                serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });

                serviceHost.Open();
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry(ex.ToString());
            }
        }

        protected override void OnStop()
        {
            if (serviceHost != null)
            {
                serviceHost.Close();
                serviceHost = null;
            }
        }
    }
}

Now if you open a command line (admin rights) and navigate to your executable, you can write MyService.exe -i or MyService -u to install and run or stop and uninstall your service

github

https://github.com/devcoons/example-wcf-windows-service

Add comment

Categories

Subscribe to our Newsletter

Tags