PRSServiceInstaller.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Configuration.Install;
  4. using System.Reflection;
  5. using System.ServiceProcess;
  6. namespace PRSServices;
  7. // Class to manage the installation of services
  8. public class PRSServiceInstaller
  9. {
  10. public static Assembly Assembly { get; set; }
  11. public static bool IsInstalled(string serviceName)
  12. {
  13. return ServiceController.GetServices().Any(s => s.ServiceName == serviceName);
  14. }
  15. public static bool IsRunning(string serviceName)
  16. {
  17. using (var controller =
  18. new ServiceController(serviceName))
  19. {
  20. if (!IsInstalled(serviceName)) return false;
  21. return controller.Status == ServiceControllerStatus.Running;
  22. }
  23. }
  24. private static AssemblyInstaller GetInstaller(string serviceName, string description, string displayName, string? username, string? password)
  25. {
  26. // The arguments passed here are received by PRSInstaller, which it uses to set service metadata.
  27. // /name=servicename is *REQUIRED* because otherwise Windows can't find the service in the executable.
  28. var installProperties = new List<string>
  29. {
  30. "/name=" + serviceName,
  31. "/description=" + description,
  32. "/displayName=" + displayName
  33. };
  34. if(!string.IsNullOrWhiteSpace(username))
  35. {
  36. installProperties.Add("/username=" + username);
  37. installProperties.Add("/password=" + (password ?? ""));
  38. }
  39. var installer = new AssemblyInstaller(Assembly, installProperties.ToArray());
  40. installer.UseNewContext = true;
  41. return installer;
  42. }
  43. private static AssemblyInstaller GetUninstaller(string serviceName)
  44. {
  45. // The argument passed here is received by PRSInstaller. /name=serviceName is used to find the serviceName
  46. // in the PRSServer.exe, which can then execute the uninstaller.
  47. var installer = new AssemblyInstaller(Assembly, new[] { "/name=" + serviceName });
  48. installer.UseNewContext = true;
  49. return installer;
  50. }
  51. public static void InstallService(string serviceName, string description, string displayName, string? username, string? password)
  52. {
  53. if (IsInstalled(serviceName)) return;
  54. using var installer = GetInstaller(serviceName, description, displayName, username, password);
  55. IDictionary state = new Hashtable();
  56. try
  57. {
  58. installer.Install(state);
  59. installer.Commit(state);
  60. }
  61. catch
  62. {
  63. try
  64. {
  65. //installer.Rollback(state);
  66. }
  67. catch
  68. {
  69. }
  70. throw;
  71. }
  72. }
  73. public static void UninstallService(string serviceName)
  74. {
  75. if (!IsInstalled(serviceName)) return;
  76. using var installer = GetUninstaller(serviceName);
  77. IDictionary state = new Hashtable();
  78. installer.Uninstall(state);
  79. }
  80. public static void ChangeService(string serviceName, string description, string displayName, string? username, string? password)
  81. {
  82. if (IsInstalled(serviceName)) UninstallService(serviceName);
  83. InstallService(serviceName, description, displayName, username, password);
  84. /*
  85. // Delegate the configuration of the service to sc.exe, and execute.
  86. // I haven't found a way to do it without using sc.exe. (Unless we decided to change the registry, which is surely a bad idea.)
  87. // Convert quotes and backslashes to escaped quotes and backslashes
  88. var newServiceName = serviceName.Replace("\"", "\\\"").Replace("\\", "\\\\");
  89. var newDisplayName = displayName.Replace("\"", "\\\"").Replace("\\", "\\\\");
  90. var newDescription = description.Replace("\"", "\\\"").Replace("\\", "\\\\");
  91. RunCommand("sc.exe", "description \"" + newServiceName + "\" \"" + newDescription + "\"");
  92. RunCommand("sc.exe", "config \"" + newServiceName + "\" displayname=\"" + newDisplayName + "\"");
  93. */
  94. }
  95. public static void StartService(string serviceName)
  96. {
  97. if (!IsInstalled(serviceName)) return;
  98. using var controller =
  99. new ServiceController(serviceName);
  100. if (controller.Status != ServiceControllerStatus.Running)
  101. {
  102. controller.Start();
  103. controller.WaitForStatus(ServiceControllerStatus.Running,
  104. TimeSpan.FromSeconds(10));
  105. }
  106. }
  107. public static void StopService(string serviceName)
  108. {
  109. if (!IsInstalled(serviceName)) return;
  110. using var controller =
  111. new ServiceController(serviceName);
  112. if (controller.Status != ServiceControllerStatus.Stopped)
  113. {
  114. controller.Stop();
  115. controller.WaitForStatus(ServiceControllerStatus.Stopped,
  116. TimeSpan.FromSeconds(10));
  117. }
  118. }
  119. }