Type a page name and press Enter. You'll jump to the page if it exists, or you can create it if it doesn't.
To create a page in a module other than advapi32, prefix the name with the module name and a period.
ControlService (advapi32)
.
Summary
C# Signature:
[DllImport("advapi32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ControlService( IntPtr hService,
SERVICE_CONTROL dwControl,
ref SERVICE_STATUS lpServiceStatus
);
VB Signature:
Declare Function ControlService Lib "advapi32.dll" (ByVal hService As Long, ByVal lControlCode As Long, ByVal lpServiceStatus As SERVICE_STATUS) As Boolean
C# User-Defined Types:
See SERVICE_STATUS definition
[Flags]
public enum SERVICE_CONTROL : uint
{
STOP = 0x00000001,
PAUSE = 0x00000002,
CONTINUE = 0x00000003,
INTERROGATE = 0x00000004,
SHUTDOWN = 0x00000005,
PARAMCHANGE = 0x00000006,
NETBINDADD = 0x00000007,
NETBINDREMOVE = 0x00000008,
NETBINDENABLE = 0x00000009,
NETBINDDISABLE = 0x0000000A,
DEVICEEVENT = 0x0000000B,
HARDWAREPROFILECHANGE = 0x0000000C,
POWEREVENT = 0x0000000D,
SESSIONCHANGE = 0x0000000E
}
public enum SERVICE_STATE : uint
{
SERVICE_STOPPED = 0x00000001,
SERVICE_START_PENDING = 0x00000002,
SERVICE_STOP_PENDING = 0x00000003,
SERVICE_RUNNING = 0x00000004,
SERVICE_CONTINUE_PENDING = 0x00000005,
SERVICE_PAUSE_PENDING = 0x00000006,
SERVICE_PAUSED = 0x00000007
}
[Flags]
public enum SERVICE_ACCEPT : uint
{
STOP = 0x00000001,
PAUSE_CONTINUE = 0x00000002,
SHUTDOWN = 0x00000004,
PARAMCHANGE = 0x00000008,
NETBINDCHANGE = 0x00000010,
HARDWAREPROFILECHANGE = 0x00000020,
POWEREVENT = 0x00000040,
SESSIONCHANGE = 0x00000080,
}
VB User-Defined Types:
See SERVICE_STATUS definition
Public Enum SERVICE_CONTROL As Integer
[STOP] = &H1
PAUSE = &H2
CONTINUE = &H3
INTERROGATE = &H4
SHUTDOWN = &H5
PARAMCHANGE = &H6
NETBINDADD = &H7
NETBINDREMOVE = &H8
NETBINDENABLE = &H9
NETBINDDISABLE = &HA
DEVICEEVENT = &HB
HARDWAREPROFILECHANGE = &HC
POWEREVENT = &HD
SESSIONCHANGE = &HE
End Enum
Public Enum SERVICE_STATE As Integer
SERVICE_STOPPED = &H1
SERVICE_START_PENDING = &H2
SERVICE_STOP_PENDING = &H3
SERVICE_RUNNING = &H4
SERVICE_CONTINUE_PENDING = &H5
SERVICE_PAUSE_PENDING = &H6
SERVICE_PAUSED = &H7
End Enum
Public Enum SERVICE_ACCEPT As Integer
[STOP] = &H1
PAUSE_CONTINUE = &H2
SHUTDOWN = &H4
PARAMCHANGE = &H8
NETBINDCHANGE = &H10
HARDWAREPROFILECHANGE = &H20
POWEREVENT = &H40
SESSIONCHANGE = &H80
End Enum
Notes:
None.
Tips & Tricks:
Sample Code:
C#
IntPtr con = Tools.OpenSCManager("\\\\compname", null, (uint)SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
IntPtr serv = Tools.OpenService(con, "ServiceTest", (uint)SERVICE_ACCESS.SERVICE_ALL_ACCESS);
SERVICE_STATUS stat = new SERVICE_STATUS();
bool res = Tools.ControlService(m_serv, SERVICE_CONTROL.STOP, ref stat);
Console.WriteLine("Stop service result: " + res);
// TODO: Code to halt execution until the service has finally stopped, to continue another task afterwards.
Alternative Managed API:
C#
using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;
namespace ServiceHelper
{
/// <summary>
/// Helper class for service control.
/// </summary>
public class ServiceControl : IDisposable
{
private int WAIT_TIMEOUT = 0x00000102;
private IntPtr serviceControlManagerHandle;
private IntPtr serviceHandle;
private IntPtr statusHandle;
private Thread heartbeatThread;
private ManualResetEvent heartbeatStopped;
private ManualResetEvent heartbeatActive;
private ManualResetEvent terminationPending;
private uint waitHintMilliseconds;
private int heartbeatMilliseconds;
public ServiceControl (ServiceBase aServiceBase, uint aWaitHintMilliseconds, int aHeartbeatMilliseconds)
{
FieldInfo fieldInfo;
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
SERVICE_STATUS serviceStatus;
serviceControlManagerHandle = Interop.OpenSCManager (
null,
null,
(uint) SCM_ACCESS.SC_MANAGER_ALL_ACCESS);
if (serviceControlManagerHandle == IntPtr.Zero)
{
throw new Exception (aServiceBase.ServiceName);
}
serviceHandle = Interop.OpenService (
serviceControlManagerHandle,
aServiceBase.ServiceName,
(uint) SERVICE_ACCESS.SERVICE_ALL_ACCESS);
if (serviceHandle == IntPtr.Zero)
{
throw new Exception ("aServiceName");
}
fieldInfo = typeof (System.ServiceProcess.ServiceBase).GetField ("statusHandle", bindingFlags);
statusHandle = (IntPtr) (fieldInfo.GetValue (aServiceBase));
if (statusHandle == IntPtr.Zero)
throw new Exception ("statusHandle is not valid.");
waitHintMilliseconds = aWaitHintMilliseconds;
heartbeatMilliseconds = aHeartbeatMilliseconds;
serviceStatus = new SERVICE_STATUS ();
Interop.QueryServiceStatus (serviceHandle, ref serviceStatus);
serviceStatus.WaitHint = waitHintMilliseconds;
Interop.SetServiceStatus (statusHandle, ref serviceStatus);
terminationPending = new ManualResetEvent (false);
heartbeatStopped = new ManualResetEvent (true);
heartbeatActive = new ManualResetEvent (false);
heartbeatThread = new Thread (IncrementHeartbeat);
heartbeatThread.SetApartmentState (ApartmentState.MTA);
heartbeatThread.Name = "Heartbeat_$" + Guid.NewGuid ().ToString ().Replace ('-', '_');
heartbeatThread.Start ();
}
private SERVICE_STATUS DoQueryServiceStatus ()
{
SERVICE_STATUS serviceStatus = new SERVICE_STATUS();
Interop.QueryServiceStatus (serviceHandle, ref serviceStatus);
return serviceStatus;
}
public void StopHeartbeat ()
{
heartbeatActive.Reset ();
heartbeatStopped.Set ();
}
public void StartHeartbeat ()
{
heartbeatStopped.Reset ();
heartbeatActive.Set ();
}
private void IncrementHeartbeat ()
{
bool terminating = false;
WaitHandle[] dispatchHandles = new WaitHandle[] { heartbeatStopped, heartbeatActive, terminationPending };
WaitHandle[] activeHeartbeatHandles = new WaitHandle[] { heartbeatStopped, terminationPending };
WaitHandle[] inactiveHeartbeatHandles = new WaitHandle[] { heartbeatActive, terminationPending };
while (!terminating)
{
switch (WaitHandle.WaitAny (dispatchHandles))
{
case 0:
WaitHandle.WaitAny (inactiveHeartbeatHandles);
break;
case 1:
if (WaitHandle.WaitAny (activeHeartbeatHandles, heartbeatMilliseconds, false) == WAIT_TIMEOUT)
{
SERVICE_STATUS serviceStatus = new SERVICE_STATUS ();
Interop.QueryServiceStatus (serviceHandle, ref serviceStatus);
serviceStatus.CheckPoint++;
Interop.SetServiceStatus (statusHandle, ref serviceStatus);
}
break;
case 2:
terminating = true;
heartbeatStopped.Set ();
break;
}
}
}
private void DoControlService (SERVICE_CONTROL aServiceControl)
{
SERVICE_STATUS serviceStatus = new SERVICE_STATUS();
if (!Interop.ControlService(serviceHandle, aServiceControl, ref serviceStatus))
{
throw new Exception (serviceStatus.ToString ());
}
}
public void Dispose()
{
heartbeatActive.Reset ();
heartbeatStopped.Reset ();
terminationPending.Set ();
heartbeatStopped.WaitOne ();
Interop.CloseServiceHandle (serviceHandle);
Interop.CloseServiceHandle (serviceControlManagerHandle);
}
}
public class TestService : ServiceBase
{
ServiceControl serviceControl;
public static void Main ()
{
ServiceBase.Run (new TestService());
}
public TestService()
{
InitializeComponent ();
}
protected override void OnPause ()
{
serviceControl = new ServiceControl (this, 60000, 10000);
serviceControl.StartHeartbeat ();
//TODO: Add pause code here ...
serviceControl.StopHeartbeat ();
}
private void InitializeComponent()
{
this.CanPauseAndContinue = true;
this.ServiceName = "TestService";
}
protected override void OnStop()
{
serviceControl = new ServiceControl (this, 60000, 10000);
serviceControl.StartHeartbeat ();
//TODO: Add stop code here ...
serviceControl.StopHeartbeat ();
}
}
internal class Interop
{
[DllImport ("advapi32.dll", SetLastError = true)]
[return: MarshalAs (UnmanagedType.Bool)]
internal static extern bool ControlService (
IntPtr hService,
SERVICE_CONTROL dwControl,
ref SERVICE_STATUS lpServiceStatus);
[DllImport ("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr OpenSCManager (
string machineName,
string databaseName,
uint dwAccess);
[DllImport ("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern IntPtr OpenService (IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport ("advapi32.dll", SetLastError = true)]
[return: MarshalAs (UnmanagedType.Bool)]
internal static extern bool CloseServiceHandle (IntPtr hSCObject);
[DllImport ("advapi32.dll", EntryPoint = "QueryServiceStatus", CharSet = CharSet.Auto)]
internal static extern bool QueryServiceStatus (IntPtr hService, ref SERVICE_STATUS dwServiceStatus);
[DllImport ("advapi32.dll")]
internal static extern bool SetServiceStatus (IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus);
}
}
Documentation
The ControlService function sends a control code to a service.
8/15/2008 12:33:46 PM - 74.74.236.101
The SERVICE_STATUS structure contains information about a service. The ControlService, EnumDependentServices, EnumServicesStatus, and QueryServiceStatus functions use this structure to return information about a service. A service uses this structure in the SetServiceStatus function to report its current status to the service control manager.
7/12/2016 6:17:21 AM - -80.11.84.239
The SERVICE_STATUS structure contains information about a service. The ControlService, EnumDependentServices, EnumServicesStatus, and QueryServiceStatus functions use this structure to return information about a service. A service uses this structure in the SetServiceStatus function to report its current status to the service control manager.
7/12/2016 6:17:21 AM - -80.11.84.239
Please edit this page!
Do you have...
helpful tips or sample code to share for using this API in managed code?
corrections to the existing content?
variations of the signature you want to share?
additional languages you want to include?
Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).