How to know when system is shutting down?

M

mdb

I have an app that I want to keep open (and hidden with an icon in the
taskbar) when the user presses the 'X' close window button. So I capture
the Closing event on the form and check a bool variable, which if set, sets
e.Cancel on the ClosingEventArgs and sets the Form.Visible=false and the
Form.ShowInTaskbar=false. I have a menu item in the window that allows the
user to actually exit the program by unsetting the bool and then exiting.

The problem is that this apparently prevents the computer from shutting
down, because the e.Cancel is getting set during a shutdown operation. How
can I determine when it is the system requesting closure of the window
instead of the user?

-mdb
 
M

Morten Wennevik

Hi mdb,

In the Closing event, read the StackTrace to determine who called the method.
The 7th last StackFrame is the method triggering the event.

protected override void OnClosing(CancelEventArgs e)
{
StackTrace trace = new StackTrace();
StackFrame frame = trace.GetFrame(7);

if(frame.GetMethod().Name != "DispatchMessageW")
e.Cancel = true;
}

DispatchMessageW is the same as Task Manager-closing of your application, not sure if it would be the same for system shutdown.

"RunDialog"/"SendMessage" = closed by code. ie this.Close();
"DefWndProc" = User close, X or Alt-4
 
W

Willy Denoyette [MVP]

mdb said:
I have an app that I want to keep open (and hidden with an icon in the
taskbar) when the user presses the 'X' close window button. So I capture
the Closing event on the form and check a bool variable, which if set,
sets
e.Cancel on the ClosingEventArgs and sets the Form.Visible=false and the
Form.ShowInTaskbar=false. I have a menu item in the window that allows
the
user to actually exit the program by unsetting the bool and then exiting.

The problem is that this apparently prevents the computer from shutting
down, because the e.Cancel is getting set during a shutdown operation.
How
can I determine when it is the system requesting closure of the window
instead of the user?

-mdb

Handle the WM_QUERYENDSESSION mesage in your overriden WndProc for your
form.
Something like this should do..

private static bool shutdownRequested = false;
protected override void WndProc(ref Forms.Message msg)
{
const int WM_QUERYENDSESSION = 0x11;
if (msg.Msg==WM_QUERYENDSESSION)
{
// set this flag to true if the System is about to shutdown
// Check this flag in your Closing handler.
shutdownRequested = true;
}

// If this is WM_QUERYENDSESSION, the closing event should be fired
// in the base WndProc
base.WndProc(m);
}


Willy.
 
W

Willy Denoyette [MVP]

James Curran said:
Look at System.Environment.HasShutdownStarted

James,

This flag is set when the CLR is about to shut down not as a direct result
of a system shutdown, this flag is set way after the Closing events are
fired and as such cannot be used in this scenario.

Willy.
 
W

Willy Denoyette [MVP]

cody said:
Why not simply use the SystemEvents.SessionEnding event?

Because OP needs to do some processing before the Closing event gets fired,
see Remarks in SessionEnding to how this should be done.

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top