Calling ShutdownBlockReasonCreate from my service doesn't stop the user from shutting down


A customer had a service application that needs to perform a sequence of operations that cannot be interrupted by a system shutdown.

The service starts performing those operations when it starts up, but we found that group policy or other shenanigans can trigger other actions that ultimately lead to a system reboot. We would like to delay the reboot until our service completes its critical sequence of operations.

We created a simple test application that calls Shutdown­Block­Reason­Create, and it works. If we try to reboot the computer, the shutdown dialog appears indicating that it is waiting for the test application to complete.

We ported this code into the service, and even though the call succeeds, there is no message shown to the user at reboot, and the reboot proceeds anyway.

Is Shutdown­Block­Reason­Create expected to work when called from a service? If so, then what we are doing wrong? If not, what alternative designs are available?

Shutdown blocks apply only to the session in which they are created. This is sort-of implied by the fact that the Shutdown­Block­Reason­Create function is exported from user32.dll, and it takes a window handle parameter, and window handles are valid only in the desktop from which they were created. Since the interactive session is session 1 and services are in session 0, the block request has no effect. (This is just another application of the principle Does this work in a service? The default answer is NO.)

Note also that the shutdown block is not a hard block. The user could click "Shut down anyway". Besides, the system assumes "Shut down anyway" if the user takes no action within some number of seconds.

Note also that if the system is shut down remotely, there is nobody present to answer the question, and it's not clear where to display the message anyway.

The correct way to delay shutdown indefinitely from a service is to set the SERVICE_ACCEPT_PRE­SHUTDOWN flag in its service status. This registers the service for preshutdown notifications, at which point it can finish up your critical actions before releasing shutdown to continue.

Note that long shutdown times is one of the major points of end-user frustration, so you should do what you can to wrap things up quickly. Otherwise, you're going to be another data point in the "Windows sucks" database.

