Curtis
Curtis

Reputation: 5892

Is there a way to detect a System-Shutdown from a .net C# Console App and delay the shutdown until your program can gracefully exit?

Keep in mind, this is a Console App running .NET with C#. Also, I might later convert this into a service, but for now, I need to handle the shutdown while my Console App is running.

My system sometimes gets shutdown automagically by Windows Updates or by Kace Updates. This is irritating when my program is in the middle of doing long tests in the middle of the night and I'm not there to see it happen. I would like to be able to detect the system shutting down and delay it long enough for my tests to finish gracefully and allow me to gracefully exit my program keeping all my test data intact.

I've looked at various threads and can't seem to find a working solution. I've tried both of these:

 AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
        Application.ApplicationExit += OnApplicationExit;

But neither of these events seem to get fired. I basically want to send an e-mail notification to myself when the shutdown is detected and pause the shutdown. Or at least log a message somehow...

I can simulate this behavior using (of all things) 'notepad.exe'. I just open notepad.exe, type some junk, and then attempt to ShutDown my computer. The computer tries to shutdown, and then shows a message that says it cannot shut down because 'notepad' is blocking it.

I would like MY program to block the shutdown (or at least delay it) the same way as 'notepad.exe' does it.

Any information, events, or other ideas that you may have would be very useful. Thanks in advance for your assistance.

Upvotes: 4

Views: 1495

Answers (1)

Leandro Bardelli
Leandro Bardelli

Reputation: 11578

This can help you:

https://www.meziantou.net/prevent-windows-shutdown-or-session-ending-in-dotnet.htm

When the user logs off or when he stops his machine, Windows quits all open applications. Some applications want to execute code before ending in order not to lose the current state (a document being written for example).

For this Windows sends a message to all applications:

WM_QUERYENDSESSION when closing the session
WM_ENDSESSION when shutting down the machine

Windows provides 3 methods:

ShutdownBlockReasonCreate

Indicates that the system cannot be shut down and sets a reason string to be displayed to the user if system shutdown is initiated ("I want to live" in the screenshot)

ShutdownBlockReasonDestroy

Indicates that the system can be shut down

SetProcessShutdownParameters

This function sets a shutdown order for a process relative to the other processes in the system

The final method determines the order in which Windows sends the WM_ENDSESSION and WM_QUERYENDSESSION messages to the applications. This is used in the case where an application A depends on an application B. The application A wishes to be informed before the application B that the machine is stopping to potentially block this stop. Thus application B remains alive as application A blocks the shutdown.

The priority is defined with an integer between 0 and 0x4FF. 0x4FF is the highest priority (called first), 0 is the lowest priority (last called). By default, applications have priority 280.

In the link there is also a code for WinForm that can be adapted. Something like:

private const int WM_QUERYENDSESSION=0x0011;
private bool isShuttingDown=false;
protected override void WndProc(ref Message m)
{
if(m.Msg==WM_QUERYENDSESSION)
{
isShuttingDown=true;
}
base.WndProc(ref m);
}

Upvotes: 2

Related Questions