How to make a .NET Windows Service detect Logon, Logoff and Switch User events?

lzm picture lzm · Mar 18, 2011 · Viewed 22.7k times · Source

I need to track the current in user (the one using the console) on Windows XP SP3.

I tried the following:

  • Microsoft.Win32.SystemEvents.SessionSwitch: Works for single logon/logout events, but fails to detect switch user.

    If the following occurs:

    1. userA log in
    2. userA switch user
    3. userB login
    4. userB logout
    5. userA restore session

    Events 3 and 4 are not detected by SystemEvents.SessionSwitch

  • Monitoring the "Security" EventLog: Events are inconsistent and arrive out of order. For instance, if the list above is replayed, I receive an event id 528 (Logon), followed by two 538 (Logoff) for userA after he restores his session. Checking event.TimeGenerated doesn't help. This method also does not work if auditing is disabled on SecPol.msc.

  • P/Invoking WTSRegisterSessionNotification: Works fine. I had to create a hidden form, override its WndProc to handle WM_WTSSESSION_CHANGE messages, and then call WTSQuerySessionInformation to get the username associated with the event. This method looks too complex, is there a simpler way?

Edit:

  • Calling WTSGetActiveConsoleSessionId every n milliseconds works too, but I'm looking for an event based method.

Answer

user203570 picture user203570 · Mar 18, 2011

If you're making a service, your class is derived from ServiceBase. Consider investigating the OnSessionChange method. Override this method to detect different types of session changes. It provides both a reason for the session change, and the new session identifier. Be sure in your constructor to set CanHandleSessionChangeEvent to true, otherwise your override will not be called.