Comments (24)
  1. Damien says:

    And, of course, the usual "the guy driving the JCB who's about to sever the power cables doesn't see anything that will prevent them shutting down your computer"

  2. Joshua says:

    I'm used to everything working in services. I have this program that opens a window, does its thing (window's only for feedback) and closes the window. It works just fine from a service. Of course nobody sees it.

  3. Yuri says:

    The typical case I run into is a lousy service that doesn't stop it's threads when shutdown is invoked.

  4. David Crowell says:

    Outside of some very narrow use-cases (prompting for file save), anything blocking a shutdown should hurry up and finish it in less than 100ms or so.  If you take much longer, either the user or the system will pull the rug out from under you.

  5. SimonRev says:

    @David -- these days I disagree that even prompting to save is a valid reason to delay shutdown.  Your application should simply save any unsaved documents to a temporary folder and then reload those the next time it starts, much like phone apps do.  (I am sure that there are exceptions such as if the temporary save file would be gigabytes in size)

  6. SimonRev says:

    One reason that prompting to save is no longer valid is that Windows Update is going to restart you either way, so why make the restart experience a bad one for users.

  7. Darran Rowe says:

    @SimonRev:

    There could also be ways around the large saves too, like saving user action or deltas to the temporary files. If the application does this regularly, it could then exit quite quickly if needed. Of course, there are also tradeoffs for even this, like having to use more memory, and using idle time to compact things.

    I have actually seen too many cases where people try to do stuff at shutdown time and ultimately get defeated by the user getting annoyed.

  8. prshaw says:

    A valid reason might be that the system is updating an external piece of hardware and interrupting the process will brick the hardware. Oh, and the update takes about 10 minutes to do. Real case that I am dealing with.

  9. Yuri says:

    I just wish Windows could better identify the offending process when it is 'svchosted'. Otherwise putting the blame on the application seems a reasonable solution to me. Outstanding critical transactions are  unavoidable after all.

  10. Ian Boyd says:

    @prshaw You might want to do that from an interactive session, where you can at tell the user that you are about to undertake a long, dangerous, operation. Check that the PC is not running on battery (GetSystemPowerStatusRef(out status); Assert(status.ACLineStatus <> 0)), and remind the user not to shutdown the machine.

    Which is a long way of saying, you maybe should not do it from a background service.

  11. John says:

    @SimonRev

    Unless you redirected your temporary files to a RAM Drive at which point saving the data to that temporary location is moot, perhaps saving to %AppData% for that program? But then again its all relative.

    I for one don't mind having it prompt on shutdown and having it halt a shutdown (its saved me at least once or twice, probably many more times than I remember).

  12. Viila says:

    SimonRev: This sort of thing is why I really don't like the new update policies for home users in Windows 10. I have a 3D printer and given how much cheaper they're becoming so will a lot of people in the future.  I'd be extremely cross if I found out that Windows had decided to update and reboot in the middle of a 12 hour print run...

  13. DWalker says:

    @Ian:  And never do a BIOS or any firmware update during a lightning storm, when power is unreliable.  Even if your computer is running on a UPS.

  14. prshaw says:

    @Ian Boyd If it wasn't a headless system that might be an option but in this case the PC is controlled by another (much older) computer and all commands come from it. Including the shutdown commands. I can't do anything about power going out (we would be just one of several hosed systems) but trying to protect against impatient users is the goal.

  15. DWalker says:

    @prshaw:  "Protect against impatient users".  Some users hate it when the software thinks it knows better than the user!

    How many posts have you seen saying "stupid computer, I know what's best, don't try to tell ME what to do, it's MY computer!  I should be able to do what I want!  I hate Windows!!!"

  16. prshaw says:

    @DWalker agreed, at least they don't know it's windows :)

    Think of it more like your cell phone. It tells you that you have an update to firmware that will take a long time to update. You start the update and it is working it's way through it. 5 minutes later you need to go do something and it is still working away. The phone is doing it's best to keep you from killing the update and bricking your phone, but you could always just pull out the battery. We could say we hate the OS on the phone because we can't stop the update but that doesn't happen often in this case. Now instead of a 100 dollar phone image updating something that cost 10s to 100s of thousands of dollars, need to try and keep it going as best as we can.

  17. That fullscreen shutdown dialog that was introduced in Vista never made any sense to me (it's nice to know it can be disabled through group policy). If you put up a dialog that prevents the user from responding to the application that is preventing shutdown you basically only give them two options. Cancel shutdown or shutdown anyway and possibly lose data. None of those are good options. It needs the option to allow you to respond to each application. You might want to respond to one application by shutting down anyway. To another application you might want to save your files first.

  18. The two programs which always seem to hold up shutdown on my system are Skype and Norton Ghost.  Ghost blocks indefinitely if it's running a backup, asking if you really want to cancel it.  I've no idea what Skype is doing, but it just seems to hate being closed at the best of times.

  19. AndyCadley says:

    @Master Programmer: Like many things in Vista, it was designed to make developers move away from bad habits. Replacing the easy "Do you want to save?" prompt with something that auto saves and plugs into Restart Manager to restore the application post-reboot gives a much better end user experience and the full screen dialog pushes developers down that route.

  20. 640k says:

    Some stupid developers don't get it. It's the *user's* computer. Software is there on a visit, if the owner tells you to leave, it's *his* choice, and the software better hurry.

    There is NO excuses. In no way is software allowed to depend on atomic transactions, especially if they are long running. That's bad design that went out the door ages ago. Please re-learn how to create a modern architecture, and that includes attached hardware.

  21. Edward M. Grant says:

    There are legitimate reasons to not want a PC shut down until an operation is complete, but those operations are usually things where you can rely on the user not shutting it down because they know it's a bad idea. Blocking the shutdown makes about as much sense as those inane 'Saving game. Do not turn off your PC' messages I get in so many PC games that have been cheaply ported from consoles... who in the heck is going to turn off their PC while playing a game? And who's going to shut it down while it's programming the flash on some industrial hardware?

    When you adopt the 'PC knows best' approach, you end up with the situation I ran into a few years ago, I was going away for the weekend, and I told my XP PC to shut down. Loaded the car, went away, came back two days later. The PC was sitting there in the bedroom at some kind of 'do you really want to shut down without saving stuff?' dialog box. Had been running all weekend, even though I'd told it to shut down, just because some crappy piece of software had told Windows not to do what I told it to do.

    Needless to say, I wasn't impressed. At least the new one shuts down so fast with its SSD that I don't have to stand there for too long to see that it really did actually shut down.

    Of course, Windows itself has historically been one of the worst offenders. A few weeks ago a friend needed a Windows computer to backup some files from their phone using some Windows software, so I grabbed my old XP laptop that I hadn't used for about two years, and drove over. Did the backup, and went to shut it down.

    'Windows is installing 57 updates. Do not switch off your PC.'

    This is a laptop that would probably never be booted again, and I actually kind of wanted to go home, not sit there while Windows updated itself. After half an hour, it was barely half-way through installing the updates. I finally turned it off and went home (and, for the record, when I turned it on the next day just to see what awful things happen when you ignore the warning and shut the PC down, it booted fine).

    Actually, on that subject, I often update the firmware in hardware that costs tens of thousands of dollars, and it wouldn't care if we rebooted the PC in the middle, because it just boots from the secondary flash if the primary is corrupt. In the worst case, we can pull out the JTAG programmer and stuff the firmware in that way. It's not a big deal, unless the hardware designers make it so.

  22. bv1 says:

    The normal next step for a user is to pull the power when a reboot gets hung.  So besides getting added to the "Windows sucks" database, if you do not put out a countdown timer, a message informing the user (please do not power off as the hard will be corrupted and all your data lost.) or other communication as to why you did not want a shutdown to occur, the user can still override you.  Do not complain about ignorant users if you do not communicate with them. And yes, as Raymond says, you need to finish up quickly.

  23. Max says:

    @prshaw: Sounds like the user should be prevented from sending commands to that remote computer while it's performing the update process. Either that, or run the update when no users are using the system, or when no users should be using the system. A ten-minute update process, during which the machine is presumably unusable and the user is presumably given little to no feedback, is a terrible user experience, it's not surprising that they're not doing things the way you want, and the obvious place to put the roadblock for destructive behavior is in the method of communication to the headless server rather than the headless server itself. There's (presumably) no reason for the headless server to be accepting commands during that process.

  24. Joshua says:

    @Max: That doesn't do any good at all when the process is attempt to interrupt an automatically initiated suspend/shutdown/hibernate. (Gee, I see I've been idle for five minutes, according to the system config I need to hibernate now. But this process needs to say NOPE to that.)

Comments are closed.

Skip to main content