Dark_King
asked on
Check if user logout or shutdown
I am making a console program that writes some stuff to files when it starts up.
I want it do keep running and check if user logout or shutdown computer and
then write to file before it closes, how do I make that possibly.
I want it do keep running and check if user logout or shutdown computer and
then write to file before it closes, how do I make that possibly.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
why not use a windows application and not console? you don't need a form, just make it without forms. it will then receive the windows messages and you can process them.
An alternative (not very recommended) is to install a system-wide hook for ExitWindows()
You should go with window messages though
You should go with window messages though
Hello Sir,
Check the following code if it is of any use. This is also not a console application.
{Detecting Windows Shutdown
To detect Windows Shutdown, you must trap WM_EndSession message. These steps should be taken: Declare a message handling procedure in your Form's Private section: }
Procedure WMEndSession(var Msg : TWMEndSession); message WM_ENDSESSION;
//Add the procedure to the implementation section of your Unit:
procedure TForm1.WMEndSession(var Msg : TWMEndSession);
begin
if Msg.EndSession = TRUE then
ShowMessage('Windows is shutting down ' + #13 + 'at ' +
FormatDateTime('c', Now));
inherited;
end;
{Detecting Windows shutdown
When Windows is shutting down, it sends a WM_QueryEndSession to all open applications. To detect (and prevent shutdown), you must define a message handler to this message. Put this definition on the private section of the main form:}
procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message
WM_QueryEndSession;
// And put this method in the implementation section of the unit:
procedure TForm1.WMQueryEndSession(v ar Msg : TWMQueryEndSession);
begin
if MessageDlg('Close Windows ?', mtConfirmation, [mbYes,mbNo], 0) = mrNo then
Msg.Result := 0
else
Msg.Result := 1;
end;
with regards,
padmaja.
Check the following code if it is of any use. This is also not a console application.
{Detecting Windows Shutdown
To detect Windows Shutdown, you must trap WM_EndSession message. These steps should be taken: Declare a message handling procedure in your Form's Private section: }
Procedure WMEndSession(var Msg : TWMEndSession); message WM_ENDSESSION;
//Add the procedure to the implementation section of your Unit:
procedure TForm1.WMEndSession(var Msg : TWMEndSession);
begin
if Msg.EndSession = TRUE then
ShowMessage('Windows is shutting down ' + #13 + 'at ' +
FormatDateTime('c', Now));
inherited;
end;
{Detecting Windows shutdown
When Windows is shutting down, it sends a WM_QueryEndSession to all open applications. To detect (and prevent shutdown), you must define a message handler to this message. Put this definition on the private section of the main form:}
procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message
WM_QueryEndSession;
// And put this method in the implementation section of the unit:
procedure TForm1.WMQueryEndSession(v
begin
if MessageDlg('Close Windows ?', mtConfirmation, [mbYes,mbNo], 0) = mrNo then
Msg.Result := 0
else
Msg.Result := 1;
end;
with regards,
padmaja.
You have to make your application a Service, then you can set a call back for logoff events.
this should work ok,
program Cleaner;
uses
Windows, WinSvc;
var
Stop:Boolean;
function CtrlHandler(CtrlType:DWORD ):BOOL; stdcall;
begin
Result:= False;
case CtrlType of
CTRL_LOGOFF_EVENT:
begin
Result:= True;
end;
end;
end;
procedure InitMain;
begin
SetConsoleCtrlHandler(@Ctr lHandler, True);
while not Stop do
Sleep(1);
end;
var
DispatchTable:ARRAY[0..1] OF TServiceTableEntry;
sshStatusHandle:Service_St atus_Handl e;
ssStatus:Service_Status;
const
Svc_Name = 'Svc';
procedure CreateSampleService;
var
schSCManager, schService:DWORD;
begin
schSCManager:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
schService:= CreateService(schSCManager , Svc_Name, 'Svc',
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
PChar(ParamStr(0)), nil, nil, nil, nil, nil);
CloseServiceHandle(schServ ice);
end;
procedure DeleteSampleService;
var
schSCManager, schService:DWORD;
begin
schSCManager:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
schService:= OpenService(schSCManager, Svc_Name, SERVICE_ALL_ACCESS);
DeleteService(schService);
CloseServiceHandle(schServ ice);
end;
procedure ServiceHandler(dwControl:I nteger); stdcall;
begin
case dwControl of
SERVICE_CONTROL_STOP:
begin
Stop:= True;
ssStatus.dwCurrentState:= Service_Stop_Pending;
SetServiceStatus(sshStatus Handle, ssStatus);
end;
SERVICE_CONTROL_PAUSE:
begin
ssStatus.dwCurrentState:= Service_Paused;
SetServiceStatus(sshStatus Handle, ssStatus);
end;
SERVICE_CONTROL_CONTINUE:
begin
ssStatus.dwCurrentState:= Service_Running;
SetServiceStatus(sshStatus Handle, ssStatus);
end;
SERVICE_CONTROL_INTERROGAT E:
SetServiceStatus(sshStatus Handle, ssStatus);
SERVICE_CONTROL_SHUTDOWN:
Stop:= True;
end;
end;
procedure ServiceProc(dwArgc:Integer ; var lpszArgv:PChar); stdcall;
begin
sshStatusHandle:= RegisterServiceCtrlHandler ((Svc_Name ), @ServiceHandler);
if sshStatusHandle <> 0 then begin
ZeroMemory(@ssStatus, SizeOf(ssStatus));
ssStatus.dwServiceType:= SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwCurrentState:= SERVICE_START_PENDING;
ssStatus.dwControlsAccepte d:= SERVICE_ACCEPT_STOP or SERVICE_ACCEPT_PAUSE_CONTI NUE;
ssStatus.dwWaitHint:= 1000;
SetServiceStatus(sshStatus Handle, ssStatus);
ssStatus.dwCurrentState:= SERVICE_RUNNING;
SetServiceStatus(sshStatus Handle, ssStatus);
InitMain;
ssStatus.dwCurrentState:= SERVICE_STOPPED;
SetServiceStatus(sshStatus Handle, ssStatus);
end;
end;
begin
if ParamCount <> 0 then begin
if ParamStr(1) = '/i' then
CreateSampleService
else if ParamStr(1) = '/u' then
DeleteSampleService;
end else begin
DispatchTable[0].lpService Name:= Svc_Name;
DispatchTable[0].lpService Proc:= @ServiceProc;
DispatchTable[1].lpService Name:= nil;
DispatchTable[1].lpService Proc:= nil;
StartServiceCtrlDispatcher (DispatchT able[0]);
end;
end.
this should work ok,
program Cleaner;
uses
Windows, WinSvc;
var
Stop:Boolean;
function CtrlHandler(CtrlType:DWORD
begin
Result:= False;
case CtrlType of
CTRL_LOGOFF_EVENT:
begin
Result:= True;
end;
end;
end;
procedure InitMain;
begin
SetConsoleCtrlHandler(@Ctr
while not Stop do
Sleep(1);
end;
var
DispatchTable:ARRAY[0..1] OF TServiceTableEntry;
sshStatusHandle:Service_St
ssStatus:Service_Status;
const
Svc_Name = 'Svc';
procedure CreateSampleService;
var
schSCManager, schService:DWORD;
begin
schSCManager:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
schService:= CreateService(schSCManager
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
PChar(ParamStr(0)), nil, nil, nil, nil, nil);
CloseServiceHandle(schServ
end;
procedure DeleteSampleService;
var
schSCManager, schService:DWORD;
begin
schSCManager:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
schService:= OpenService(schSCManager, Svc_Name, SERVICE_ALL_ACCESS);
DeleteService(schService);
CloseServiceHandle(schServ
end;
procedure ServiceHandler(dwControl:I
begin
case dwControl of
SERVICE_CONTROL_STOP:
begin
Stop:= True;
ssStatus.dwCurrentState:= Service_Stop_Pending;
SetServiceStatus(sshStatus
end;
SERVICE_CONTROL_PAUSE:
begin
ssStatus.dwCurrentState:= Service_Paused;
SetServiceStatus(sshStatus
end;
SERVICE_CONTROL_CONTINUE:
begin
ssStatus.dwCurrentState:= Service_Running;
SetServiceStatus(sshStatus
end;
SERVICE_CONTROL_INTERROGAT
SetServiceStatus(sshStatus
SERVICE_CONTROL_SHUTDOWN:
Stop:= True;
end;
end;
procedure ServiceProc(dwArgc:Integer
begin
sshStatusHandle:= RegisterServiceCtrlHandler
if sshStatusHandle <> 0 then begin
ZeroMemory(@ssStatus, SizeOf(ssStatus));
ssStatus.dwServiceType:= SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwCurrentState:= SERVICE_START_PENDING;
ssStatus.dwControlsAccepte
ssStatus.dwWaitHint:= 1000;
SetServiceStatus(sshStatus
ssStatus.dwCurrentState:= SERVICE_RUNNING;
SetServiceStatus(sshStatus
InitMain;
ssStatus.dwCurrentState:= SERVICE_STOPPED;
SetServiceStatus(sshStatus
end;
end;
begin
if ParamCount <> 0 then begin
if ParamStr(1) = '/i' then
CreateSampleService
else if ParamStr(1) = '/u' then
DeleteSampleService;
end else begin
DispatchTable[0].lpService
DispatchTable[0].lpService
DispatchTable[1].lpService
DispatchTable[1].lpService
StartServiceCtrlDispatcher
end;
end.
ASKER
heretoread
where do I call my procedure if user logoff, and is logoff trigger when user shutdown to?
where do I call my procedure if user logoff, and is logoff trigger when user shutdown to?
In this function here,
function CtrlHandler(CtrlType:DWORD ):BOOL; stdcall;
begin
Result:= False;
case CtrlType of
CTRL_LOGOFF_EVENT:
begin
//USER LOG OFF, SAVE FILE
Result:= True;
end;
end;
end;
And it works for shutdowns too as the user is logged off before shutdown.
As it's a service you need to install it like
MyService.exe /i
That will add it to the services and it will start every time with the computer, to uninstall do
MyService.exe /u
function CtrlHandler(CtrlType:DWORD
begin
Result:= False;
case CtrlType of
CTRL_LOGOFF_EVENT:
begin
//USER LOG OFF, SAVE FILE
Result:= True;
end;
end;
end;
And it works for shutdowns too as the user is logged off before shutdown.
As it's a service you need to install it like
MyService.exe /i
That will add it to the services and it will start every time with the computer, to uninstall do
MyService.exe /u
ASKER
Is there a way to run this service as user, It has no network resources and can’t log to network file.
ASKER
And I need to manual start this service
ASKER
I mean the service is installed but it is not running, If I start it self it work almost
ASKER
No answer, I now try the form app
ASKER