PRSServiceInstaller.cs 4.8 KB

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