Solved

make a program respond to system shutdown/reboot

Posted on 2004-08-31
34
4,761 Views
Last Modified: 2007-12-19
hi,

i have an application that needs to do some housekeeping when the system shuts down. i've done this before on Borland c++ builder and in delphi but i'm rather confused as to where to add the message capture and handler on a normal C program (to be compiled with either mingw (gcc) or visual studio)

any ideas how can i capture the windows shutdown, pause it for a bit, do the housekeeping  and then continue withg the shutdown?

thanks, i really appreciate any help
0
Comment
Question by:urif
34 Comments
 
LVL 11

Expert Comment

by:cjjclifford
ID: 11939855
In Unix, the way to do this is to set the program up in the init table (init.d, etc), wrapped by a script that handles "start" and "stop" commands. The start is called when the relevant run level is reached, the stop is called when the OS is shutting down.

In Windows, I'm assuming the same can be achieved by making a service from your program, and have this service setup to be automatic. Sorry I can't help more in how to do this...
0
 

Author Comment

by:urif
ID: 11940238
thanks, i only need it under windows, under unix/linux is easier to do.

anyways, what i meant is how can i trap the WM_ENDSESSION message, then hold the exitwindows() api and perform my thing...


0
 
LVL 86

Expert Comment

by:jkr
ID: 11942569
You need to catch 'WM_QUERYENDSESSION' and then return FALSE indicating that you need time to cleanup. This message is being sent to your main window. If you don't have one, create an invisible window.
0
 

Author Comment

by:urif
ID: 11949874
thanks jkr, i know that.

my question still is "how"

as i said, i know what needs to be done, i did it under delphi and c++builder.
from what i understand i can't do this in a console application (a command line program) right?

anyways, do you have some code?
thanks
0
 
LVL 86

Expert Comment

by:jkr
ID: 11953604
>>from what i understand i can't do this in a console application

Sure you can - but, there might be a better way do do this from a console, which is using 'SetConsoleCtrlHandler()' and supplying your own handler that handles both CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT.

0
 

Author Comment

by:urif
ID: 11961037
ok, i'll take your word for it, any example code?

thanks
0
 
LVL 86

Expert Comment

by:jkr
ID: 11963802
Well, just

BOOL WINAPI MyConsoleControlHandler (   DWORD dwCtrlType )
{
    switch  (   dwCtrlType )
            {
                case CTRL_LOGOFF_EVENT:  
                case CTRL_SHUTDOWN_EVENT:  

                    MyAppCleanupRoutine ();

                    return  (   TRUE);

                    break;
            }

    return  (   FALSE);
}

All you need to do then is calling 'SetConsoleCtrlHandler()' from your app.
0
 

Author Comment

by:urif
ID: 11981520
thanks for the example, but i just doesnt work...
i tried the same code under win2k and winxp and nothing, it won't even compile under borlan C or GCC. only under vc++

anyways, any ideas?

thanks again
0
 

Expert Comment

by:personalshopper
ID: 12018831
I have written a custom built Access routine that when the user Clicks Bye Bye a backup routine to floppy disk or USB Pen Drive is invoked and then then that has finished sucessfully Windows Shutdown or Reboot is activated, (as required). If you let me know what your requirements are I will see if I can be of assistance.
0
 
LVL 2

Expert Comment

by:x_terminat_or_3
ID: 12023923
Create a form (window) in your program.  When windows shuts down, it sends a WMQUERYsomething message to the form.  You can cancel it there by changing the return value.

I'm not a C programmer but this DID work in Visual Basic



With kind regards



x_terminat_or_3
0
 
LVL 23

Expert Comment

by:ahammar
ID: 12023970
It doesn't look like you are wanting to do this with Visual basic but if you want to give it a try, it is very simple.  Create a form and in the query unload event just put this code:

If UnloadMode = 2 then Cancel = true

