context: using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Configuration.Install;
  using System.Diagnostics;
  using System.Linq;
  using System.Reflection;
  using System.Runtime.InteropServices;
  using System.Security.Permissions;
  using System.Security.Principal;
  using System.ServiceProcess;
  
  namespace EasyService
  {
      /// <summary>
      /// SCM communication class
      /// </summary>
      public static class ScmController
      {
          #region Service Management
  
          /// <summary>
          /// Checks if service is installed.
          /// </summary>
          public static bool IsInstalled(string serviceName)
          {
              return ServiceController
                  .GetServices()
                  .Any(service => service.ServiceName == serviceName);
          }
  
          /// <summary>
          /// Starts the service if it is not running.
          /// </summary>
          public static void Start(string serviceName)
          {
              using (var sc = new ServiceController(serviceName))
              {
                  ServiceControllerStatus status = sc.Status;
  
                  if (status == ServiceControllerStatus.Running)
                  {
                      return;
                  }
  
                  if (status == ServiceControllerStatus.StartPending)
                  {
                      return;
                  }
  
                  if (!IsAdministrator())
                  {
                      if (RerunAsAdministrator())
                          return;
  
                      throw new InvalidOperationException("The service can only be started by administrator");
                  }
  
                  sc.Start();
                  sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
  
                  sc.Refresh();
                  status = sc.Status;
  
                  if (status != ServiceControllerStatus.Running)
                  {
                      throw new InvalidOperationException("Service failed to start in timely manner.");
                  }
              }
          }
  
          /// <summary>
          /// Stops the service if it is running.
          /// </summary>
          public static void Stop(string serviceName)
          {
              using (var sc = new ServiceController(serviceName))
              {
                  ServiceControllerStatus status = sc.Status;
  
                  if (status == ServiceControllerStatus.Stopped)
                  {
                      return;
                  }
  
                  if (status == ServiceControllerStatus.StopPending)
                  {
                      return;
                  }
  
                  if (IsAdministrator())
                  {
                      if (RerunAsAdministrator())
                          return;
                      throw new InvalidOperationException("The service can only be stopped by administrator");
                  }
  
                  sc.Stop();
                  sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
  
                  sc.Refresh();
                  status = sc.Status;
  
                  if (status != ServiceControllerStatus.Stopped)
                  {
                      throw new InvalidOperationException("Service failed to stop in timely manner.");
                  }
              }
          }
          #endregion
  
          #region Installer
  
          private static Installer CreateInstaller(
                  string serviceName,
                  string serviceDisplayName,
                  string serviceDescription,
                  ServiceStartMode startMode,
                  ServiceAccount serviceAccount,
                  IEnumerable<ServiceDependency> dependencies,
                  ServiceRecoveryOptions recoveryOptions
              )
          {
              ServiceProcessInstaller spi = new ServiceProcessInstaller();
  
              spi.Account = (System.ServiceProcess.ServiceAccount)(int)serviceAccount.AccountType;
  
              if (serviceAccount.AccountType == ServiceAccountType.User)
              {
                  spi.Username = serviceAccount.Username;
                  spi.Password = serviceAccount.Password;
              }
  
              string[] servicesDependedOn;
  
              if (dependencies == null)
              {
                  servicesDependedOn = new string[0];
              }
              else
              {
                  servicesDependedOn = dependencies.Select(d => d.ServiceName).ToArray();
              }
  
              ServiceInstaller si = new ServiceInstaller
                                        {
                                            ServiceName = serviceName,
                                            DisplayName = serviceDisplayName,
                                            Description = serviceDescription,
                                            ServicesDependedOn = servicesDependedOn,
                                            StartType = (System.ServiceProcess.ServiceStartMode)(int)startMode
                                        };
  
              var installer = new Installer();
              installer.Installers.Add(spi);
              installer.Installers.Add(si);
  
              installer.Committed += delegate 
                                         {
                                             ScmController.SetServiceRecoveryOptions(serviceName, recoveryOptions);
                                         };
  
              string path = String.Format("/assemblypath={0}", Assembly.GetEntryAssembly().Location);
              string[] cmdline = { path, "/LogtoConsole=false" }; //disable installer output
  
              TransactedInstaller ti = new TransactedInstaller();
              ti.Installers.Add(installer);
              ti.Context = new InstallContext(null, cmdline);
  
              return ti;
          }
  
          /// <summary>
          /// Registers service in SCM.
          /// </summary>
          public static void Install(
                  string serviceName,
                  string serviceDisplayName,
                  string serviceDescription,
                  ServiceStartMode startMode,
                  ServiceAccount serviceAccount,
                  IEnumerable<ServiceDependency> dependencies,
                  ServiceRecoveryOptions recoveryOptions
              )
          {
              using (Installer ti = CreateInstaller(serviceName, serviceDisplayName, serviceDescription, startMode, serviceAccount, dependencies, recoveryOptions))
              {
                  if (IsInstalled(serviceName))
                  {
                      throw new InvalidOperationException("The service is already installed.");
                  }
  
                  if (!IsAdministrator())
                  {
                      if (RerunAsAdministrator())
                          return;
  
                      throw new InvalidOperationException("The service can only be installed by administrator");
                  }
                  
                  ti.Install(new System.Collections.Hashtable());
              }
          }
  
          /// <summary>
          /// Removes service from SCM.
          /// </summary>
          public static void Uninstall(
                  string serviceName,
                  string serviceDisplayName,
                  string serviceDescription,
                  ServiceStartMode startMode,
                  ServiceAccount serviceAccount,
                  IEnumerable<ServiceDependency> dependencies,
                  ServiceRecoveryOptions recoveryOptions
              )
          {
              using (Installer ti = CreateInstaller(serviceName, serviceDisplayName, serviceDescription, startMode, serviceAccount, dependencies, recoveryOptions))
              {
                  if (!IsInstalled(serviceName))
                  {
                      throw new InvalidOperationException("The service is not installed.");
                  }
  
                  if (!IsAdministrator())
                  {
                      if (RerunAsAdministrator())
                          return;
  
                      throw new InvalidOperationException("The service can only be uninstalled by administrator");
                  }
  
                  ti.Uninstall(null);
              }
          }
  
          #endregion
  
          #region User Account Elevation
  
          private static bool IsAdministrator()
          {
              WindowsIdentity identity = WindowsIdentity.GetCurrent();
  
              if (null != identity)
              {
                  var principal = new WindowsPrincipal(identity);
                  return principal.IsInRole(WindowsBuiltInRole.Administrator);
              }
  
              return false;
          }
  
          private static bool RerunAsAdministrator()
          {
              if (Environment.OSVersion.Version.Major == 6)
              {
                  var startInfo = new ProcessStartInfo
                  {
                      Verb = "runas",
                      UseShellExecute = true,
                      CreateNoWindow = true,
                      FileName = Assembly.GetEntryAssembly().Location,
                      Arguments = string.Join(" ", Environment.GetCommandLineArgs().Skip(1)),
                      WorkingDirectory = Environment.CurrentDirectory,
                  };
  
                  try
                  {
  
gt:                     Process process = Process.Start(startInfo);