Reputation: 1394
I am attempting to use C to capture a logoff event on a Windows Server 2008 64 bit system. Currently I am using the console logoff event code illustrated here: http://www.cplusplus.com/forum/beginner/1501/ (6th comment down by Grey Wolf, his second coding example) will be attached to the end of this post.
There are several issues with this code. It works fine standalone and when the user starts the program. When I begin to add calls to some of our proprietary code it stops catching logoff events. No GUI code, this is all console. Anyone know anything that would stop this from working? It seems rather finicky.
Also if the program is started by another program automatically during logon (started at the user level and same session ID as if you were to double click the .exe and activate it yourself) it also fails to capture the logoff event. Any ideas would be great.
Examples: This works fine standalone and if manually started by the user.
#include <windows.h>
#include <tchar.h>
#include <signal.h>
BOOL WINAPI ConsoleHandler(
DWORD dwCtrlType // control signal type
);
static int startup;
int main(int argc, char *argv[])
{
if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE)
{
// unable to install handler...
// display message to the user
printf("Unable to install handler!\n");
return -1;
}
startup=1;
while(1)
{
}
}
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
char mesg[128];
static FILE * pFile;
char FileName[32] = "ControlHandle.txt";
if(startup) {
/* create the filename */
pFile = fopen(FileName, "at");
printf("creating a file\n");
fprintf(pFile, "This file contains the message when a control character is received.\n\n\n");
fclose(pFile);
startup=0;
}
switch(CEvent)
{
case CTRL_C_EVENT:
pFile = fopen(FileName, "at");
if(pFile > 0){
printf("Got File Handle");
}
fprintf( pFile,"in handler got an CTRL_C_EVENTevent\n" );
fclose(pFile);
break;
case CTRL_BREAK_EVENT:
pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_BREAK_EVENTevent\n" );
fclose(pFile);
break;
case CTRL_CLOSE_EVENT:
pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_CLOSE_EVENTevent\n" );
fclose(pFile);
break;
case CTRL_LOGOFF_EVENT:
pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_LOGOFF_EVENTevent\n" );
fclose(pFile);
break;
case CTRL_SHUTDOWN_EVENT:
pFile = fopen(FileName, "at");
fprintf( pFile,"in handler got an CTRL_SHUTDOWN_EVENTevent\n" );
fclose(pFile);
break;
}
return TRUE;
}
Upvotes: 4
Views: 2064
Reputation: 562
There are two ways
If you are using console application, then you can use
main()
{
...
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlEventHandler, TRUE );
...
}
BOOL CtrlEventHandler(DWORD eventType)
{
if(eventType == CTRL_C_EVENT)
{
printf(""Sample text");
return FALSE
}
else if(eventType == CTRL_LOGOFF_EVENT)
{
printf(""Sample text");
return FALSE
}
}
If you are using Windows UI based application,then you can use virtual function WindowProc and use below code
LRESULT CMainDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == WM_ENDSESSION)
{
if(lParam == ENDSESSION_LOGOFF)
{
/*Handle event*/
}
}
return CDialogEx::WindowProc(message, wParam, lParam);
}
For 1st option, you can refer MSDN LINK Registering a Control Handler Function
Upvotes: 2
Reputation: 25288
You can listen to the WM_QUERYENDSESSION or WM_ENDSESSION messages. This works both in GUI and console apps as long as you have a window (doesn't have to be visible) with a message loop.
EDIT: check this thread, especially the code in the last post.
Extra info:
Upvotes: 1
Reputation: 2842
You probably have to implement the code as a Service, since you want the program to run until the very end and start at the very beginning of log on. That way, the program is running in system mode, and doesn't shut down yoru program when it starts to force quite user level (including admin programs).
Upvotes: 0