That's it.  That will prevent windows from shutting down.  Then you can have it do what you want then write another line of code to have it shut down windows which I could put here for you.  But it doesn't look like you are wanting to do this with Visual Basic, but just in case you want to try it...it works.

Cheers!
ahammar
0
 
LVL 2

Expert Comment

by:x_terminat_or_3
ID: 12024003
You can call your C program from within the query unload event.  

Either with the SHELL command, or you can create a dynamic link library in C that does your cleanup and call it from the query unload event.


That way you don't need to resend the shutdown/reboot command



With kind regards



x_terminat_or_3
0
 

Author Comment

by:urif
ID: 12024269
thanks everyone, but no, no visal basic, but C, that's why i posted the question on the C forum.
if i wanted to do a gui program i would use delphi or c++builder, and i know how to catch this message there.
i jsut don't know how to catch them on a command line program.

that's my question, how do you catch the message.

thanks
0
 

Accepted Solution

by:
garyolliffe earned 100 total points
ID: 12024669
Does this help....
http://www.codeproject.com/win32/winconsole.asp

Change the code to specify a hidden window, and add an event handler for WM_QUERYENDSESSION....

Not tried it, but to catch a *window* message you need _window_ and a message pump...this example provides the simplest code to give you both in C.

G
0
 

Expert Comment

by:cabbi
ID: 12024840
VC6, just create a new "Win32 Application" and here the code:

#include "stdafx.h"
#include "Windows.h"

  //---------------------------------------------------
 // windows procedure
//---------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   if (message == WM_QUERYENDSESSION)
   {
      // ... here your stuff ...
   }
   return DefWindowProc(hWnd, message, wParam, lParam);
}

  //---------------------------------------------------
 // main
//---------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
   // Creates an hidden window
   WNDCLASSEX wcex;
   ZeroMemory(&wcex, sizeof(WNDCLASSEX));
      wcex.cbSize = sizeof(WNDCLASSEX);
   const char* WND_CLASS = "MyWndToCatchWndMessages";

      wcex.lpfnWndProc       = (WNDPROC)WndProc;
      wcex.lpszClassName = WND_CLASS;
      RegisterClassEx(&wcex);

   HWND hWnd = CreateWindow(WND_CLASS,
                            "",
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT,
                            0,
                            CW_USEDEFAULT,
                            0,
                            NULL,
                            NULL,
                            hInstance,
                            NULL);
   // Message pump
   MSG msg;
      while (GetMessage(&msg, NULL, 0, 0))
   {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
   }
      return 0;
}

Hope this will solve your problem,
Cabbi
0
 

Author Comment

by:urif
ID: 12025003
ok, so from what i see IT CANNOT BE DONE as a command line,, right?
0
 

Expert Comment

by:garyolliffe
ID: 12025066
The link I posted _is_ console application that can deal with stdio etc. (it spins a separate thread for the message pump).  It has a standard void main and even gives an example of using printf to interact witht he console.

The _hidden_ window "magic" is required because AFAIK there is no way to catch a WM event without a window (hidden or visible).  

What's the problem with creating a hidden window in order to do this?  
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:urif
ID: 12025869
memory. that's the problem.

by creating a console application i have access to all the console API's, so i thought there was a way.
aparently not.

i'll give you the points, even when i still don't hve the anwer.

if i wanted a form, even a hidden onw, i can still use my own code under c++builder.
thanks anyway
0
 

Expert Comment

by:psims
ID: 12026343
Sorry if i have missed the point but if you are using Windows 2000 you can setup a script thats runs on shutdown, be it a .vbs or a batch file.
0
 

Expert Comment

by:ScanIAmDMAX
ID: 12027705
Look up:

SetConsoleCtrlHandler

This allows you to create a handler routine that will override the standard control handler.  

You can decide what to do in based on a number of 'events' that will call back into your program.  For your example, you will want to look for the CTRL_SHUTDOWN_EVENT and CTRL_CLOSE_EVENT events.  

