Skip to main content

How to get the Currently Logged on User with PowerShell

In the past, I have used the USERNAME property from Win32_ComputerSystem to recover the currently logged on user on a remote client.  I’ve notice that with Windows 8, this may no longer be possible where executing it against a remote system or in a virtual environment.  I do not know why, but I do know that some of my code is non-functional because of this.

While researching this problem, I came across the command quserAccording to Microsoft, quser “Displays information about user sessions on a Remote Desktop Session Host (RD Session Host) server.”  This command will return a few strings of text, or an error if no one is logged in.  One of the commands’ properties, SessionName, will return console if the user is logged in locally. 

Below is my code to allow for you to utilize quser and retrieve the information as a PowerShell object.  This code requires that PowerShell’s remoting capability be turned on for any client that you execute it against.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

<#

.SYNOPSIS

Returns the currently logged on user on a client.

.DESCRIPTION

Utilizes the command "quser" to return the currently logged on user from a

remote Client.  This cmdlet will convert the returned strings into PowerShell

objects.  PowerShell remoting must be turned on in your environment for this

command to work.

.PARAMETER ComputerName

The name of the client to connect to.

.EXAMPLE

Get-LoggedOnUser -ComputerName "Tech-cl1"

 

ID          :

SessionName : No Logged On User

Online      : True

LogOnTime   :

IdleTime    :

UserName    : No Logged On User

State       :

 

This example shows that there is currently no user logged on, but the client is

online.

 

.EXAMPLE

Get-LoggedOnUser -ComputerName "Tech-cl1"

 

ID          : 2

SessionName : console

Online      : True

LogOnTime   : 4/25/2014 8:56:00 AM

IdleTime    : none

UserName    : chuck

State       : Active

 

This example demonstrates that the client is logged in to.

 

.EXAMPLE

"Tech-cl1", "tech-ex1", "bad" | Get-LoggedOnUser

 

Recovers the logged in user information from multiple clients.

 

#>

Function Get-LoggedOnUser

{

    [CmdletBinding()]

    Param (

        [parameter(mandatory=$true,

        ValueFromPipeline=$true)]

        [String[]]$ComputerName

    )

    BEGIN

    {

        # Function New-UserSession-Object -----------------------------------------

        # Creates an object to hold the corresponding data form the

        # QUSER command.

        Function New-UserSession-Object

        {

       

            $Obj = New-Object -TypeName PSObject -Property @{

                'UserName' = "No Logged On User"

                'SessionName' = "No Logged On User"

                'ID' = $null

                'State' = $null

                'IdleTime' = $null

                'LogOnTime' = $null

                'Online' = $True

                'ComputerName' = $null

                }

            $Obj.psobject.typenames.insert(0,'HDObject.LoggedOnUsers')

            Write-Output $Obj

        } # END: Function New-UserSession-Object ----------------------------------

    } # END: BEGIN Block   

 

    PROCESS

    {

        ForEach ($C in $ComputerName)

        {

            $Obj =  New-UserSession-Object

            # Clear the $DATA variable by setting it to $null.

            $Data = $null

            Try

            {

      

 

                # Execute "quser" on the remote client.

                $Data  = Invoke-Command -ComputerName $C -ScriptBlock {

                    $Data = Quser

                    Write-Output $Data

                } -ErrorAction Stop

 

           }

           Catch

           {

                # If "quser" returns an error, then there is no loged on user.

                # Send the default object values. 

                #$Obj =  New-UserSession-Object

                $Obj.ComputerName = $C

 

                Try

                {

                    $TestSession = New-PSSession -ComputerName $C -ErrorAction Stop

                    $TestSession | Remove-PSSession

                }

                Catch

                {

                   $Obj.Online = $False

                }

           }

 

 

           If ($Data -eq $null)

           {

                Write-output $Obj

           }

           ElseIf (($Data -ne $null) -and ($Data.Count -gt 0))

           {

 

            

                For ($X=1;$X -le $Data.Count-1; $X++)

                {

                    $Obj =  New-UserSession-Object

                    $Obj.UserName = $Data[$X].Remove(16).Trim()

                    $Obj.SessionName = $Data[$X].Remove(0,16).Remove(19).Trim()

                    $Obj.ID = $Data[$X].Remove(0,41).Remove(3).Trim()

                    $Obj.State = $Data[$X].Remove(0,44).Remove(8).Trim()

                    $Obj.IdleTime = $Data[$X].Remove(0,54).Remove(11).Trim()

                    $Obj.LogOnTime = Get-Date "$($Data[$X].Remove(0,65).Trim())"

                    $Obj.ComputerName = $C

                    Write-Output $obj

                }

 

           }

          

        } # END: ForEach ($C in $ComputerName)

    } # END: PROCESS Block   

}

