Sunday, March 04, 2012

Handling pre-shutdown notification in C# Windows service

In this post I am going to explain how pre-shutdown notification can be enabled and handled in C# Windows service.

The need for pre-shutdown notification
Starting from Windows Vista on wards Windows provides an mechanism to notify applications/services about the system shutdown/reboot. Though shutdown notification was already supported through ServiceBase class's CanShutdown property and OnShutdown method their functionality is very limited.

The limitation of OnShutdown method is, limited time given for the cleanup work and there is no guarantee that other essential services(e.g. DB, EventLog) are running. The last point is the fundamental reason why Microsoft brought this pre-shutdown notification.

Enabling pre-shutdown notification
If we are developing a Win32 application it is really easy to enable pre-shutdown notification. All we need to do is include "SERVICE_ACCEPT_PRESHUTDOWN" flag in dwControlsAccepted field of service's SERVICE_STATUS structure.

But in .NET's ServiceBase class there is no direct way to enable pre-shutdown notification. We can achieve the goal by accessing the ServiceBase class's internals through .NET reflection.


  FieldInfo acceptedCommandsFieldInfo =
      typeof(ServiceBase).GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic);
  if (acceptedCommandsFieldInfo == null)
    throw ApplicationException("acceptedCommands field not found");
  int value = (int)acceptedCommandsFieldInfo.GetValue(this);
  acceptedCommandsFieldInfo.SetValue(this, value | SERVICE_ACCEPT_PRESHUTDOWN);
In the constructor of the service "MyService" we add the "SERVICE_ACCEPT_PRESHUTDOWN" flag to "acceptedCommands" private field of ServiceBase using reflection. This enables the pre-shutdown notification.

Handling pre-shutdown notification
The pre-shutdown notification is delivered through the ServiceBase class's "OnCustomCommand" method. This method is called whenever a command is sent to the service which is not supported by ServiceBase. The method provides a parameter "command" which holds the command code. So to handle the pre-shutdown notification we need to check whether the "command" matches with pre-shutdown notification code.
protected override void OnCustomCommand(int command)
      // do the clean-up here
So that is all we need to enable and handle pre-shutdown notification.


gaaah said...

Hi, how did you know that "acceptedCommands" was a field that was available? Or do these fields only show up at runtime? I couldn't find them with the Object broswer. Thanks, you saved me from attempting a bunch of pinvoke madness. --tom

Siva Chandran P said...

It may not show up in the ObjectBrowser but it shows up in Reflector as private field.

Anonymous said...

Is the code provided GPL, i.e. may I use it for a GPL project?


Siva Chandran P said...

Yes, you can use it in your project.

Unknown said...


When using "shutdown -s -f -t 3600".

How can i avoid the "system will shutdown in 10 minutes" notification.??

Thank you!
Diego M.

Siva Chandran P said...

I don't think we can control that, but I am not sure.

Kimberly Cox said...

Thank you for such advice, I just wanted to turn off these notices, because they terribly annoyed me. Also, if you suddenly have problems with api-ms-win-crt-runtime-l1-1-0.dll missing I can recommend the site that I use. There are instructions and articles, as well as files that are needed for installation. It always helping to me with my windows.