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;
594 scHandle = OpenServiceControlManager (machineName,
595 SERVICE_MANAGER_RIGHTS.SC_MANAGER_ENUMERATE_SERVICE);
598 uint bytesNeeded = 0;
599 uint servicesReturned = 0;
600 uint resumeHandle = 0;
602 ServiceController [] services;
605 if (!EnumServicesStatusEx (scHandle, SC_ENUM_PROCESS_INFO, serviceType, SERVICE_STATE_REQUEST.SERVICE_STATE_ALL, buffer, bufferSize, out bytesNeeded, out servicesReturned, ref resumeHandle, group)) {
606 int err = Marshal.GetLastWin32Error ();
607 if (err == ERROR_MORE_DATA) {
608 buffer = Marshal.AllocHGlobal ((int) bytesNeeded);
609 bufferSize = bytesNeeded;
611 throw new Win32Exception (err);
614 int iPtr = buffer.ToInt32 ();
616 services = new ServiceController [servicesReturned];
617 for (int i = 0; i < servicesReturned; i++) {
618 ENUM_SERVICE_STATUS_PROCESS serviceStatus = (ENUM_SERVICE_STATUS_PROCESS) Marshal.PtrToStructure (
619 new IntPtr (iPtr), typeof (ENUM_SERVICE_STATUS_PROCESS));
620 // TODO: use internal ctor that takes displayname too
621 services [i] = new ServiceController (serviceStatus.pServiceName,
623 // move on to the next services
624 iPtr += ENUM_SERVICE_STATUS_PROCESS.SizeOf;
627 // we're done, so exit the loop
634 if (scHandle != IntPtr.Zero)
635 CloseServiceHandle (scHandle);
636 if (buffer != IntPtr.Zero)
637 Marshal.FreeHGlobal (buffer);
641 private static IntPtr OpenServiceControlManager (string machineName, SERVICE_MANAGER_RIGHTS rights)
643 return OpenServiceControlManager (machineName, rights, false);
646 private static IntPtr OpenServiceControlManager (string machineName, SERVICE_MANAGER_RIGHTS rights, bool ignoreWin32Error)
648 IntPtr scHandle = OpenSCManager (machineName, SERVICES_ACTIVE_DATABASE,
650 if (scHandle == IntPtr.Zero) {
651 string msg = string.Format (CultureInfo.CurrentCulture,
652 "Cannot open Service Control Manager on computer '{0}'."
653 + " This operation might require other priviliges.",
655 if (ignoreWin32Error)
656 throw new InvalidOperationException (msg);
657 throw new InvalidOperationException (msg, new Win32Exception ());
662 private static InvalidOperationException CreateCannotOpenServiceException (string serviceName, string machineName)
664 return new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
665 "Cannot open {0} service on computer '{1}'.", serviceName, machineName),
666 new Win32Exception ());
669 #region PInvoke declaration
671 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
672 private static extern void CloseServiceHandle (IntPtr SCHANDLE);
674 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
675 private static extern bool ControlService (
677 SERVICE_CONTROL_TYPE dwControl,
678 ref SERVICE_STATUS lpServiceStatus);
680 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
681 private static extern bool EnumDependentServices (
683 SERVICE_STATE_REQUEST dwServiceState,
686 out uint pcbBytesNeeded,
687 out uint lpServicesReturned);
689 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
690 private static extern bool EnumServicesStatusEx (
693 SERVICE_TYPE dwServiceType,
694 SERVICE_STATE_REQUEST dwServiceState,
697 out uint pcbBytesNeeded,
698 out uint lpServicesReturned,
699 ref uint lpResumeHandle,
700 string pszGroupName);
702 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
703 private static extern bool GetServiceDisplayName (
705 string lpServiceName,
706 StringBuilder lpDisplayName,
707 ref uint lpcchBuffer);
709 [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
710 private static extern bool GetServiceKeyName (
712 string lpDisplayName,
713 StringBuilder lpServiceName,
714 ref uint lpcchBuffer);
716 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
717 private static extern IntPtr OpenSCManager (
718 string lpMachineName,
720 SERVICE_MANAGER_RIGHTS scParameter);
722 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
723 private static extern IntPtr OpenService (
726 SERVICE_RIGHTS dwNumServiceArgs);
728 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
729 private static extern bool QueryServiceConfig (
731 IntPtr lpServiceConfig,
733 out uint pcbBytesNeeded);
735 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
736 private static extern bool QueryServiceStatusEx (
737 IntPtr serviceHandle,
741 out int pcbBytesNeeded);
743 [DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
744 private static extern bool StartService (
746 int dwNumServiceArgs,
747 IntPtr [] lpServiceArgVectors);
749 private const int SC_ENUM_PROCESS_INFO = 0;
750 private const char SC_GROUP_IDENTIFIER = '+';
751 private const int SC_STATUS_PROCESS_INFO = 0;
752 private const int SERVICE_NO_CHANGE = -1;
753 private const int ERROR_MORE_DATA = 234;
754 private const int ERROR_INSUFFICIENT_BUFFER = 122;
755 private const int STANDARD_RIGHTS_REQUIRED = 0xf0000;
756 private const string SERVICES_ACTIVE_DATABASE = "ServicesActive";
758 internal struct QUERY_SERVICE_CONFIG
760 public int dwServiceType;
761 public int dwStartType;
762 public int dwErrorControl;
763 public IntPtr lpBinaryPathName;
764 public IntPtr lpLoadOrderGroup;
766 public IntPtr lpDependencies;
767 public IntPtr lpServiceStartName;
768 public IntPtr lpDisplayName;
772 private enum SERVICE_RIGHTS
774 SERVICE_QUERY_CONFIG = 1,
775 SERVICE_CHANGE_CONFIG = 2,
776 SERVICE_QUERY_STATUS = 4,
777 SERVICE_ENUMERATE_DEPENDENTS = 8,
780 SERVICE_PAUSE_CONTINUE = 64,
781 SERVICE_INTERROGATE = 128,
782 SERVICE_USER_DEFINED_CONTROL = 256,
783 SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SERVICE_QUERY_CONFIG |
784 SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS |
785 SERVICE_ENUMERATE_DEPENDENTS | SERVICE_START | SERVICE_STOP |
786 SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE |
787 SERVICE_USER_DEFINED_CONTROL)
790 private enum SERVICE_MANAGER_RIGHTS : uint
792 STANDARD_RIGHTS_READ = 0x20000,
793 STANDARD_RIGHTS_WRITE = 0x20000,
794 STANDARD_RIGHTS_EXECUTE = 0x20000,
795 STANDARD_RIGHTS_ALL = 0x1F0000,
797 SC_MANAGER_ALL_ACCESS = 0xf003f,
798 SC_MANAGER_CONNECT = 1,
799 SC_MANAGER_CREATE_SERVICE = 2,
800 SC_MANAGER_ENUMERATE_SERVICE = 4,
802 SC_MANAGER_QUERY_LOCK_STATUS = 16,
803 SC_MANAGER_MODIFY_BOOT_CONFIG = 32,
805 GENERIC_READ = 0x80000000,
806 GENERIC_WRITE = 0x40000000,
807 GENERIC_EXECUTE = 0x20000000,
808 GENERIC_ALL = 0x10000000
811 [StructLayout (LayoutKind.Sequential)]
812 private struct ENUM_SERVICE_STATUS_PROCESS
814 public static readonly int SizeOf = Marshal.SizeOf (typeof (ENUM_SERVICE_STATUS_PROCESS));
816 [MarshalAs (UnmanagedType.LPWStr)]
817 public string pServiceName;
819 [MarshalAs (UnmanagedType.LPWStr)]
820 public string pDisplayName;
822 public SERVICE_STATUS_PROCESS ServiceStatus;
825 [StructLayout (LayoutKind.Sequential)]
826 private struct ENUM_SERVICE_STATUS
828 public static readonly int SizeOf = Marshal.SizeOf (typeof (ENUM_SERVICE_STATUS));
830 [MarshalAs (UnmanagedType.LPWStr)]
831 public string pServiceName;
832 [MarshalAs (UnmanagedType.LPWStr)]
833 public string pDisplayName;
834 public SERVICE_STATUS ServiceStatus;
837 [StructLayout (LayoutKind.Sequential)]
838 private struct SERVICE_STATUS
840 public ServiceType dwServiceType;
841 public ServiceControllerStatus dwCurrentState;
842 public SERVICE_CONTROL_ACCEPTED dwControlsAccepted;
843 public int dwWin32ExitCode;
844 public int dwServiceSpecificExitCode;
845 public uint dwCheckPoint;
846 public uint dwWaitHint;
849 [StructLayout (LayoutKind.Sequential, Pack = 1)]
850 private struct SERVICE_STATUS_PROCESS
852 public static readonly int SizeOf = Marshal.SizeOf (typeof (SERVICE_STATUS_PROCESS));
854 public ServiceType dwServiceType;
855 public ServiceControllerStatus dwCurrentState;
856 public SERVICE_CONTROL_ACCEPTED dwControlsAccepted;
857 public int dwWin32ExitCode;
858 public int dwServiceSpecificExitCode;
859 public int dwCheckPoint;
860 public int dwWaitHint;
861 public int dwProcessId;
862 public int dwServiceFlags;
865 private enum SERVICE_TYPE
867 SERVICE_KERNEL_DRIVER = 0x1,
868 SERVICE_FILE_SYSTEM_DRIVER = 0x2,
869 SERVICE_ADAPTER = 0x4,
870 SERVICE_RECOGNIZER_DRIVER = 0x8,
871 SERVICE_DRIVER = (SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER),
872 SERVICE_WIN32_OWN_PROCESS = 0x10,
873 SERVICE_WIN32_SHARE_PROCESS = 0x20,
874 SERVICE_INTERACTIVE_PROCESS = 0x100,
875 SERVICETYPE_NO_CHANGE = SERVICE_NO_CHANGE,
876 SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS),
877 SERVICE_TYPE_ALL = (SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS)
880 private enum SERVICE_START_TYPE
882 SERVICE_BOOT_START = 0x0,
883 SERVICE_SYSTEM_START = 0x1,
884 SERVICE_AUTO_START = 0x2,
885 SERVICE_DEMAND_START = 0x3,
886 SERVICE_DISABLED = 0x4,
887 SERVICESTARTTYPE_NO_CHANGE = SERVICE_NO_CHANGE
890 private enum SERVICE_ERROR_CONTROL
892 SERVICE_ERROR_IGNORE = 0x0,
893 SERVICE_ERROR_NORMAL = 0x1,
894 SERVICE_ERROR_SEVERE = 0x2,
895 SERVICE_ERROR_CRITICAL = 0x3,
896 msidbServiceInstallErrorControlVital = 0x8000,
897 SERVICEERRORCONTROL_NO_CHANGE = SERVICE_NO_CHANGE
900 private enum SERVICE_STATE_REQUEST
902 SERVICE_ACTIVE = 0x1,
903 SERVICE_INACTIVE = 0x2,
904 SERVICE_STATE_ALL = (SERVICE_ACTIVE | SERVICE_INACTIVE)
907 private enum SERVICE_CONTROL_TYPE
909 SERVICE_CONTROL_STOP = 0x1,
910 SERVICE_CONTROL_PAUSE = 0x2,
911 SERVICE_CONTROL_CONTINUE = 0x3,
912 SERVICE_CONTROL_INTERROGATE = 0x4,
913 SERVICE_CONTROL_SHUTDOWN = 0x5,
914 SERVICE_CONTROL_PARAMCHANGE = 0x6,
915 SERVICE_CONTROL_NETBINDADD = 0x7,
916 SERVICE_CONTROL_NETBINDREMOVE = 0x8,
917 SERVICE_CONTROL_NETBINDENABLE = 0x9,
918 SERVICE_CONTROL_NETBINDDISABLE = 0xA,
919 SERVICE_CONTROL_DEVICEEVENT = 0xB,
920 SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0xC,
921 SERVICE_CONTROL_POWEREVENT = 0xD,
922 SERVICE_CONTROL_SESSIONCHANGE = 0xE
926 private enum SERVICE_CONTROL_ACCEPTED
928 SERVICE_ACCEPT_NONE = 0x0,
929 SERVICE_ACCEPT_STOP = 0x1,
930 SERVICE_ACCEPT_PAUSE_CONTINUE = 0x2,
931 SERVICE_ACCEPT_SHUTDOWN = 0x4,
932 SERVICE_ACCEPT_PARAMCHANGE = 0x8,
933 SERVICE_ACCEPT_NETBINDCHANGE = 0x10,
934 SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x20,
935 SERVICE_ACCEPT_POWEREVENT = 0x40,
936 SERVICE_ACCEPT_SESSIONCHANGE = 0x80
939 #endregion PInvoke declaration