2 // System.ServiceProcess.Win32ServiceController
5 // Gert Driesen (drieseng@users.sourceforge.net)
7 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.ComponentModel;
32 using System.Globalization;
33 using System.Runtime.InteropServices;
36 namespace System.ServiceProcess
38 internal class Win32ServiceController : ServiceControllerImpl
40 SERVICE_STATUS_PROCESS _status;
42 public Win32ServiceController (ServiceController serviceController)
43 : base (serviceController)
47 public override bool CanPauseAndContinue {
49 if ((int) _status.dwServiceType == 0)
50 _status = GetServiceStatus (ServiceController.ServiceName,
51 ServiceController.MachineName);
52 return (_status.dwControlsAccepted & SERVICE_CONTROL_ACCEPTED.SERVICE_ACCEPT_PAUSE_CONTINUE) != 0;
56 public override bool CanShutdown {
58 if ((int) _status.dwServiceType == 0)
59 _status = GetServiceStatus (ServiceController.ServiceName,
60 ServiceController.MachineName);
61 return (_status.dwControlsAccepted & SERVICE_CONTROL_ACCEPTED.SERVICE_ACCEPT_SHUTDOWN) != 0;
65 public override bool CanStop {
67 if ((int) _status.dwServiceType == 0)
68 _status = GetServiceStatus (ServiceController.ServiceName,
69 ServiceController.MachineName);
70 return (_status.dwControlsAccepted & SERVICE_CONTROL_ACCEPTED.SERVICE_ACCEPT_STOP) != 0;
74 public override ServiceController [] DependentServices {
76 return GetDependentServices (ServiceController.ServiceName,
77 ServiceController.MachineName);
81 public override string DisplayName {
83 string lookupName = ServiceController.ServiceName;
85 IntPtr scHandle = IntPtr.Zero;
87 scHandle = OpenServiceControlManager (ServiceController.MachineName,
88 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
89 if (lookupName.Length == 0) {
90 // if the service name is not available, then
91 // assume the specified name is in fact already a display
94 string serviceName = GetServiceName (scHandle,
96 ServiceController.InternalServiceName = serviceName;
97 ServiceController.Name = string.Empty;
99 } catch (Win32Exception) {
103 if (ServiceController.InternalDisplayName.Length == 0)
104 return GetServiceDisplayName (scHandle, lookupName,
105 ServiceController.MachineName);
106 return ServiceController.InternalDisplayName;
108 if (scHandle != IntPtr.Zero)
109 CloseServiceHandle (scHandle);
114 public override string ServiceName {
116 string lookupName = ServiceController.Name;
117 if (lookupName.Length == 0)
118 lookupName = ServiceController.InternalDisplayName;
120 IntPtr scHandle = IntPtr.Zero;
122 scHandle = OpenServiceControlManager (ServiceController.MachineName,
123 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
125 // assume the specified name is in fact a display name
127 string serviceName = GetServiceName (scHandle, lookupName);
128 ServiceController.InternalDisplayName = lookupName;
129 ServiceController.Name = string.Empty;
131 } catch (Win32Exception) {
134 // instead of opening the service to verify whether it exists,
135 // we'll try to get its displayname and hereby avoid looking
136 // this up separately
137 string displayName = GetServiceDisplayName (scHandle,
138 lookupName, ServiceController.MachineName);
139 ServiceController.InternalDisplayName = displayName;
140 ServiceController.Name = string.Empty;
143 if (scHandle != IntPtr.Zero)
144 CloseServiceHandle (scHandle);
149 public override ServiceController [] ServicesDependedOn {
151 return GetServiceDependencies (ServiceController.ServiceName,
152 ServiceController.MachineName);
156 public override ServiceType ServiceType {
158 if ((int) _status.dwServiceType == 0)
159 _status = GetServiceStatus (ServiceController.ServiceName,
160 ServiceController.MachineName);
161 return _status.dwServiceType;
165 public override ServiceControllerStatus Status {
167 if ((int) _status.dwServiceType == 0)
168 _status = GetServiceStatus (ServiceController.ServiceName,
169 ServiceController.MachineName);
170 return _status.dwCurrentState;
174 public override void Close ()
176 // clear status cache
177 _status.dwServiceType = 0;
180 public override void Continue ()
182 string serviceName = ServiceController.ServiceName;
183 string machineName = ServiceController.MachineName;
184 IntPtr scHandle = IntPtr.Zero;
185 IntPtr svcHandle = IntPtr.Zero;
188 scHandle = OpenServiceControlManager (machineName,
189 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
191 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE);
192 if (svcHandle == IntPtr.Zero)
193 throw CreateCannotOpenServiceException (serviceName,
196 SERVICE_STATUS status = new SERVICE_STATUS ();
197 if (!ControlService (svcHandle, SERVICE_CONTROL_TYPE.SERVICE_CONTROL_CONTINUE, ref status))
198 throw new InvalidOperationException (string.Format (
199 CultureInfo.CurrentCulture, "Cannot resume {0} service"
200 + " on computer '{1}'.", serviceName, machineName),
201 new Win32Exception ());
203 if (svcHandle != IntPtr.Zero)
204 CloseServiceHandle (svcHandle);
205 if (scHandle != IntPtr.Zero)
206 CloseServiceHandle (scHandle);
210 public override void Dispose (bool disposing)
212 // we're not keeping any handles open
215 public override void ExecuteCommand (int command)
217 string serviceName = ServiceController.ServiceName;
218 string machineName = ServiceController.MachineName;
219 IntPtr scHandle = IntPtr.Zero;
220 IntPtr svcHandle = IntPtr.Zero;
223 scHandle = OpenServiceControlManager (machineName,
224 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
226 // MSDN: the hService handle must have the SERVICE_USER_DEFINED_CONTROL
228 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_USER_DEFINED_CONTROL);
229 if (svcHandle == IntPtr.Zero)
230 throw CreateCannotOpenServiceException (serviceName,
233 SERVICE_STATUS status = new SERVICE_STATUS ();
234 if (!ControlService (svcHandle, (SERVICE_CONTROL_TYPE) command, ref status))
235 throw new InvalidOperationException (string.Format (
236 CultureInfo.CurrentCulture, "Cannot control {0} service"
237 + " on computer '{1}'.", serviceName, machineName),
238 new Win32Exception ());
240 if (svcHandle != IntPtr.Zero)
241 CloseServiceHandle (svcHandle);
242 if (scHandle != IntPtr.Zero)
243 CloseServiceHandle (scHandle);
247 public override ServiceController [] GetDevices ()
249 return GetServices (ServiceController.MachineName,
250 SERVICE_TYPE.SERVICE_DRIVER, null);
253 public override ServiceController [] GetServices ()
255 return GetServices (ServiceController.MachineName,
256 SERVICE_TYPE.SERVICE_WIN32, null);
259 public override void Pause ()
261 string serviceName = ServiceController.ServiceName;
262 string machineName = ServiceController.MachineName;
263 IntPtr scHandle = IntPtr.Zero;
264 IntPtr svcHandle = IntPtr.Zero;
267 scHandle = OpenServiceControlManager (machineName,
268 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
270 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE);
271 if (svcHandle == IntPtr.Zero)
272 throw CreateCannotOpenServiceException (serviceName,
275 SERVICE_STATUS status = new SERVICE_STATUS ();
276 if (!ControlService (svcHandle, SERVICE_CONTROL_TYPE.SERVICE_CONTROL_PAUSE, ref status))
277 throw new InvalidOperationException (string.Format (
278 CultureInfo.CurrentCulture, "Cannot pause {0} service"
279 + " on computer '{1}'.", serviceName, machineName),
280 new Win32Exception ());
282 if (svcHandle != IntPtr.Zero)
283 CloseServiceHandle (svcHandle);
284 if (scHandle != IntPtr.Zero)
285 CloseServiceHandle (scHandle);
289 public override void Refresh ()
291 // force refresh of status
292 _status.dwServiceType = 0;
295 public override void Start (string [] args)
297 string serviceName = ServiceController.ServiceName;
298 string machineName = ServiceController.MachineName;
299 IntPtr scHandle = IntPtr.Zero;
300 IntPtr svcHandle = IntPtr.Zero;
301 IntPtr [] arguments = new IntPtr [args.Length];
304 scHandle = OpenServiceControlManager (machineName,
305 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
307 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_START);
308 if (svcHandle == IntPtr.Zero)
309 throw CreateCannotOpenServiceException (serviceName,
312 for (int i = 0; i < args.Length; i++) {
313 string argument = args [i];
314 arguments [i] = Marshal.StringToHGlobalAnsi (argument);
317 if (!StartService (svcHandle, arguments.Length, arguments))
318 throw new InvalidOperationException (string.Format (
319 CultureInfo.CurrentCulture, "Cannot start {0} service"
320 + " on computer '{1}'.", serviceName, machineName),
321 new Win32Exception ());
323 for (int i = 0; i < arguments.Length; i++)
324 Marshal.FreeHGlobal (arguments [i]);
325 if (svcHandle != IntPtr.Zero)
326 CloseServiceHandle (svcHandle);
327 if (scHandle != IntPtr.Zero)
328 CloseServiceHandle (scHandle);
333 public override void Stop ()
335 string serviceName = ServiceController.ServiceName;
336 string machineName = ServiceController.MachineName;
337 IntPtr scHandle = IntPtr.Zero;
338 IntPtr svcHandle = IntPtr.Zero;
341 scHandle = OpenServiceControlManager (machineName,
342 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
344 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_STOP);
345 if (svcHandle == IntPtr.Zero)
346 throw CreateCannotOpenServiceException (serviceName,
349 SERVICE_STATUS status = new SERVICE_STATUS ();
350 if (!ControlService (svcHandle, SERVICE_CONTROL_TYPE.SERVICE_CONTROL_STOP, ref status))
351 throw new InvalidOperationException (string.Format (
352 CultureInfo.CurrentCulture, "Cannot stop {0} service"
353 + " on computer '{1}'.", serviceName, machineName),
354 new Win32Exception ());
356 if (svcHandle != IntPtr.Zero)
357 CloseServiceHandle (svcHandle);
358 if (scHandle != IntPtr.Zero)
359 CloseServiceHandle (scHandle);
363 private static ServiceController [] GetDependentServices (string serviceName, string machineName)
365 IntPtr scHandle = IntPtr.Zero;
366 IntPtr svcHandle = IntPtr.Zero;
367 IntPtr buffer = IntPtr.Zero;
370 scHandle = OpenServiceControlManager (machineName,
371 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
373 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_ENUMERATE_DEPENDENTS);
374 if (svcHandle == IntPtr.Zero)
375 throw CreateCannotOpenServiceException (serviceName, machineName);
378 uint bytesNeeded = 0;
379 uint servicesReturned = 0;
381 ServiceController [] services;
384 if (!EnumDependentServices (svcHandle, SERVICE_STATE_REQUEST.SERVICE_STATE_ALL, buffer, bufferSize, out bytesNeeded, out servicesReturned)) {
385 int err = Marshal.GetLastWin32Error ();
386 if (err == ERROR_MORE_DATA) {
387 buffer = Marshal.AllocHGlobal ((int) bytesNeeded);
388 bufferSize = bytesNeeded;
390 throw new Win32Exception (err);
393 int iPtr = buffer.ToInt32 ();
395 services = new ServiceController [servicesReturned];
396 for (int i = 0; i < servicesReturned; i++) {
397 ENUM_SERVICE_STATUS serviceStatus = (ENUM_SERVICE_STATUS) Marshal.PtrToStructure (
398 new IntPtr (iPtr), typeof (ENUM_SERVICE_STATUS));
399 // TODO: use internal ctor that takes displayname too ?
400 services [i] = new ServiceController (serviceStatus.pServiceName,
402 // move on to the next services
403 iPtr += ENUM_SERVICE_STATUS.SizeOf;
406 // we're done, so exit the loop
413 if (scHandle != IntPtr.Zero)
414 CloseServiceHandle (scHandle);
415 if (svcHandle != IntPtr.Zero)
416 CloseServiceHandle (svcHandle);
417 if (buffer != IntPtr.Zero)
418 Marshal.FreeHGlobal (buffer);
422 private static ServiceController [] GetServiceDependencies (string serviceName, string machineName)
424 IntPtr scHandle = IntPtr.Zero;
425 IntPtr svcHandle = IntPtr.Zero;
426 IntPtr buffer = IntPtr.Zero;
429 scHandle = OpenServiceControlManager (machineName,
430 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
432 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_QUERY_CONFIG);
433 if (svcHandle == IntPtr.Zero)
434 throw CreateCannotOpenServiceException (serviceName, machineName);
437 uint bytesNeeded = 0;
439 ServiceController [] services;
442 if (!QueryServiceConfig (svcHandle, buffer, bufferSize, out bytesNeeded)) {
443 int err = Marshal.GetLastWin32Error ();
444 if (err == ERROR_INSUFFICIENT_BUFFER) {
445 buffer = Marshal.AllocHGlobal ((int) bytesNeeded);
446 bufferSize = bytesNeeded;
448 throw new Win32Exception (err);
451 QUERY_SERVICE_CONFIG config = (QUERY_SERVICE_CONFIG) Marshal.PtrToStructure (
452 buffer, typeof (QUERY_SERVICE_CONFIG));
454 Hashtable depServices = new Hashtable ();
455 IntPtr iPtr = config.lpDependencies;
456 StringBuilder sb = new StringBuilder ();
457 string currentChar = Marshal.PtrToStringUni (iPtr, 1);
458 while (currentChar != "\0") {
459 sb.Append (currentChar);
460 iPtr = new IntPtr (iPtr.ToInt64 () + Marshal.SystemDefaultCharSize);
461 currentChar = Marshal.PtrToStringUni (iPtr, 1);
462 if (currentChar != "\0") {
465 iPtr = new IntPtr (iPtr.ToInt64 () + Marshal.SystemDefaultCharSize);
466 currentChar = Marshal.PtrToStringUni (iPtr, 1);
467 string dependency = sb.ToString ();
468 if (dependency [0] == SC_GROUP_IDENTIFIER) {
469 ServiceController [] groupServices = GetServices (
470 machineName, SERVICE_TYPE.SERVICE_WIN32,
471 dependency.Substring (1));
472 foreach (ServiceController sc in groupServices) {
473 if (!depServices.Contains (sc.ServiceName))
474 depServices.Add (sc.ServiceName, sc);
476 } else if (!depServices.Contains (dependency)) {
477 depServices.Add (dependency, new ServiceController (dependency, machineName));
482 services = new ServiceController [depServices.Count];
483 depServices.Values.CopyTo (services, 0);
490 if (scHandle != IntPtr.Zero)
491 CloseServiceHandle (scHandle);
492 if (svcHandle != IntPtr.Zero)
493 CloseServiceHandle (svcHandle);
494 if (buffer != IntPtr.Zero)
495 Marshal.FreeHGlobal (buffer);
499 private static string GetServiceDisplayName (IntPtr scHandle, string serviceName, string machineName)
501 StringBuilder buffer = new StringBuilder ();
503 uint bufferSize = (uint) buffer.Capacity;
506 if (!GetServiceDisplayName (scHandle, serviceName, buffer, ref bufferSize)) {
507 int err = Marshal.GetLastWin32Error ();
508 if (err == ERROR_INSUFFICIENT_BUFFER) {
509 // allocate additional byte for terminating null char
510 buffer = new StringBuilder ((int) bufferSize + 1);
511 bufferSize = (uint) buffer.Capacity;
513 throw new InvalidOperationException (string.Format (
514 CultureInfo.CurrentCulture, "Service {0} was not"
515 + " found on computer '{1}'.", serviceName,
516 machineName), new Win32Exception ());
519 return buffer.ToString ();
524 private static string GetServiceName (IntPtr scHandle, string displayName)
526 StringBuilder buffer = new StringBuilder ();
528 uint bufferSize = (uint) buffer.Capacity;
531 if (!GetServiceKeyName (scHandle, displayName, buffer, ref bufferSize)) {
532 int err = Marshal.GetLastWin32Error ();
533 if (err == ERROR_INSUFFICIENT_BUFFER) {
534 // allocate additional byte for terminating null char
535 buffer = new StringBuilder ((int) bufferSize + 1);
536 bufferSize = (uint) buffer.Capacity;
538 throw new Win32Exception ();
541 return buffer.ToString ();
546 private static SERVICE_STATUS_PROCESS GetServiceStatus (string serviceName, string machineName)
548 IntPtr scHandle = IntPtr.Zero;
549 IntPtr svcHandle = IntPtr.Zero;
550 IntPtr buffer = IntPtr.Zero;
553 scHandle = OpenServiceControlManager (machineName,
554 SERVICE_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
556 svcHandle = OpenService (scHandle, serviceName, SERVICE_RIGHTS.SERVICE_QUERY_STATUS);
557 if (svcHandle == IntPtr.Zero)
558 throw CreateCannotOpenServiceException (serviceName, machineName);
564 if (!QueryServiceStatusEx (svcHandle, SC_STATUS_PROCESS_INFO, buffer, bufferSize, out bytesNeeded)) {
565 int err = Marshal.GetLastWin32Error ();
566 if (err == ERROR_INSUFFICIENT_BUFFER) {
567 buffer = Marshal.AllocHGlobal (bytesNeeded);
568 bufferSize = bytesNeeded;
570 throw new Win32Exception (err);
573 SERVICE_STATUS_PROCESS serviceStatus = (SERVICE_STATUS_PROCESS) Marshal.PtrToStructure (
574 buffer, typeof (SERVICE_STATUS_PROCESS));
575 return serviceStatus;
579 if (scHandle != IntPtr.Zero)
580 CloseServiceHandle (scHandle);
581 if (svcHandle != IntPtr.Zero)
582 CloseServiceHandle (svcHandle);
583 if (buffer != IntPtr.Zero)
584 Marshal.FreeHGlobal (buffer);
588 private static ServiceController [] GetServices (string machineName, SERVICE_TYPE serviceType, string group)
590 IntPtr scHandle = IntPtr.Zero;
591 IntPtr buffer = IntPtr.Zero;
595 scHandle = OpenServiceControlManager (machineName,
596 SERVICE_MANAGER_RIGHTS.SC_MANAGER_ENUMERATE_SERVICE);
598 scHandle = OpenServiceControlManager (machineName,
599 SERVICE_MANAGER_RIGHTS.SC_MANAGER_ENUMERATE_SERVICE, true);
603 uint bytesNeeded = 0;
604 uint servicesReturned = 0;
605 uint resumeHandle = 0;
607 ServiceController [] services;
610 if (!EnumServicesStatusEx (scHandle, SC_ENUM_PROCESS_INFO, serviceType, SERVICE_STATE_REQUEST.SERVICE_STATE_ALL, buffer, bufferSize, out bytesNeeded, out servicesReturned, ref resumeHandle, group)) {
611 int err = Marshal.GetLastWin32Error ();
612 if (err == ERROR_MORE_DATA) {
613 buffer = Marshal.AllocHGlobal ((int) bytesNeeded);
614 bufferSize = bytesNeeded;
616 throw new Win32Exception (err);
619 int iPtr = buffer.ToInt32 ();
621 services = new ServiceController [servicesReturned];
622 for (int i = 0; i < servicesReturned; i++) {
623 ENUM_SERVICE_STATUS_PROCESS serviceStatus = (ENUM_SERVICE_STATUS_PROCESS) Marshal.PtrToStructure (
624 new IntPtr (iPtr), typeof (ENUM_SERVICE_STATUS_PROCESS));
625 // TODO: use internal ctor that takes displayname too
626 services [i] = new ServiceController (serviceStatus.pServiceName,
628 // move on to the next services
629 iPtr += ENUM_SERVICE_STATUS_PROCESS.SizeOf;
632 // we're done, so exit the loop
639 if (scHandle != IntPtr.Zero)
640 CloseServiceHandle (scHandle);
641 if (buffer != IntPtr.Zero)
642 Marshal.FreeHGlobal (buffer);
646 private static IntPtr OpenServiceControlManager (string machineName, SERVICE_MANAGER_RIGHTS rights)
648 return OpenServiceControlManager (machineName, rights, false);
651 private static IntPtr OpenServiceControlManager (string machineName, SERVICE_MANAGER_RIGHTS rights, bool ignoreWin32Error)
653 IntPtr scHandle = OpenSCManager (machineName, SERVICES_ACTIVE_DATABASE,
655 if (scHandle == IntPtr.Zero) {
656 string msg = string.Format (CultureInfo.CurrentCulture,
657 "Cannot open Service Control Manager on computer '{0}'."
658 + " This operation might require other priviliges.",
660 if (ignoreWin32Error)
661 throw new InvalidOperationException (msg);
662 throw new InvalidOperationException (msg, new Win32Exception ());
667 private static InvalidOperationException CreateCannotOpenServiceException (string serviceName, string machineName)
669 return new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
670 "Cannot open {0} service on computer '{1}'.", serviceName, machineName),
671 new Win32Exception ());
674 #region PInvoke declaration
676 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
677 private static extern void CloseServiceHandle (IntPtr SCHANDLE);
679 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
680 private static extern bool ControlService (
682 SERVICE_CONTROL_TYPE dwControl,
683 ref SERVICE_STATUS lpServiceStatus);
685 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
686 private static extern bool EnumDependentServices (
688 SERVICE_STATE_REQUEST dwServiceState,
691 out uint pcbBytesNeeded,
692 out uint lpServicesReturned);
694 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
695 private static extern bool EnumServicesStatusEx (
698 SERVICE_TYPE dwServiceType,
699 SERVICE_STATE_REQUEST dwServiceState,
702 out uint pcbBytesNeeded,
703 out uint lpServicesReturned,
704 ref uint lpResumeHandle,
705 string pszGroupName);
707 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
708 private static extern bool GetServiceDisplayName (
710 string lpServiceName,
711 StringBuilder lpDisplayName,
712 ref uint lpcchBuffer);
714 [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
715 private static extern bool GetServiceKeyName (
717 string lpDisplayName,
718 StringBuilder lpServiceName,
719 ref uint lpcchBuffer);
721 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
722 private static extern IntPtr OpenSCManager (
723 string lpMachineName,
725 SERVICE_MANAGER_RIGHTS scParameter);
727 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
728 private static extern IntPtr OpenService (
731 SERVICE_RIGHTS dwNumServiceArgs);
733 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
734 private static extern bool QueryServiceConfig (
736 IntPtr lpServiceConfig,
738 out uint pcbBytesNeeded);
740 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
741 private static extern bool QueryServiceStatusEx (
742 IntPtr serviceHandle,
746 out int pcbBytesNeeded);
748 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
749 private static extern bool StartService (
751 int dwNumServiceArgs,
752 IntPtr [] lpServiceArgVectors);
754 private const int SC_ENUM_PROCESS_INFO = 0;
755 private const char SC_GROUP_IDENTIFIER = '+';
756 private const int SC_STATUS_PROCESS_INFO = 0;
757 private const int SERVICE_NO_CHANGE = -1;
758 private const int ERROR_MORE_DATA = 234;
759 private const int ERROR_INSUFFICIENT_BUFFER = 122;
760 private const int STANDARD_RIGHTS_REQUIRED = 0xf0000;
761 private const string SERVICES_ACTIVE_DATABASE = "ServicesActive";
763 internal struct QUERY_SERVICE_CONFIG
765 public int dwServiceType;
766 public int dwStartType;
767 public int dwErrorControl;
768 public IntPtr lpBinaryPathName;
769 public IntPtr lpLoadOrderGroup;
771 public IntPtr lpDependencies;
772 public IntPtr lpServiceStartName;
773 public IntPtr lpDisplayName;
777 private enum SERVICE_RIGHTS
779 SERVICE_QUERY_CONFIG = 1,
780 SERVICE_CHANGE_CONFIG = 2,
781 SERVICE_QUERY_STATUS = 4,
782 SERVICE_ENUMERATE_DEPENDENTS = 8,
785 SERVICE_PAUSE_CONTINUE = 64,
786 SERVICE_INTERROGATE = 128,
787 SERVICE_USER_DEFINED_CONTROL = 256,
788 SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG |
789 SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS |
790 SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP |
791 SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE |
792 SERVICE_USER_DEFINED_CONTROL)
795 private enum SERVICE_MANAGER_RIGHTS : uint
797 STANDARD_RIGHTS_READ = 0x20000,
798 STANDARD_RIGHTS_WRITE = 0x20000,
799 STANDARD_RIGHTS_EXECUTE = 0x20000,
800 STANDARD_RIGHTS_ALL = 0x1F0000,
802 SC_MANAGER_ALL_ACCESS = 0xf003f,
803 SC_MANAGER_CONNECT = 1,
804 SC_MANAGER_CREATE_SERVICE = 2,
805 SC_MANAGER_ENUMERATE_SERVICE = 4,
807 SC_MANAGER_QUERY_LOCK_STATUS = 16,
808 SC_MANAGER_MODIFY_BOOT_CONFIG = 32,
810 GENERIC_READ = 0x80000000,
811 GENERIC_WRITE = 0x40000000,
812 GENERIC_EXECUTE = 0x20000000,
813 GENERIC_ALL = 0x10000000
816 [StructLayout (LayoutKind.Sequential)]
817 private struct ENUM_SERVICE_STATUS_PROCESS
819 public static readonly int SizeOf = Marshal.SizeOf (typeof (ENUM_SERVICE_STATUS_PROCESS));
821 [MarshalAs (UnmanagedType.LPWStr)]
822 public string pServiceName;
824 [MarshalAs (UnmanagedType.LPWStr)]
825 public string pDisplayName;
827 public SERVICE_STATUS_PROCESS ServiceStatus;
830 [StructLayout (LayoutKind.Sequential)]
831 private struct ENUM_SERVICE_STATUS
833 public static readonly int SizeOf = Marshal.SizeOf (typeof (ENUM_SERVICE_STATUS));
835 [MarshalAs (UnmanagedType.LPWStr)]
836 public string pServiceName;
837 [MarshalAs (UnmanagedType.LPWStr)]
838 public string pDisplayName;
839 public SERVICE_STATUS ServiceStatus;
842 [StructLayout (LayoutKind.Sequential)]
843 private struct SERVICE_STATUS
845 public ServiceType dwServiceType;
846 public ServiceControllerStatus dwCurrentState;
847 public SERVICE_CONTROL_ACCEPTED dwControlsAccepted;
848 public int dwWin32ExitCode;
849 public int dwServiceSpecificExitCode;
850 public uint dwCheckPoint;
851 public uint dwWaitHint;
854 [StructLayout (LayoutKind.Sequential, Pack = 1)]
855 private struct SERVICE_STATUS_PROCESS
857 public static readonly int SizeOf = Marshal.SizeOf (typeof (SERVICE_STATUS_PROCESS));
859 public ServiceType dwServiceType;
860 public ServiceControllerStatus dwCurrentState;
861 public SERVICE_CONTROL_ACCEPTED dwControlsAccepted;
862 public int dwWin32ExitCode;
863 public int dwServiceSpecificExitCode;
864 public int dwCheckPoint;
865 public int dwWaitHint;
866 public int dwProcessId;
867 public int dwServiceFlags;
870 private enum SERVICE_TYPE
872 SERVICE_KERNEL_DRIVER = 0x1,
873 SERVICE_FILE_SYSTEM_DRIVER = 0x2,
874 SERVICE_ADAPTER = 0x4,
875 SERVICE_RECOGNIZER_DRIVER = 0x8,
876 SERVICE_DRIVER = (SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER),
877 SERVICE_WIN32_OWN_PROCESS = 0x10,
878 SERVICE_WIN32_SHARE_PROCESS = 0x20,
879 SERVICE_INTERACTIVE_PROCESS = 0x100,
880 SERVICETYPE_NO_CHANGE = SERVICE_NO_CHANGE,
881 SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS),
882 SERVICE_TYPE_ALL = (SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS)
885 private enum SERVICE_START_TYPE
887 SERVICE_BOOT_START = 0x0,
888 SERVICE_SYSTEM_START = 0x1,
889 SERVICE_AUTO_START = 0x2,
890 SERVICE_DEMAND_START = 0x3,
891 SERVICE_DISABLED = 0x4,
892 SERVICESTARTTYPE_NO_CHANGE = SERVICE_NO_CHANGE
895 private enum SERVICE_ERROR_CONTROL
897 SERVICE_ERROR_IGNORE = 0x0,
898 SERVICE_ERROR_NORMAL = 0x1,
899 SERVICE_ERROR_SEVERE = 0x2,
900 SERVICE_ERROR_CRITICAL = 0x3,
901 msidbServiceInstallErrorControlVital = 0x8000,
902 SERVICEERRORCONTROL_NO_CHANGE = SERVICE_NO_CHANGE
905 private enum SERVICE_STATE_REQUEST
907 SERVICE_ACTIVE = 0x1,
908 SERVICE_INACTIVE = 0x2,
909 SERVICE_STATE_ALL = (SERVICE_ACTIVE | SERVICE_INACTIVE)
912 private enum SERVICE_CONTROL_TYPE
914 SERVICE_CONTROL_STOP = 0x1,
915 SERVICE_CONTROL_PAUSE = 0x2,
916 SERVICE_CONTROL_CONTINUE = 0x3,
917 SERVICE_CONTROL_INTERROGATE = 0x4,
918 SERVICE_CONTROL_SHUTDOWN = 0x5,
919 SERVICE_CONTROL_PARAMCHANGE = 0x6,
920 SERVICE_CONTROL_NETBINDADD = 0x7,
921 SERVICE_CONTROL_NETBINDREMOVE = 0x8,
922 SERVICE_CONTROL_NETBINDENABLE = 0x9,
923 SERVICE_CONTROL_NETBINDDISABLE = 0xA,
924 SERVICE_CONTROL_DEVICEEVENT = 0xB,
925 SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0xC,
926 SERVICE_CONTROL_POWEREVENT = 0xD,
927 SERVICE_CONTROL_SESSIONCHANGE = 0xE
931 private enum SERVICE_CONTROL_ACCEPTED
933 SERVICE_ACCEPT_NONE = 0x0,
934 SERVICE_ACCEPT_STOP = 0x1,
935 SERVICE_ACCEPT_PAUSE_CONTINUE = 0x2,
936 SERVICE_ACCEPT_SHUTDOWN = 0x4,
937 SERVICE_ACCEPT_PARAMCHANGE = 0x8,
938 SERVICE_ACCEPT_NETBINDCHANGE = 0x10,
939 SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x20,
940 SERVICE_ACCEPT_POWEREVENT = 0x40,
941 SERVICE_ACCEPT_SESSIONCHANGE = 0x80
944 #endregion PInvoke declaration