Cel
Cel

Reputation: 6659

Detect users logging off in Windows service

I'm interested in listening to logging off events from a Windows service running in Session 0


How to find out which user is logging off - getting Session ID from SessionEndingEventArgs ?

protected override void OnStart(string[] args)
    {
        SystemEvents.SessionEnding += SystemEvents_SessionEnding;
    }

private void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
    {
        // SessionEndingEventArgs does not contain SID
        // or other user identifying info?
    }

[ And I havent tested whether a Windows Service can actually capture the SessionEnding event ]


Or can SessionChangeDescription be used to identify users that are about to log off ?

public ServiceApp()
    {
        CanHandleSessionChangeEvent = true;
    }

protected override void OnSessionChange(SessionChangeDescription changeDescription)
    {
        // Although changeDescription has SessionId property
        // I'm not sure it has the equivalent of session ending event?
        base.OnSessionChange(changeDescription);
    }

Other event sources ?

Upvotes: 2

Views: 2892

Answers (1)

Sheng Jiang 蒋晟
Sheng Jiang 蒋晟

Reputation: 15271

WM_QUERYENDSESSION is sent to all top level windows on the desktop in the closing session. However since your service usually runs in a different session, you normally won't get the notification. Before Vista you could enable interaction with desktop to share the desktop with the user on session 0, but you won't get the message sent to you if the logging off happens in another session. After XP, you won't get messages from user sessions due to session 0 isolation.

To notify your service of this message, you need to run an agent process in each session (that is, register to auto start when the user log in via start menu shortcut or registry) and listen to WM_QUERYENDSESSION (in .Net terms, run a message pump like Application.Run in Windows Forms and subscribe to SystemEvents.SessionEnding), then gather session information and send the notification to your service through inter-process communication methods like named pipe (if you use WCF, use NetNamedPipeBinding). If you want to get the current session, use WTSQuerySessionInformation (or in .Net terms, Process.GetCurrentProcess().SessionId)

The OnSessionChange method is called after the user has logged off. Same for SENS's log off event, so those two are too late for you.

Upvotes: 4

Related Questions