53

I have an issue with my application when Windows shuts down - my app isn't exiting nicely, resulting in the End Task window being displayed. How can I use the debugger to see what's going on?

Is there a way to send the Windows shutdown message(s) to my application so it thinks Windows is shutting down, so I can see exactly how it behaves?

EricLaw
  • 56,563
  • 7
  • 151
  • 196
Rory
  • 40,559
  • 52
  • 175
  • 261

5 Answers5

65

There is a tool named Restart Manager (rmtool.exe) in the Microsoft's Logo Testing Tools for Windows, which can be used to send shutdown and restart messages to a process. Logo testing tools can be downloaded here:

http://download.microsoft.com/download/d/2/5/d2522ce4-a441-459d-8302-be8f3321823c/LogoToolsv1.0.msi

Then you can simulate shutdown for your process:

rmtool.exe -p [PID] -S

where [PID] is the process ID. According to the Vista Logo Certification Test Cases document,

Restart Manager shutdown messages are:

a. WM_QUERYENDSESSION with LPARAM = ENDSESSION_CLOSEAPP(0x1): GUI applications must respond (TRUE) immediately to prepare for a restart.

b. WM_ENDSESSION with LPARAM = ENDSESSION_CLOSEAPP(0x1): The application must shutdown within 5 seconds (20 seconds for services).

c. CTRL_SHUTDOWN_EVENT: Console applications must shutdown immediately.

Community
  • 1
  • 1
dkl
  • 3,850
  • 2
  • 27
  • 26
  • awesome! (I haven't tried it yet - if anyone uses it and can provide feedback that'd be great) – Rory Apr 20 '10 at 22:01
  • 6
    Your link is broken. The Logo Testing Tools were part of the old Windows 7 Client Software Logo Program. The tools are no longer on Microsoft's website. The tools seem to have been superseded by the Windows App Certification Kit, which is part of the Windows 10 Desktop App Certification Program. The kit doesn't include `rmtool.exe`, only `rmlogotest.exe`. I've written a little bit about `rmlogotest.exe` elsewhere; to read what I've written, follow [this link](http://superuser.com/questions/959364/on-windows-how-can-i-gracefully-ask-a-running-program-to-terminate#1154058). – unforgettableidSupportsMonica Dec 07 '16 at 18:23
  • `rmlogotest.exe` does send some messages to your app, and I suspect they're the same messages that `rmtool.exe` used to send, but I haven't checked to be sure. – unforgettableidSupportsMonica Dec 07 '16 at 18:23
  • The link returns a 404 error indicating the file no longer exists. – Rami A. Mar 08 '18 at 04:34
  • 3
    To open the link, you can use Wayback Machine website: https://web.archive.org/web/20070403002537/http://download.microsoft.com/download/d/2/5/d2522ce4-a441-459d-8302-be8f3321823c/LogoToolsv1.0.msi – itaiy Aug 20 '18 at 12:02
8

I believe when Windows is shutting down it sends a "WM_QueryEndSession" to all applications. To simulate a Windows shutdown you could create a little application that just does a PostMessage with this message to your application and see what happens. Windows may send more messages than that to actually close your application (like WM_CLOSE), but whenever your application receives the "WM_QueryEndSession" message it means your application is about to have the rug pulled out from under it.

Jon Tackabury
  • 47,710
  • 52
  • 130
  • 168
  • 1
    Also, WM_QueryEndSession is followed (given the all-OK by the apps that receive it) by WM_EndSession. – JMD Feb 06 '09 at 16:24
  • Excellent - thanks for the clarification JMD. I figured there had to be an additional message, but I wasn't sure what it was. – Jon Tackabury Feb 06 '09 at 16:25
  • Any useful utils that I can use to send such messages instead of crafting one myself? – Rory Feb 06 '09 at 16:28
  • 1
    I don't know of any applications, but you could do this: [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam); Then just call PostMessage(handle, WM_whatever, IntPtr.Zero, IntPtr.Zero); – Jon Tackabury Feb 06 '09 at 16:39
  • 1
    Oh, and to get your window handle from outside your application you can use Spy++ that comes with Visual Studio, or the excellent "Winspector Spy" which is freely available and easier to use. – Jon Tackabury Feb 06 '09 at 16:41
  • @JonTackabury - If I may suggest a way to post code in comments in the future. Inclusion of a character sequence unique to the string would allow one to search replace it with `\n`/equivalent in compatible code editors. – user66001 Mar 10 '16 at 17:01
2

This can be done using rmlogotest.exe tool. See following link:

https://superuser.com/questions/959364/on-windows-how-can-i-gracefully-ask-a-running-program-to-terminate#1154058

If you're using WPF, then you can handle additional event:

        Application.SessionEnding += Application_SessionEnding;

where you can set e.Cancel = true; to be able to abort application closure.

I think rmlogotest.exe uses timeout of 5 seconds and then it will tell you that LOGO Validation FAILED.

If you put some sort of message box confirmation in your application - you get failure as for end-user it will take probably more than 5 seconds to respond.

I guess from windows perspective if 5 seconds passed by, it want to reboot anyway - and if end-user hasn't saved his document / work - then windows is expecting to copy it somewhere else maybe.

From my perspective (as application developer) - it's acceptable to have failing LOGO Validation FAILED, as user can decide on it's own - whether he will kill my application after 5 seconds and looses his document or he will save the document and closes my application manually.

If you need to broadcast WM_QUERYENDSESSION message, then it needs to be sent via SendMessage to all windows in current process. Starting sample code can be found from here:

https://github.com/qakit/headless.git

But it sends only WM_ENDSESSION message, you need to use WM_QUERYENDSESSION instead and add windows enumeration of given process.

Related links:

TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
1

SendMessage can be used to send window messages with any parameters to a window.

Very useful for debugging and testing.

  1. Send the message WM_QUERYENDSESSION with LPARAM = ENDSESSION_CLOSEAPP. The application must return 1 (TRUE) to indicate it's prepared to shut down and restart.

  2. Send the message WM_ENDSESSION with LPARAM = ENDSESSION_CLOSEAPP The application must shut down within the specified timeout period.

Rami A.
  • 10,302
  • 4
  • 44
  • 87
1

You could use the SystemEvents.SessionEnding event, which is fired when a user logs off or shuts down. Be careful when using it though, some resources are not guaranteed to be available. For example, my application needed to hit a server when it was shutting down to clock a user out (a timeclock application), but the network card is sometimes already disabled when this event occurs. Since you're just doing cleanup, this should work fine.

jamesmillerio
  • 3,154
  • 4
  • 27
  • 32