-1

I have an application where i need to periodically run some code in the background when the user is not logged in and then stop running the code when they log back into their windows session.

To do this i have initiated a simple timer on the SystemEvents.SessionSwitch event like so:

 Private Sub SystemEvent_SessionSwitched(sender As Object, e As Microsoft.Win32.SessionSwitchEventArgs)
    WriteLogEntry("System Event Switch user Fired... initiating timer")
    _switchTimer = New Timers.Timer(8000)

    AddHandler _switchTimer.Elapsed, AddressOf OnSwitchTimedEvent

    _switchTimer.AutoReset = True
    _switchTimer.Enabled = True
End Sub

This is fine and works just how i need it to.

When the Timer elapses I then need to check to see if my user is logged back in, or if not carry out some background work. so i tried something this:

 Private Sub OnSwitchTimedEvent(sender As Object, e As Timers.ElapsedEventArgs)
    If Environment.UserName = Me.User.ID Then 'Me.User.ID stores the windows username of the person logged into my application

        WriteLogEntry("User Logged back in... Resume Normal activity")
        _switchTimer.Stop()
        Exit Sub

    Else
        'Do the background stuff here
    End If

End Sub 

Based on the description of Environment.UserName ("Gets the user name of the person who is currently logged on to the Windows operating system.") I thought this would be perfect. However it seems that what Microsoft say and what they mean are two different things as it always returns the user who initiated the process of my application, which is not what I want.

For example if "User1" logs in and starts my application and then "User2" comes along and switches user to his/her windows account, Environment.UserName still returns "User1". I need to work out how to return the active user (i.e "User2") in this example.

If anyone knows the correct property or even an alternative solution to finding out when the user of my application is active again it would be much appreciated.

edit: the end game is to see when my user has logged back in not to obtain the name... obtaining the name was the only way i could see to do it

mattisrowe
  • 149
  • 2
  • 14
  • Possible duplicate of [Find out the current user's username - when multiple users are logged on](http://stackoverflow.com/questions/1244000/find-out-the-current-users-username-when-multiple-users-are-logged-on) – Ken White Jan 11 '16 at 17:46

1 Answers1

1

Ok, so I think you were really close. I would have thought that the Session Switch event would have fired for all users, but it only seems to fire for the user who started the program. Note: I only tested this as a user process, not as a system service where perhaps it would behave differently. When you run the program below, you only get events for the user who started it. If other users log onto the system, you will not see the events.

using System;
using System.Management;
using Microsoft.Win32;

namespace userloggedin
{
    class Program
    {
        static void Main(string[] args)
        {
            SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);

            // block main thread
            Console.ReadLine();

            //Do this during application close to avoid handle leak
            Microsoft.Win32.SystemEvents.SessionSwitch -= new SessionSwitchEventHandler(SystemEvents_SessionSwitch);

        }

        static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
        {
            switch (e.Reason)
            {
                case SessionSwitchReason.ConsoleConnect:
                case SessionSwitchReason.RemoteConnect:
                case SessionSwitchReason.SessionLogon:
                case SessionSwitchReason.SessionUnlock:
                    Console.WriteLine("User connected, logged on, or unlocked so stop your processing.");

                    ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT UserName FROM Win32_ComputerSystem");

                    foreach (ManagementObject queryObj in searcher.Get())
                    {
                        var loggedOnUserName = queryObj["UserName"].ToString();
                        loggedOnUserName = loggedOnUserName.Substring(loggedOnUserName.LastIndexOf('\\') + 1);

                        Console.WriteLine(string.Format("User who just logged on is {0}.", loggedOnUserName));
                    }

                    break;
                case SessionSwitchReason.ConsoleDisconnect:
                case SessionSwitchReason.RemoteDisconnect:
                case SessionSwitchReason.SessionLock:
                case SessionSwitchReason.SessionLogoff:
                    Console.WriteLine("User logged off, locked, or disconnected so start your processing.");
                    break;
            }
        }
    }
}
  • Hmm i'm not sure either of these are particularly relevant.... the code i am executing in the Else statement is not processor intensive in any way. it's simply checks to see what processes are running on the machine and performs some simple logic based on that outcome. I just need to know when the person who ran my application has logged back in and become active so i can stop performing this check as it is not needed when the process user is active. – mattisrowe Jan 12 '16 at 14:30
  • Ok, check my new answer. – Tom McAnnally Jan 12 '16 at 18:10
  • Ahhh i thought it picked up the event for every user which is why i hadn't tried that... yep works perfectly! thanks. – mattisrowe Jan 13 '16 at 15:27