To Main Page

View in Russian

How to shut down the system correctly
Frequently in development of the software for computer management there is a necessity for a code which shuts down operation system without user participation. It seemed, that it can be done easy: there is ExitWindowsEx API function, doing it, however so simple decision works not always. The thing is that each application started on the computer, has the right to cancel system shutdown or to suspend it, by showing a pop-up window. Basically, it is possible to avoid it by call of ExitWindowsEx with EWX_FORCE flag, but in this case all applications are terminating by a method of "rough force", which may result in data loss. Some applications react to such method of terminating inadequately, for example, WinPopup shows a pop-up window, and if at the moment of ExitWindowsEx call there were already any pop-up windows on the screen, the system may crash.

The decision of the task arises with itself: it is necessary to close all working applications before ExitWindowsEx call, and so correct, as far as it is possible.

What may be considered as "correct closing of application"? It is possible to discuss this question very long, and the decision will be specific for each application. Therefore we shall not look throw a question of data preservation in open documents here (it's necessity, on my sight, is rather disputable), but we shall try to find a sequence of commands, common for all applications, and, as a rule, resulting to their closing without of "rough force" of TerminateProcess function.

So, action first: we are closing all pop-up windows, visible on the screen, by sending them WM_CLOSE message. We are waiting some time, while applications are processing the message.

Action second: we are sending to all top-level applications' windows WM_CLOSE message. It is equivalent to clicking the cross in a right top corner of a window. Different applications react on it differently: the first may close itself obediently, second will show a pop-up window, third will move itself to tray, fourth can simply ignore this message. Again we are waiting some time.

Action third: again we are closing emerged pop-up windows (it is possible to press the default button on these windows, but, on my sight, it can cause undesirable consequences, for example, the file will be saved without user permission while he/she was not going to save it by security reason), and again we are waiting slightly.

Action fourth: we are notifying remaining applications of system shutdown by sending to their top-level windows WM_QUERYENDSESSION message. This message returns a value, and if it is not equal to zero, the application permits system shutdown. In this case we are sending WM_ENDSESSION message to it. After that the application must close itself. We are waiting.

Action fifth: again we are closing emerged pop-up windows. We are waiting.

Action sixth: we are destroying remaining applications using TerminateProcess API. We warned them! Here it is necessary to mean, that some top-level windows can belong to one process, and consequently it is necessary to make provision for TerminateProcess function is not applying repeatedly to such processes. Once again we are waiting.

Action seventh: here now, at last, it is possible to call ExitWimdowsEx function.

In the above-stated sequence of actions the applications which have no visible windows, are not closing before ExitWimdowsEx call. As a rule, such applications are specially developed for work without user intervention, and are normally closing with operation system.

It is more preferable to some applications, that they are closing only together with OS: for example, Windows Explorer and Internet Explorer in this case keep windows set and arrangement. This group includes also Program Manager and WinPopup. The classes of their windows make the list of exceptions when messages are sending.

There are features of using of all stated above in Windows NT/2000. Firstly, ExitWindowsEx will work correctly only if the process is started under account with sufficient rights (it should belong to Administrators or Server Operators group), but it is not enough: the process must obtain "SeShutdownPrivilege" privilege. How to do it - see source code and Knowledge Base article. Secondly, all this is meaningful only when the program, shutting down the system, works on an interactive desktop. If this program is started as a service or by Task Scheduler, it can "not see" the user applications' windows, and can not close them. However, in Windows NT/2000 there is a InitiateSystemShutdown function, which practically always shuts down the system.

See also:

Microsoft Knowledge Base Q161136, Q168796.
Download the source code (18 kB)

This page has been updated last time on 13-Jun-2000
2000 Sergey Merzlikin
Write me: