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 quser. According 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