PageRenderTime 57ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.ServiceProcess/System.ServiceProcess/ServiceController.cs

https://github.com/iainlane/mono
C# | 456 lines | 339 code | 58 blank | 59 comment | 43 complexity | 93b6ec3f03efdf33f0f0b3438e96e033 MD5 | raw file
  1. //
  2. // System.ServiceProcess.ServiceController
  3. //
  4. // Authors:
  5. // Marek Safar (marek.safar@seznam.cz)
  6. // Gert Driesen (drieseng@users.sourceforge.net)
  7. //
  8. // (C) 2005, Marek Safar
  9. //
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. // TODO: check if there's more information to cache (eg. status)
  31. // Start / Stop / ...
  32. using System;
  33. using System.ComponentModel;
  34. using System.Globalization;
  35. #if NET_2_0
  36. using System.Runtime.InteropServices;
  37. #endif
  38. using System.ServiceProcess.Design;
  39. using System.Threading;
  40. namespace System.ServiceProcess
  41. {
  42. [Designer("System.ServiceProcess.Design.ServiceControllerDesigner, " + Consts.AssemblySystem_Design)]
  43. [MonoTODO ("No unix implementation")]
  44. #if NET_2_0
  45. [ServiceProcessDescription ("Provides the ability to connect to, query, and manipulate running or stopped Windows services.")]
  46. #endif
  47. public class ServiceController : Component
  48. {
  49. private string _name;
  50. private string _serviceName = string.Empty;
  51. private string _machineName;
  52. private string _displayName = string.Empty;
  53. private readonly ServiceControllerImpl _impl;
  54. private ServiceController [] _dependentServices;
  55. private ServiceController [] _servicesDependedOn;
  56. public ServiceController ()
  57. {
  58. _machineName = ".";
  59. _name = string.Empty;
  60. _impl = CreateServiceControllerImpl (this);
  61. }
  62. public ServiceController (string name) : this (name, ".")
  63. {
  64. }
  65. public ServiceController (string name, string machineName)
  66. {
  67. if (name == null || name.Length == 0)
  68. throw new ArgumentException (string.Format (CultureInfo.CurrentCulture,
  69. "Invalid value {0} for parameter name.", name));
  70. ValidateMachineName (machineName);
  71. _machineName = machineName;
  72. _name = name;
  73. _impl = CreateServiceControllerImpl (this);
  74. }
  75. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  76. [ServiceProcessDescription ("Whether this service recognizes the Pause and Continue commands.")]
  77. public bool CanPauseAndContinue {
  78. get {
  79. #if NET_2_0
  80. ValidateServiceName (ServiceName);
  81. #endif
  82. return _impl.CanPauseAndContinue;
  83. }
  84. }
  85. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  86. [ServiceProcessDescription ("Whether this service can respond to a system shutdown.")]
  87. public bool CanShutdown {
  88. get
  89. {
  90. #if NET_2_0
  91. ValidateServiceName (ServiceName);
  92. #endif
  93. return _impl.CanShutdown;
  94. }
  95. }
  96. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  97. [ServiceProcessDescription ("Whether this service can be stopped.")]
  98. public bool CanStop {
  99. get
  100. {
  101. #if NET_2_0
  102. ValidateServiceName (ServiceName);
  103. #endif
  104. return _impl.CanStop;
  105. }
  106. }
  107. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  108. [ServiceProcessDescription ("The services that depend on this service in order to run.")]
  109. public ServiceController [] DependentServices {
  110. get
  111. {
  112. #if NET_2_0
  113. ValidateServiceName (ServiceName);
  114. #endif
  115. if (_dependentServices == null)
  116. _dependentServices = _impl.DependentServices;
  117. return _dependentServices;
  118. }
  119. }
  120. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  121. [ReadOnly (true)]
  122. [ServiceProcessDescription ("The descriptive name of the service.")]
  123. public string DisplayName {
  124. get {
  125. if (_displayName.Length == 0 && (_serviceName.Length > 0 || _name.Length > 0))
  126. _displayName = _impl.DisplayName;
  127. return _displayName;
  128. }
  129. set {
  130. if (value == null)
  131. throw new ArgumentNullException ("value");
  132. if (_displayName == value)
  133. return;
  134. _displayName = value;
  135. // if display name is modified, then we also need to force a
  136. // new lookup of the corresponding service name
  137. _serviceName = string.Empty;
  138. // you'd expect the DependentServices and ServiceDependedOn cache
  139. // to be cleared too, but the MS implementation doesn't do this
  140. //
  141. // categorized as by design:
  142. // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=201762
  143. // release any handles and clear cache
  144. Close ();
  145. }
  146. }
  147. [Browsable (false)]
  148. [DefaultValue (".")]
  149. [RecommendedAsConfigurable (true)]
  150. [ServiceProcessDescription ("The name of the machine on which this service resides.")]
  151. public string MachineName {
  152. get {
  153. return _machineName;
  154. }
  155. set {
  156. ValidateMachineName (value);
  157. if (_machineName == value)
  158. return;
  159. _machineName = value;
  160. // you'd expect the DependentServices and ServiceDependedOn cache
  161. // to be cleared too, but the MS implementation doesn't do this
  162. //
  163. // categorized as by design:
  164. // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=201762
  165. // release any handles and clear cache
  166. Close ();
  167. }
  168. }
  169. [DefaultValue ("")]
  170. [ReadOnly (true)]
  171. [RecommendedAsConfigurable (true)]
  172. [ServiceProcessDescription ("The short name of the service.")]
  173. [TypeConverter (typeof (ServiceNameConverter))]
  174. public string ServiceName {
  175. get {
  176. if (_serviceName.Length == 0 && (_displayName.Length > 0 || _name.Length > 0))
  177. _serviceName = _impl.ServiceName;
  178. return _serviceName;
  179. }
  180. set {
  181. if (value == null)
  182. throw new ArgumentNullException ("value");
  183. if (_serviceName == value)
  184. return;
  185. #if NET_2_0
  186. ValidateServiceName (value);
  187. #endif
  188. _serviceName = value;
  189. // if service name is modified, then we also need to force a
  190. // new lookup of the corresponding display name
  191. _displayName = string.Empty;
  192. // you'd expect the DependentServices and ServiceDependedOn cache
  193. // to be cleared too, but the MS implementation doesn't do this
  194. //
  195. // categorized as by design:
  196. // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=201762
  197. // release any handles and clear cache
  198. Close ();
  199. }
  200. }
  201. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  202. [ServiceProcessDescription ("Services that must be started in order for this one to start.")]
  203. public ServiceController [] ServicesDependedOn {
  204. get
  205. {
  206. #if NET_2_0
  207. ValidateServiceName (ServiceName);
  208. #endif
  209. if (_servicesDependedOn == null)
  210. _servicesDependedOn = _impl.ServicesDependedOn;
  211. return _servicesDependedOn;
  212. }
  213. }
  214. #if NET_2_0
  215. [MonoTODO]
  216. [Browsable (false)]
  217. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  218. public SafeHandle ServiceHandle
  219. {
  220. get {
  221. throw new NotImplementedException ();
  222. }
  223. }
  224. #endif
  225. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  226. [ServiceProcessDescription ("The type of this service.")]
  227. public ServiceType ServiceType {
  228. get
  229. {
  230. #if NET_2_0
  231. ValidateServiceName (ServiceName);
  232. #endif
  233. return _impl.ServiceType;
  234. }
  235. }
  236. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  237. [ServiceProcessDescription ("The status of the service, e.g., Running or Stopped.")]
  238. public ServiceControllerStatus Status {
  239. get
  240. {
  241. #if NET_2_0
  242. ValidateServiceName (ServiceName);
  243. #endif
  244. return _impl.Status;
  245. }
  246. }
  247. public void Close ()
  248. {
  249. _impl.Close ();
  250. }
  251. public void Continue ()
  252. {
  253. #if NET_2_0
  254. ValidateServiceName (ServiceName);
  255. #endif
  256. _impl.Continue ();
  257. }
  258. protected override void Dispose (bool disposing)
  259. {
  260. _impl.Dispose (disposing);
  261. base.Dispose (disposing);
  262. }
  263. public void ExecuteCommand (int command)
  264. {
  265. #if NET_2_0
  266. ValidateServiceName (ServiceName);
  267. #endif
  268. _impl.ExecuteCommand (command);
  269. }
  270. public static ServiceController[] GetDevices ()
  271. {
  272. return GetDevices (".");
  273. }
  274. public static ServiceController[] GetDevices (string machineName)
  275. {
  276. ValidateMachineName (machineName);
  277. using (ServiceController sc = new ServiceController ("dummy", machineName)) {
  278. ServiceControllerImpl impl = CreateServiceControllerImpl (sc);
  279. return impl.GetDevices ();
  280. }
  281. }
  282. public static ServiceController[] GetServices ()
  283. {
  284. return GetServices (".");
  285. }
  286. public static ServiceController[] GetServices (string machineName)
  287. {
  288. ValidateMachineName (machineName);
  289. using (ServiceController sc = new ServiceController ("dummy", machineName)) {
  290. ServiceControllerImpl impl = CreateServiceControllerImpl (sc);
  291. return impl.GetServices ();
  292. }
  293. }
  294. public void Pause ()
  295. {
  296. #if NET_2_0
  297. ValidateServiceName (ServiceName);
  298. #endif
  299. _impl.Pause ();
  300. }
  301. public void Refresh ()
  302. {
  303. // MSDN: this method also sets the ServicesDependedOn and
  304. // DependentServices properties to a null reference
  305. //
  306. // I assume they wanted to say that the cache for these properties
  307. // is cleared. Verified by unit tests.
  308. _dependentServices = null;
  309. _servicesDependedOn = null;
  310. _impl.Refresh ();
  311. }
  312. public void Start ()
  313. {
  314. Start (new string [0]);
  315. }
  316. public void Start (string [] args)
  317. {
  318. #if NET_2_0
  319. ValidateServiceName (ServiceName);
  320. #endif
  321. _impl.Start (args);
  322. }
  323. public void Stop ()
  324. {
  325. #if NET_2_0
  326. ValidateServiceName (ServiceName);
  327. #endif
  328. _impl.Stop ();
  329. }
  330. public void WaitForStatus (ServiceControllerStatus desiredStatus)
  331. {
  332. WaitForStatus (desiredStatus, TimeSpan.MaxValue);
  333. }
  334. public void WaitForStatus (ServiceControllerStatus desiredStatus, TimeSpan timeout)
  335. {
  336. #if NET_2_0
  337. ValidateServiceName (ServiceName);
  338. #endif
  339. DateTime start = DateTime.Now;
  340. while (Status != desiredStatus) {
  341. if (timeout < (DateTime.Now - start))
  342. throw new TimeoutException ("Time out has expired and the"
  343. + " operation has not been completed.");
  344. Thread.Sleep (100);
  345. // force refresh of status
  346. Refresh ();
  347. }
  348. }
  349. internal string Name {
  350. get {
  351. return _name;
  352. }
  353. set {
  354. _name = value;
  355. }
  356. }
  357. internal string InternalDisplayName {
  358. get {
  359. return _displayName;
  360. }
  361. set {
  362. _displayName = value;
  363. }
  364. }
  365. internal string InternalServiceName {
  366. get {
  367. return _serviceName;
  368. }
  369. set {
  370. _serviceName = value;
  371. }
  372. }
  373. #if NET_2_0
  374. private static void ValidateServiceName (string serviceName)
  375. {
  376. if (serviceName.Length == 0 || serviceName.Length > 80)
  377. throw new ArgumentException (string.Format (CultureInfo.CurrentCulture,
  378. "Service name {0} contains invalid characters, is empty"
  379. + " or is too long (max length = 80).", serviceName));
  380. }
  381. #endif
  382. private static void ValidateMachineName (string machineName)
  383. {
  384. if (machineName == null || machineName.Length == 0)
  385. throw new ArgumentException (string.Format (CultureInfo.CurrentCulture,
  386. "MachineName value {0} is invalid.", machineName));
  387. }
  388. private static ServiceControllerImpl CreateServiceControllerImpl (ServiceController serviceController)
  389. {
  390. int p = (int) Environment.OSVersion.Platform;
  391. if (p == 4 || p == 128 || p == 6){
  392. return new UnixServiceController (serviceController);
  393. } else {
  394. return new Win32ServiceController (serviceController);
  395. }
  396. }
  397. }
  398. }