Question

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

  • whilst also knowing which user it is that is logging off (their Session ID)
  • Note I'm talking about the cancellable logging off event here, not the logged off event

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 ?

  • Or does Cassia provide such events, including user account information?
  • Or can i pull it from WMI somewhere?
  • Or use some Win32 API directly?
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top