Advanced Windows PowerShell Scripting Video Training

Advanced Windows PowerShell Scripting Video Training
Advanced Windows PowerShell Scripting Video Training

Friday, April 25, 2014

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.

No comments: