?
Solved

Stop Windows shutdown from a service

Posted on 2003-03-23
5
Medium Priority
?
1,360 Views
Last Modified: 2012-05-04
Hi all experts,

I have a C application that runs as service in Windows XP. I want to be able to warn the user before the computer is being shut down and halt the shutdown if the user chooses to. FYI, the program was developed using Visual C++ using the Win32 Console Application option. I just added some codes found on the Net to make it a service and it's not an ATL COM service or anything fancy.

I know 'normal' program can use message maps to catch the WM_QUERYENDSESSION and return a false answer (not really sure though) to prevent shutdown. How can I do that with a service because services due to their nature are supposed to run silently in the background. The best I can do now (and it's really lame) is pop up a message box using the MB_SERVICE_NOTIFICATION by putting some codes under the ServiceHandler SERVICE_CONTROL_SHUTDOWN case but this hardly suffice as I can't prevent the shutdown and there's no option for the user to click Yes or No.

Is there anyway I can do this at all? Is the WM_QUERYENDSESSION message sent to services at all? Please provide source codes if possible. Points will be increased if I feel the accepted answer is thorough and, of course, solves my problem as soon as possible.
0
Comment
Question by:js_cheng
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
5 Comments
 

Accepted Solution

by:
vadimtsarik earned 450 total points
ID: 8192536
The way I see the solution of the problem is as follows:

1. Your service should be setupped to be able to interact with desktop ('Allow service to interact with desktop' checkbox should be checked).

2. Your service creates a hidden normal window (to trap WM_QUERYENDSESSION) in the required desktop (there may be more the one desktops in Win2000\XP). You may probably need to use function EnumDesktops() for that.

3. Your service calls SetConsoleCtrlHandler to trap logoff events (to gracefully close hidden windows, created by the service)

This way you will be able to trap WM_QUERYENDSESSION and query for user confirmation. These are just guidelines, but I hope the idea is clear.
0
 

Author Comment

by:js_cheng
ID: 8195331
Vadimtsarik,

Thank you for your comment but it still seems a bit general there. I'm not entirely sure but I think SetConsoleCtrlHandler can't stop a shutdown from happening. It can only intercept CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT to do some clean up before shutdown, something that is similar to ServiceHandler's SERVICE_CONTROL_SHUTDOWN case option.

The idea about creating a hidden windows sounds interesting though. Maybe you can explain more I can go on about doing that? I'm not very experienced when it comes to programming for Windows.

Is there anyway I can add message maps to a console program. Normal Win32 program can handle these messages and event easily thorugh message maps but I don't know how to do it in my program. Any ideas?

Thank you again.
0
 

Author Comment

by:js_cheng
ID: 8258331
I've added codes for creating a window in the service program and run it as a local system account with 'Allow service to interact with the desktop' checked. The Window Procedure funtion for this window is created to handle WM_QUERYENDSESSION and pops up a message box asking for user confirmation before returning a boolean value. Unfortunately, when opened up through the service, the window will receive the message but Windows XP does not wait for the reply. The window and message box is closed if the user does not click a button immediately. The usual not responding and end task message doesn't even appear. Why is this happening?

Please help. Thank you.
0
 
LVL 49

Assisted Solution

by:DanRollins
DanRollins earned 300 total points
ID: 8259538
>>Why is this happening?

That is exactly what is supposed to happen.  If you give it any thought at all, you would realize that.  

If no user responds to the popup, then the system must continue with the shutdown process.  And that means forceably killing the stubborn process.

Have you tried simply returning FALSE?

I can't find out if the system treats Services different in this regard, but I would not be surprised if they were treated as second-class citizens and either give a *very short* time to respond or simply closed.  Here is a reasonable explanation of why:  Imagine a standard service that cannot interact with the desktop.  If it waited for user input, it would wait forever and never let the system shutdown.  That means users who are angry at Microsoft and at your company because "the system inexplicably hangs when I try to shut down" It also means that automatic procedures such as rebooting after a critical system update would fail.  And it also means a hard reset or forced power off ... which is bad bad bad.

=-=-=-=-=-=-=-=-=-
Finally, look at the ExitWindowsEx API.... notice that it is possible to call this function and specify EWX_FORCE or EWX_FORCE or EWX_FORCEIFHUNG and that effectively overrides any WM_QUERYENDSESSION handling.... It just gives each process a chance to do immediate final cleanup.

And one last thing:  WHY ON EARTH DO YOU WNAT TO PREVENT SHUTDOWN?  This can only cause problems for anyone who uses your software.

-- Dan
0
 

Author Comment

by:js_cheng
ID: 8587379
Hi and sorry for the late response. Been busy lately.

Anyway, I've done the shoutdown thing successfully by creating a window from the service and writing my own Winproc function. Contary to Dan's remarks, it does work (to a certain extent) except that on certain machines some other programs will somehow interfere.

And Dan is right about preventing shutdown being bad bad bad. Anyone reading this should be aware that it is just bad programming practice to mess around with users computers this way (unless you want user to come after you with baseball bats :-)

Anyhow, I wanted to do it because the organization I work for requires it and we have problems with ID10T users shutting down the PC while it is doing something important. However, as a saving grace for my disruptive program, I have, as a good measure, put in a messagebox informing the user of what the PC is doing and telling the about the abortion of shutdown.

Thanks for all the useful comments. I think I'll just split the point between the two of you. A bit more to vadimtsarik for his comments about desktop (although actually there's no need for enumdesktop as there is another way of getting the current desktop).
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
What do responsible coders do? They don't take detrimental shortcuts. They do take reasonable security precautions, create important automation, implement sufficient logging, fix things they break, and care about users.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
Simple Linear Regression

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question