65.9K
CodeProject is changing. Read more.
Home

Methods to Help Working with Services

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (8 votes)

Jun 13, 2018

CPOL
viewsIcon

6410

This is a set of methods to help in working with Services on the local machine.

Introduction

I was working on a custom installer for a Windows Service pretty much starting from the beginning. One of the issues I had was the code to determine if service exists, starting, stopping, finding the path, and finding the version. This is just a tip that includes the static methods I used. There are more complete methods, but these methods should do for most of what is encountered.

The Code

This is the class that I used for all of the methods used with Windows Services:

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.ServiceProcess;

namespace InstallApplication
{
    class ServiceMethods
    {
        public static void InstallService(string strInstallService, bool unistall = false)
        {
            InstallService(strInstallService, null, null, unistall);
        }

        public static void InstallService(string strInstallService, string userName, 
			string password = null, bool unistall = false )
        {
            var executeType = unistall ? "u" : "i";
            var userInfo = userName == null ? string.Empty : 
			string.Format(" \"/username={0}\" \"/password={1}\"", userName, password);
            string strInstallUtilPath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(),
			 @"InstallUtil.exe");
            if (!File.Exists(strInstallUtilPath))
                throw new FileNotFoundException(string.Format
			("Install Utility path not found: \"{0}\""));
            if (!File.Exists(strInstallService))
                throw new FileNotFoundException(string.Format(
			"Install Service path not found: \"{0}\""));

            ProcessStartInfo processStartInfo = new ProcessStartInfo(strInstallUtilPath, 
			String.Format("/{1} \"{0}\"{2}", strInstallService, executeType, userInfo));
            processStartInfo.RedirectStandardOutput = true;
            processStartInfo.RedirectStandardError = true;
            processStartInfo.UseShellExecute = false;

            Process process = new Process();
            process.StartInfo = processStartInfo;
            process.Start();
            process.WaitForExit();

            if (process.ExitCode == -1)
                throw new Exception(process.StandardOutput.ReadToEnd());
        }

        public static bool ServiceExists(string serviceName)
        {
            //Avoid exceptions this way
            return ServiceController.GetServices().Any(i => i.ServiceName == serviceName);
        }

        public static void ServiceStart(string serviceName)
        {
            using (ServiceController service = new ServiceController(serviceName))
            {
                try
                {
                    if (service.Status == ServiceControllerStatus.Running) return;
                    service.Start();
                    service.WaitForStatus(ServiceControllerStatus.Running);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Failed to start the Windows Service {0}", 
			serviceName), ex);
                }
            }
        }

        public static void ServiceStop(string serviceName)
        {
            using (ServiceController service = new ServiceController(serviceName))
            {
                try
                {
                    if (service.Status == ServiceControllerStatus.Stopped) return;
                    service.Stop();
                    service.WaitForStatus(ServiceControllerStatus.Stopped);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Failed to stop the Windows Service {0}", 
			serviceName), ex);
                }
            }
        }

        public static void ServiceRefresh(string serviceName)
        {
            using (ServiceController service = new ServiceController(serviceName))
            {
                try
                {
                    if (service.Status == ServiceControllerStatus.Running)
                    {
                        service.Stop();
                        service.WaitForStatus(ServiceControllerStatus.Stopped);
                    }

                    service.Start();
                    service.WaitForStatus(ServiceControllerStatus.Running);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Failed to restart the Windows Service {0}", 
			serviceName), ex);
                }
            }
        }

        public static string ServicePath(string serviceName)
        {
            try
            {
                string registryPath = @"SYSTEM\CurrentControlSet\Services\" + serviceName;
                var key = Registry.LocalMachine.OpenSubKey(registryPath);
                string value = key.GetValue("ImagePath").ToString();
                key.Close();
                return value[0] == '\"' ? value.Substring(1, value.Length - 2) : value;
            }
            catch (Exception ex)
            {
                 throw new Exception(string.Format(
			"Error in attempting to get Registry key for service {0}", serviceName), ex);
            }
        }

        public static FileVersionInfo ServiceVersion(string serviceName)
        {
            return FileVersionInfo.GetVersionInfo(ServicePath(serviceName));
        }
    }
}

History

  • 2018-06-13: Initial version
  • 2018-06-15: Updated Service Install to include optional password and username