How To Convert Existing C# Application Into Windows Service

In this blog, I will be demonstrating the process of converting an existing exe application into a Windows Service using multiple steps - Windows Services creation, launching of the exe in hidden mode when services start, log the information using event log, and also, write the unit tests to test Windows Service.
 
Let's start with Visual Studio to create one .exe application.
 
Open VS, go to File > New and select Project. Now, select a new project from the dialog box and create a new .NET Framework console application (for example, Myexe) and add the below logic to test that this exe was called from Windows Service. 
  1. static void Main(string[] args)  
  2. {  
  3.     using (var sw = new StreamWriter(args[0]))  
  4.     {  
  5.         sw.WriteLine("Welcome to Windows service in .net");  
  6.     }  
  7.     Console.Readkey();  
  8. }  
Now, let's create a Windows Service using Visual Studio. So, go to File > New and select Project as “Window Service”. I am creating this project under the same solution, but you can try with a new solution too.
 
 
 
The next step is to add an installer for this Windows Service. Right-click on the blank area and select "Add installer". This installer registers the service to the control manager.
 
Open ProjectInstaller.Designer.cs => InitializeComponent() to update the service name, display name and description of the service, as shown below. And set the account as LocalSystem; else, it will prompt for username and password during installation.
  1.    private void InitializeComponent()  
  2.      {  
  3.           this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();  
  4.             this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();  
  5.             //   
  6.             // serviceProcessInstaller1  
  7.             //   
  8.             this.serviceProcessInstaller1.Password = null;  
  9.             this.serviceProcessInstaller1.Username = null;  
  10.             this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;  
  11.             //   
  12.             // serviceInstaller1  
  13.             //   
  14.             this.serviceInstaller1.ServiceName = "MyWindowservice";  
  15.             this.serviceInstaller1.Description = "MyWindowservice Description";  
  16.             this.serviceInstaller1.DisplayName = "MyWindowservice";  
  17.             this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;  
  18.   
  19.             //   
  20.             // ProjectInstaller  
  21.             //   
  22.             this.Installers.AddRange(new System.Configuration.Install.Installer[] {  
  23.             this.serviceProcessInstaller1,  
  24.             this.serviceInstaller1});  
  25.   
  26.         }  
Now, we will implement the real service where we launch the .exe created in step1 when this Windows Service starts.
  • Open your service class(in my case MyWindowService.Designer.cs) and you should be having two default methods - OnStart & OnStop().
  • Use event logger to log the Windows Service information.
  • Go to the InitializeComponent method and initialize the event logger.
  1.         /// <summary>   
  2.         /// Required method for Designer support - do not modify   
  3.         /// the contents of this method with the code editor.  
  4.         /// </summary>  
  5.         private void InitializeComponent()  
  6.         {  
  7.             components = new System.ComponentModel.Container();  
  8.             this.eventLogger = new System.Diagnostics.EventLog();  
  9.             ((System.ComponentModel.ISupportInitialize)(this.eventLogger)).BeginInit();  
  10.             //   
  11.             // SystemManagerService  
  12.             //   
  13.             this.CanHandleSessionChangeEvent = true;  
  14.             this.ServiceName = "MyWindowService";  
  15.             ((System.ComponentModel.ISupportInitialize)(this.eventLogger)).EndInit();  
  16.   
  17.         }  
  18.  
  19.         #endregion  
  20.   
  21.         private System.Diagnostics.EventLog eventLogger;  
Now, write the implementations of two default methods, i.e., OnStart and OnStop.
  • OnStart starts a new process to launch the .exe created in step1. The .exe execution must be written into the file to verify that our service is started and the task manager should have an entry for Myexe.
  • OnStop is used to stop the service which kills the process. Verify in the task manager that the service is stopped.
  • Use eventLogger.WriteEntry to log any information.
The below code snippet represents the main service class with those two methods. 
  1. public partial class MyWindowService : ServiceBase  
  2.    {  
  3.        private int processId;  
  4.        private string filePath;  
  5.   
  6.        public MyWindowService()  
  7.        {  
  8.            InitializeComponent();  
  9.        }  
  10.   
  11.        public void Verify(string[] args)  
  12.        {  
  13.            this.OnStart(args);  
  14.   
  15.            // do something here...  
  16.   
  17.            this.OnStop();  
  18.        }  
  19.   
  20.        protected override void OnStart(string[] args)  
  21.        {  
  22.            var location = new Uri(Assembly.GetEntryAssembly().CodeBase).LocalPath;  
  23.            var path = Path.GetDirectoryName(location);  
  24.            var serverPath = Path.Combine(path, "MyExe.exe");  
  25.            Process cmd = new Process();  
  26.            cmd.StartInfo.FileName = serverPath;  
  27.            cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;  
  28.            using (var f = File.Create(Path.Combine(path, "TestFile.txt")))  
  29.            {  
  30.                filePath = f.Name;  
  31.            }  
  32.   
  33.            cmd.StartInfo.Arguments = filePath;  
  34.            cmd.Start();  
  35.            processId = cmd.Id;  
  36.        }  
  37.   
  38.        protected override void OnStop()  
  39.        {  
  40.            Process process = null;  
  41.            try  
  42.            {  
  43.                process = Process.GetProcessById((int)processId);  
  44.            }  
  45.            finally  
  46.            {  
  47.                if (process != null)  
  48.                {  
  49.                    process.Kill();  
  50.                    process.WaitForExit();  
  51.                    process.Dispose();  
  52.                }  
  53.   
  54.                File.Delete(filePath);  
  55.            }  
  56.        }  
  57.    }  
Now rebuild your application, I have defined the same Output Directory Pathfor my both projects. 
 
Now its time to Install the Service and verify it.
 
Run the command prompt in administrator mode and run the below script.

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319

Install/Uninstall Windows Service
 
We have InstallUtil.exe which comes with installation of ,net framework to install windows service.
  • Run below command to register service.
    InstallUtil.exe OutputDirectoryPath + \your service name + .exe and press enter

  • Run below command to unregister service whenever you want to remove it.
    InstallUtil.exe -u OutputDirectoryPath + \your service name + .exe and press enter 
 
 
Verify your service by executing command "Services.msc", you should find you service if the installation was successful.
 
 
 
Once the service is started, then I can find my txt file which was executed by Myexe which verifies that service was started.
 
 
 
Once the service is stopped, txt file must be deleted, which verifies that service has been stopped and no process(myexe) is running.
 

How to test/debug windows service

 
It is very simple to debug your Windows Service by creating a new Console application and introduce a new public method in your service which calls OnStart and OnStop methods internally.
  1. class Program  
  2.    {  
  3.        static void Main(string[] args)  
  4.        {  
  5.            var myService = new MyWindowService.MyWindowService();  
  6.            myService.Verify(args);  
  7.        }  
  8.    }  
  9.  
  1. public partial class MyWindowService : ServiceBase
  2. {
  3.  public void Verify(string[] args)
  4.  {
  5.    this.OnStart(args);
  6.    // do something here...
  7.    this.OnStop();
  8.  }
  9. }
 
 

Summary

 
This article demonstrated how to create Windows Services to launch any existing exe/process and installing/uninstalling of services and how to test Windows Service.