Be warned, if your cleanup routines hang for any reason, you WILL cause your app to hang and possible keep the system from shutting down.  Also, on later version of the os (W2k and XP), if you take too long to shut down, you'll get the 'would you like to kill it anyway' dialog which will allow your users to preempt your cleanup routines.

Scan
0
 
LVL 86

Expert Comment

by:jkr
ID: 12028072
>>SetConsoleCtrlHandler

Why does that sound so familiar to me?
0
 

Expert Comment

by:Christopher222
ID: 12029113
In order to get the messages to your ap the essential parts are
SERVICE_STATUS m_status;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
                                            SERVICE_ACCEPT_SHUTDOWN;
::SetServiceStatus(m_hServiceStatus, &m_status);
0
 

Expert Comment

by:ScanIAmDMAX
ID: 12029640
jkr,  That would be because I failed to read the entire post.  Yours was the first solution to mention this.
0
 

Author Comment

by:urif
ID: 12035272
thanks everyone for the commets placed after the answer was selected.
it makes more sence that i could do it thro the console API's, and not creating a virtual or hidden form.

i'll see if i can work it out,

the reason i don't want to use a script is because the acction should be perfom from within the program when windows shuts down.
0
 

Expert Comment

by:PeterKi
ID: 12041331
If you just want to do the job without any programming have a look at http://www.snapfiles.com/get/lastchance.html
0
 
LVL 1

Expert Comment

by:PRDUBOIS
ID: 12043264
It is possible to write a script and then call the SHUTDOWN.EXE utility that is shipped with NT Resourse kit:

shutdown /l /y

You could then add a shortcut to this script on the desktop.

A second way is a utility called Shutdown Plus 2.04 which you can download at:
HTTP://www.zdnet.com/pcmag/download.utils/
0
 
LVL 1

Expert Comment

by:PRDUBOIS
ID: 12043281
It is possible to write a script and then call the SHUTDOWN.EXE utility that is shipped with NT Resourse kit:

shutdown /l /y

You could then add a shortcut to this script on the desktop.

A second way is a utility called Shutdown Plus 2.04 which you can download at:
HTTP://www.zdnet.com/pcmag/download.utils/
0
 

Author Comment

by:urif
ID: 12044545
thanks PRDUBOIS, but no scripts, no external program, i just need to do some housekeeping when windows shutdowns from WITHIN my own program, meaning: i meed to sump all the memory to files, close connections, etc.

thanks anyway
0
 

Author Comment

by:urif
ID: 12044554
Christopher222 i tried several things but so far it's not reponding, do you have any example code?

thanks so much
0
 

Expert Comment

by:Christopher222
ID: 12051086
I was remembering I couldn't make a service respond to the events and found that I needed to "register" for the events as I showed, however you are trying it with an application not a service.

Here's a sample code to verify that you get the signals.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/registering_a_control_handler_function.asp

Copy and run that program and see if you get the beeps on each signal. ie. Ctrl-C, Break, logoff and shutdown.
0
 

Author Comment

by:urif
ID: 12051672
great! now i can finish my program. thx!

do you know hwo to change the "solution" so i can give you the points?
0
 
LVL 3

Expert Comment

by:aravindtj
ID: 14525535
Hi,
 The last comment added by Christopher is working fine for NT based machines.
 But the logoff/shutdown is not detected by 98 machines.
 How to do it?
Thanks in advance.
Aravind.T
0
 
LVL 1

Expert Comment

by:PRDUBOIS
ID: 14525671
Use Poledit to edit the policy and add a shutdown script
0
 
LVL 3

Expert Comment

by:aravindtj
ID: 14525752
Hi PRDUBOIS,
 Thanks for reply.
 But, my need is detecting the WM_QUERYENDSESSION message for logoff/ shutdown in a console application. The example given on the above link is working nicly on NT machines.
 But it doesn't detect the logoff/shutdown events.
 How to do this?

 Then, how do this using policies? I want to do all this in C++.

Thanks in advance.

with regards,
aravind.t
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now