PRSServiceInstaller.cs 5.8 KB

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