To make this answer perhaps more generally useful, I will assume here that the application wants to give the user a choice about whether to shut-down the machine, or not. That's an expansion of the topic beyond what the OP has asked.
Try this (my corrected version of Microsoft's incorrect example of using 'SessionEnding) [^
private static int WM_QUERYENDSESSION = 0x11;
private static bool systemShutdown = false;
protected override void WndProc(ref System.Windows.Forms.Message m)
if (m.Msg == WM_QUERYENDSESSION)
MessageBox.Show("queryendsession: this is a logoff, shutdown, or reboot");
systemShutdown = true;
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
systemShutdown = false;
if (DialogResult.Yes == MessageBox.Show("My application",
"Do you want to save your work before logging off?",
e.Cancel = true;
e.Cancel = false;
But, you may not be satisfied with the result. If you use this in Win 8.1, for example, assuming your application is running, when the user shuts-down the computer:
1. Some applications (not yours) are going to get shut-down before the shut-down process is halted by the code shown above.
2. The shut-down will halt at a blue-screen with information about what is preventing the computer from shutting-down, and your program will be among the items listed.
3. from that blue-screen the user can either cancel and return to whatever state is now current (remember that some applications may have been shut-down): if you cancel the shut-down, you will then see your dialog box. From that blue-screen any blocking application can be forced to close.
Other things to keep in mind:
1. MS cautions you ... re this technique: "Because this is a static event, you must detach your event handlers when your application is disposed, or memory leaks will result." But, as often with MS docs, there's no practical example given of this.
2. The end-user could have shut-down your application using the Task Manager. Perhaps that's not important here, and you can handle that in the 'FormClosing EventHandler by evaluating if e.CloseReason == CloseReason.TaskManagerClosing