Board index » cppbuilder » Re: HELP: My app closes, but cancels Windows shutdown?

Re: HELP: My app closes, but cancels Windows shutdown?


2007-03-09 02:39:47 AM
cppbuilder44
A Nonymous < XXXX@XXXXX.COM >writes:
Quote
I have an application that used to shutdown gracefully if it was
running when Windows shutdown. Now I noticed that my application
shuts down, but it also seems to cancel the Windows shutdown.
Please post this in the nativeapi, as it has nothing to do with the
rules/usage of the C++ langauge.
--
Chris (TeamB);
 
 

Re:Re: HELP: My app closes, but cancels Windows shutdown?

I have an application that used to shutdown gracefully if it was running
when Windows shutdown. Now I noticed that my application shuts down, but
it also seems to cancel the Windows shutdown.
I trap/handle the WM_QUERYENDSESSION and WM_ENDSESSION messages to save my
files and close. I set the Msg.Result = 1 (ok to shutdown) in each handler
so Windows should continue to shutdown. It use to work...
I did some research and apparently any 3rd party component that is using
AllocateHWnd and not calling DefaultWindowProc in the handler method can
cause this problem. In that case the handler method is answering 0 to
WM_QUERYENDSESSION which tells Windows to cancel the shutdown.
This is a BIG application and I use a lot of components. I created a new
project and have been adding components one at a time to see what kills the
shutdown. With an almost 5 minute reboot cycle this is EXTREMELY time
consuming. There must be a better way?
Does anyone know any way of "tracing" a message so I can see where
Msg.Result is being set incorrectly?
I also created a test application that sends the WM_QUERYENDSESSION and
WM_ENDSESSION messages to my app in an attempt to "fake" the shutdown, but
it seems to report that my app is responding properly.
Something is going wrong but I am having trouble finding it.
Can anyone help?
 

Re:Re: HELP: My app closes, but cancels Windows shutdown?

More info:
My original code which has not changed in a LONG time and used to work
fine:
void __fastcall TFormMain::wmQueryEndSession(TMessage& Message)
{
Message.Result = 1;
SaveFile();
CloseFile();
Application->Terminate();
}
My fake shutdown app is just a form with a button and a memo. The
button press event looks like this:
void __fastcall TForm1::ButtonQueryEndSessionClick(TObject *Sender)
{
Memo->Lines->Append("Send WM_QueryEndSession Message:");
WPARAM wParam = 0;
LPARAM lParam = 0;
HWND H = FindWindow("TFormMain",NULL);
if(H)
{
Memo->Lines->Append("- Application window handle = " + IntToStr(H));
if (SendMessage(H,WM_QUERYENDSESSION,wParam,lParam))
Memo->Lines->Append("- Application responded OK to close.");
else
Memo->Lines->Append("- Application responded NOT OK to close.");
Memo->Lines->Append("- wParam = " + IntToStr(wParam));
Memo->Lines->Append("- lParam = " + IntToStr(lParam));
}
else
Memo->Lines->Append("- Application window handle NOT FOUND!");
Memo->Lines->Append("----------------------------------");
}
The send message return is true, and both wParam and lParam are 0. My
application is saving and closing it's files.
OK, so why doesn't windows shutdown?
 

{smallsort}

Re:Re: HELP: My app closes, but cancels Windows shutdown?

"A Nonymous" < XXXX@XXXXX.COM >wrote in message
Quote
My original code which has not changed in a LONG time and used to
work
fine:
Why don't you simply use the form's OnCloseQuery and OnClose events
instead? The VCL already handles the WM_QUERYENDSESSION and
WM_ENDSESSION messages. OnCloseQuery is triggered when
WM_QUERYENDSESSION is received.
Quote
HWND H = FindWindow("TFormMain",NULL);
Have you tried sending the message to the hidden TApplication window
yet? That is the parent window for TForm, after all.
Gambit
 

Re:Re: HELP: My app closes, but cancels Windows shutdown?

"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >wrote in news:45f08683$1
@newsgroups.borland.com:
Quote

"A Nonymous" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>My original code which has not changed in a LONG time and used to
work
>fine:

Why don't you simply use the form's OnCloseQuery and OnClose events
instead? The VCL already handles the WM_QUERYENDSESSION and
WM_ENDSESSION messages. OnCloseQuery is triggered when
WM_QUERYENDSESSION is received.

I just tried that. I commented out the message map line so as not to
interfeer with the normal processing of the end session messages. I
then modified the OnQueryClose to not ask about saving, just save and
exit.
Same problem.
I want the shutdown on Windows shutdown to be non interactive, just save
and close. If the user manually closes the app, then I want to ask if
they want to save modified files.
Quote
>HWND H = FindWindow("TFormMain",NULL);

Have you tried sending the message to the hidden TApplication window
yet? That is the parent window for TForm, after all.


Gambit



Not sure what you are asking about here. Is that the window that
windows is actually sending the WM_QUERYENDSESSION to? How do I get the
handle, TApplication doesn't seem to work. Even if I send to the hidden
form using my "fake" shutdown app and it returns false from the end
session messages, how do I isolate the source.
The goal is to identify what is causing the problem. If it is a
component I have the source for I will try to fix it. If it is one I
don't have the source for then I will contact the vendor for a patch, or
replace the component with something else.
 

