Description
Background and motivation
Currently, there is OnCustomCommand() method in ServiceBase
class which can be overriden and appears to be wired to receive other service control codes sent to underlying native LPHANDLER_FUNCTION_EX callback by the operating system.
However, this method only receives the service control code -- it doesn't receive any other parameters (namely dwEventType
and lpEventData
) which makes it impossible to actually handle any service control codes that require those such as device notifications, power notifications, etc.
Given that it is possible to call RegisterDeviceNotification() using P/Invoke and pass the native service handle from ServiceBase
, it should also be possible to actually receive data that is sent by the OS along with the control code.
I believe this method was misnamed -- it is not receiving commands but service control codes, so I am not sure whether creating an overload with additional parameters is the way to go or if differently named method should be created. I would personally prefer sticking to underlying OS naming, hence the API proposal below.
If it is ever implemented, it would be nice if it was also backported to .Net Framework.
API Proposal
namespace System.ServiceProcess
{
public class ServiceBase : Component
{
protected virtual void HandlerFunctionEx(UInt32 dwControl, UInt32 dwEventType, IntPtr lpEventData, IntPtr lpContext)
{
}
}
}
API Usage
namespace Demo
{
public static class Win32
{
// marshaling omitted for brevity
}
partial class DemoService : ServiceBase
{
protected override void HandlerFunctionEx(UInt32 dwControl, UInt32 dwEventType, IntPtr lpEventData, IntPtr lpContext)
{
Win32.DEV_BROADCAST_HDR dbh = null;
switch (dwControl) {
case Win32.SERVICE_CONTROL_DEVICEEVENT: // handle device events
switch (dwEventType) {
case Win32.DBT_DEVICEARRIVAL:
// do something when device is added
dbh = Marshal.PtrToStructure<Win32.DEV_BROADCAST_HDR>(lpEventData);
break;
case Win32.DBT_DEVICEREMOVECOMPLETE:
// do something when device is removed
break;
}
break;
}
// Call base implementation for the rest (i.e. `OnStart()`, `OnStop()`, etc)
base.HandlerFunctionEx(dwControl, dwEventType, lpEventData, lpContext);
}
}
}
Alternative Designs
Alternative would be creating virtual OnDeviceEvent()
API and marshaling everything involved in the framework itself, but that would take considerably more effort and I am pretty certain just exposing low level access to all parameters would be enough for users like me who need this kind of functionality in a .Net service.
Risks
No response