Complex Structure:
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct SERVICE_STATUS
{
public SERVICE_TYPES dwServiceType;
public SERVICE_STATE dwCurrentState;
public uint dwControlsAccepted;
public uint dwWin32ExitCode;
public uint dwServiceSpecificExitCode;
public uint dwCheckPoint;
public uint dwWaitHint;
}
Easier Structure (which appears to work fine and allows you to avoid defining the SERVICE_TYPES and SERVICE_STATE enumerations and to use CLR compliant types (int)):
[StructLayout(LayoutKind.Sequential)]
private struct SERVICE_STATUS
{
public int serviceType;
public int currentState;
public int controlsAccepted;
public int win32ExitCode;
public int serviceSpecificExitCode;
public int checkPoint;
public int waitHint;
}
For example:
dwWaitHint / waitHint
Estimated time required for a pending start, stop, pause, or continue operation, in milliseconds. Before the specified amount of time has elapsed, the service should make its next call to the SetServiceStatus function with either an incremented dwCheckPoint value or a change in dwCurrentState. If the amount of time specified by dwWaitHint passes, and dwCheckPoint has not been incremented or dwCurrentState has not changed, the service control manager or service control program can assume that an error has occurred and the service should be stopped. However, if the service shares a process with other services, the service control manager cannot terminate the service application because it would have to terminate the other services sharing the process as well.
Requirements
Private Structure SERVICE_STATUS
Dim dwServiceType As Int32
Dim dwCurrentState As Int32
Dim dwControlsAccepted As Int32
Dim dwWin32ExitCode As Int32
Dim dwServiceSpecificExitCode As Int32
Dim dwCheckPoint As Int32
Dim dwWaitHint As Int32
End Structure
Utility class to manage SetServiceStatus()
internal class ServiceStateSignalizer
{
internal enum SERVICE_STATE : int
{
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]
internal enum SERVICE_TYPE : int
{
SERVICE_KERNEL_DRIVER = 0x00000001,
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002,
SERVICE_WIN32_OWN_PROCESS = 0x00000010,
SERVICE_WIN32_SHARE_PROCESS = 0x00000020,
SERVICE_INTERACTIVE_PROCESS = 0x00000100
}
[Flags]
internal enum CONTROLS_ACCEPTED : int
{
SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010,
SERVICE_ACCEPT_PARAMCHANGE = 0x00000008,
SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002,
SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100,
SERVICE_ACCEPT_SHUTDOWN = 0x00000004,
SERVICE_ACCEPT_STOP = 0x00000001,
//supported only by HandlerEx
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020,
SERVICE_ACCEPT_POWEREVENT = 0x00000040,
SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080,
SERVICE_ACCEPT_TIMECHANGE = 0x00000200,
SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400,
SERVICE_ACCEPT_USERMODEREBOOT = 0x00000800
}
[StructLayout(LayoutKind.Sequential)]
internal struct ServiceStatus
{
public SERVICE_TYPE dwServiceType;
public SERVICE_STATE dwCurrentState;
public CONTROLS_ACCEPTED dwControlsAccepted;
public long dwWin32ExitCode;
public long dwServiceSpecificExitCode;
public long dwCheckPoint;
public long dwWaitHint;
};
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool SetServiceStatus(IntPtr handle, ref ServiceStatus serviceStatus);
}
See EnumServicesStatus and EnumDependentServices.
See ControlService for SERVICE_STATE definition.
See SERVICE_TYPES definition.