Lines 1 – 43 is the help file.

Lines 52 – 73 is the BEGIN Block.  It contains a function that creates a copy of the object that will be sent to the PowerShell pipeline. This section runs only once when the command begins to put the function New-UserSession-Object into the current scope of memory.

Lines 75 – 131 is the PROCESS block.  This will execute once for each item passed to this command from the pipeline.

Line 79 calls the function New-UserSession-Object and places it in the $Obj variable.

Line 81 initializes the variable $Data.  This ensures that even if there is an error from line 87, that previous data is not accidentally transposed on the next set of data.

Lines 87 – 90 runs the quser command on the remote clients.  Remember, PowerShell remoting must be enabled on the target client.

Lines 100 – 109 in the CATCH block performs an additional test to see the client is even online by attempting to create a PowerShell Session.  If it is able to, the session is quickly removed.  If not, an additional CATCH block will change the Online property to $FALSE.

In lines 112 – 115, writes the object to the pipeline if no logged on user was returned.

Lines 116 – 133 provides $Obj with its property values.  Take a look at line 123.  I’m utilizing the Get-Date command with the string value returned from quser to create an actual DateTime object that PowerShell understands.

Comments

Popular posts from this blog

Adding a Comment to a GPO with PowerShell

As I'm writing this article, I'm also writing a customization for a PowerShell course I'm teaching next week in Phoenix.  This customization deals with Group Policy and PowerShell.  For those of you who attend my classes may already know this, but I sit their and try to ask the questions to myself that others may ask as I present the material.  I finished up my customization a few hours ago and then I realized that I did not add in how to put a comment on a GPO.  This is a feature that many Group Policy Administrators may not be aware of. This past summer I attended a presentation at TechEd on Group Policy.  One organization in the crowd had over 5,000 Group Policies.  In an environment like that, the comment section can be priceless.  I always like to write in the comment section why I created the policy so I know its purpose next week after I've completed 50 other tasks and can't remember what I did 5 minutes ago. In the Group Policy module for PowerShell V3, th

Return duplicate values from a collection with PowerShell

If you have a collection of objects and you want to remove any duplicate items, it is fairly simple. # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   # Remove the duplicate values. $Set1 | Select-Object -Unique 1 2 3 4 5 6 7 What if you want only the duplicate values and nothing else? # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   #Create a second collection with duplicate values removed. $Set2 = $Set1 | Select-Object -Unique   # Return only the duplicate values. ( Compare-Object -ReferenceObject $Set2 -DifferenceObject $Set1 ) . InputObject | Select-Object – Unique 1 2 This works with objects as well as numbers.  The first command creates a collection with 2 duplicates of both 1 and 2.   The second command creates another collection with the duplicates filtered out.  The Compare-Object cmdlet will first find items that are diffe

How to list all the AD LDS instances on a server

AD LDS allows you to provide directory services to applications that are free of the confines of Active Directory.  To list all the AD LDS instances on a server, follow this procedure: Log into the server in question Open a command prompt. Type dsdbutil and press Enter Type List Instances and press Enter . You will receive a list of the instance name, both the LDAP and SSL port numbers, the location of the database, and its status.