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

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.

How to run GPResult on a remote client with PowerShell

In the past, to run the GPResult command, you would need to either physically visit this client, have the user do it, or use and RDP connection.  In all cases, this will disrupt the user.  First, you need PowerShell remoting enabled on the target machine.  You can do this via Group Policy . Open PowerShell and type this command. Invoke-Command –ScriptBlock {GPResult /r} –ComputerName <ComputerName> Replace <ComputerName> with the name of the target.  Remember, the target needs to be online and accessible to you.

Error icon when creating a GPO Preference drive map

You may not have an error at all.  Take a look at the drive mapping below. The red triangle is what threw us off.  It is not an error.  It is simply a color representation of the Replace option of the Action field in the properties of the drive mappings. Create action This give you a green triangle. The Create action creates a new mapped drive for users. Replace Action The Replace action gives you a red triangle.  This action will delete and recreate mapped drives for users. The net result of the Replace action is to overwrite all existing settings associated with the mapped drive. If the drive mapping does not exist, then the Replace action creates a new drive mapping. Update Action The Update action will have a yellow triangle. Update will modify settings of an existing mapped drive for users. This action differs from Replace in that it only updates settings defined within the preference item. All other settings remain as configured on the mapped drive. If the