Re:Re: HELP: My app closes, but cancels Windows shutdown?

"A Nonymous" < XXXX@XXXXX.COM >wrote in message
Quote
>Why don't you simply use the form's OnCloseQuery and OnClose events
>instead? The VCL already handles the WM_QUERYENDSESSION and
>WM_ENDSESSION messages. OnCloseQuery is triggered when
>WM_QUERYENDSESSION is received.
>

I just tried that. I commented out the message map line so as not to
interfeer with the normal processing of the end session messages. I
then modified the OnQueryClose to not ask about saving, just save and
exit.

Yeah, that's why I handle both the VCL events and the Windows messages, and
then also some of my own messages, because I have control over when the user
is prompted for confirmation. I ask the user for confirmation only if the
user is shutting down the application, but not if Windows is shutting down:
MESSAGE void __fastcall TMainForm::WM_Service_Stop(TMessage &Message)
{
bool CanStop = true;
if ( Message.WParam != NoPrompt )
{
StopQuery( CanStop );
}
if ( !CanStop )
{
return;
}
LogMsg("Application is stopping the service - Received service stop
notification");
Service->Stop();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCloseQuery(TObject */*Sender*/, bool
&CanClose)
{
LogMsg("Application wants to shut down - Received close window request");
if ( Service->IsRunning() )
{
StopQuery( CanClose );
if ( !CanClose )
{
LogMsg("Application shut down cancelled");
}
}
}
//---------------------------------------------------------------------------
void TMainForm::StopQuery( bool &CanStop )
{
LogMsg("Application wants to stop the service - Received service stop
request");
AnsiString StopQueryMsg = "You are about to deactivate the service...";
if ( IDCANCEL == Application->MessageBox( StopQueryMsg.c_str(),
"Confirm",
MB_OKCANCEL |
MB_ICONWARNING ) )
{
LogMsg("Service stop cancelled");
CanStop = false;
}
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormClose(TObject */*Sender*/,
TCloseAction &/*Action*/)
{
LogMsg("Application is shutting down - Received close window
notification");
SendMessage( this->Handle, WM_SERVICE_STOP, NoPrompt, 0 );
}
//---------------------------------------------------------------------------
MESSAGE void __fastcall TMainForm::WMEndSession(TMessage &msg)
{
// if WM_QUERYENDSESSION returned false, it's not okay to shutdown the
program
if ( msg.WParam == false ) return;
// if we get this far, it's okay to shut down the interface
LogMsg("System is shutting down - Received end of session notification");
// if Windows is shutting down, we want to shut down the application
without user intervention;
// to accomplish this, we must stop the interface service first
SendMessage( this->Handle, WM_SERVICE_STOP, NoPrompt, 0 );
// now we know the interface service is not running; we can close the
application and we
// won't be queried about shutting down
Close();
}
//---------------------------------------------------------------------------
// handle WM_QUERYENDSESSION -- this isn't strictly necessary since we
always want to allow
// Windows to shut down, but it's here for completeness and for the sake of
logging
MESSAGE void __fastcall TMainForm::WMQueryEndSession(TMessage &msg)
{
LogMsg("System wants to shut down - Received end of session query
notification");
// when an application receives the WM_QUERYENDSESSION message, it must
tell Windows
// whether or not it is really okay to shut down;
// setting the message result to 'true' means it is okay to shut down
Windows
msg.Result = true;
}
//---------------------------------------------------------------------------
- Dennis
 

Re:Re: HELP: My app closes, but cancels Windows shutdown?

"A Nonymous" < XXXX@XXXXX.COM >wrote in message
Quote
I want the shutdown on Windows shutdown to be non interactive,
just save and close.
That is exactly what the OnClose and OnCloseQuery events provide for
you without using message hooks. It does work. I've used it many
times before.
Quote
If the user manually closes the app, then I want to ask if
they want to save modified files.
That is also easy to do. You can intercept the WM_SYSCOMMAND message.
That is sent when the user closes the window, but not during a
shutdown. You can use it to set a flag that your OnClose/Query
handlers can check.
Quote
Not sure what you are asking about here.
You do know that TForm windows are not standalone windows, right? The
global TApplication object has its own hidden window that silently
controls the TForm windows.
Quote
Is that the window that windows is actually sending the
WM_QUERYENDSESSION to?
It can be.
Quote
How do I get the handle, TApplication doesn't seem to work.
TApplication has a Handle property.
When you do your FindWindow(), look for the 'TApplication" classname
instead of "TFormMain". You will also have to look for the
TApplication.Title (what is displayed on the Taskbar button) as the
caption to look for as well, since every VCL application has a
TApplication class, so you want to make sure you use unique captions
in your projects so you are searching for the right program.
Quote
how do I isolate the source.
I already explained to you earlier. As far as the VCL is concerned,
there is NO difference whatsoever between a real shutdown and a fake
one. If the OS is not responding correctly to the VCL reporting that
the shutdown is ok, then that is a problem in the OS itself, not the
VCL.
Quote
The goal is to identify what is causing the problem. If it is a
component I have the source for I will try to fix it.
You won't be able to do that until you have a reliable test
environment with which to send fake shutdowns with. Onc you have that
working properly, then you can debug the message handling inside the
offending program to see who is handling the messages and how.
Gambit