Recently I helped an IT Pro on PowerShell.com who needed to find out how to discover who was logged into his clients. Here is the advanced version of the code that allows you to send information via the PowerShell Pipeline.
This code was tested in a PowerShell V3 environment. If you need to alter the code for a PowerShell V2 without WinRM turned on, make the following changes:
Line 50: "ClassName" to "Class"
Line 58: "Get-CIMInstance" to Get-WMIObject"
Lines 4 – 15 define our two parameters of $ComputerName and $Name. A parameter set is used so that these two parameters cannot be used at the same time. $ComputerName is designed to be used from a object that contains a property called “ComputerName”. $Name is designed to accept a string of names.
Line 17 – 34 is our begin block. It contains a function that creates a new, empty object. Line 28 assigned a typename to our object. This method of creating a object is done to make updating the object with new properties easier and also to reduce clutter when populating the objects properties.
Lines 35 – 82 executes for each object passed to this cmdlet.
Lines 41 and 42 ensure that no matter which parameter is used, the data is processed.
Lines 45 – 81 loops through each client.
Lines 47 and 64 are the Try..Catch blocks that will handle any clients that are not online. A possible error may occur on line 58 where the script reaches out to the remote client. If the client is online, the currently logged on user name is extracted. If it is not online, the CATCH block executes and populates the object with user “n\a” and Online = $False.
Line 76 starts the FINALLY block which will execute no matter if a connection error occurred or not. It wends the object to the PowerShell pipeline.
This code was tested in a PowerShell V3 environment. If you need to alter the code for a PowerShell V2 without WinRM turned on, make the following changes:
Line 50: "ClassName" to "Class"
Line 58: "Get-CIMInstance" to Get-WMIObject"
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
Function Get-LoggedOnUsers
{
[cmdletBinding()]
Param (
[parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName="Object")]
[String[]]
$ComputerName,
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ParameterSetName="Name")]
[String[]]
$Name
)
Begin
{
Function CustomObj
{
# Create the empty object.
$Obj = New-Object -TypeName PSObject -Property @{
'User' = $Null
'Computer' = $Null
'Online' = $Null}
# Provide the object with a custom type name.
$Obj.psobject.TypeNames.Insert(0, "LoggedOnUser")
# Send the object to the calling statement.
Write-Output $Obj
}
}
# This is an advance function.
Process
{
# If the "Name" parameter is used, copy
# its contents to the "ComputerName"
# Parameter.
If ($Name -ne $Null)
{$ComputerName = $Name}
# Cycle through each item in "ComputerName".
ForEach ($Computer in $ComputerName)
{
Try
{
# Hash value used with Get-CIMInstance.
$CIMHash = @{'ClassName' = "Win32_ComputerSystem";
'ComputerName' = $Computer;
'EA' = "Stop"}
# Create the object to output.
$Obj = CustomObj
# Plug in the data ito the blank object.
$Obj.User = (Get-CimInstance @CIMHash |
Select-Object -ExpandProperty UserName)
$Obj.Computer = $Computer
$Obj.Online = $True
}
Catch
{
# Create the object to output.
# This is the output if no user
# is currently logged into the
# target client.
$Obj = CustomObj
$Obj.User = "n\a"
$Obj.Computer = $Computer
$Obj.Online = $False
}
Finally
{
# Send the object to the pipeline.
Write-Output $Obj
}
}
} # End: Process
<#
.SYNOPSIS
Returns a list of the users logged into clients targeted by
this cmdlet.
.DESCRIPTION
Returns a list of the users logged into clients targeted by
this cmdlet. If the user name is listed as " ", then there
is not a user currently logged on.
===============================================================================
== Cmdlet: Get-LoggedOnUsers ==
== Module: PSV3 ==
==---------------------------------------------------------------------------==
== Author: Jason A. Yoder ==
== Company: MCTExpert, Inc. ==
== Blog: MCTExpert.Blogspot.com ==
== Twitter: @JasonYoder_MCT ==
==---------------------------------------------------------------------------==
== License Information: ==
== Copyright 2013 - MCTExpert, Inc. ==
== This code is licensed for personal use only. This code may not be ==
== re published or distributed in whole or in part without the express ==
== written consent of MCTExpert, Inc. All rights reserved. ==
==---------------------------------------------------------------------------==
== Disclaimer: The user takes full responsibility for the execution of any ==
== PowerShell code. This code is provided without warranty or support. ==
== As with all PowerShell code, review it and test it in a test environment ==
== prior to using it in a production environment. The user takes complete ==
== responsibility for the results of executing this code. ==
===============================================================================
.PARAMETER ComputerName
The names of the computers to return the currently logged
on user. Use this when passing objects via with a
ComputerName property
.PARAMETER Name
The names of the computers to return the currently logged
on user.
.EXAMPLE
"CL-154", "CL-155", "CL-156" | Get-LoggedOnUsers
User Computer
---- --------
INDNet\Administrator CL-154
INDNet\Administrator CL-155
N\a CL-156
.EXAMPLE
Get-ADComputer -filter * |
Select -Property @{N="ComputerName";E={$PSItem.Name}} |
Get-LoggedOnUsers
Extracts all the clients from Active Directory and returns
the logged on user.
.EXAMPLE
Get-LoggedOnUsers -Name "CL-154", "CL-155", "CL-156"
User Computer
---- --------
INDNet\Administrator CL-154
INDNet\Administrator CL-155
N\a CL-156
#>
} # End: Function Get-LoggedOnUsers
|
Lines 4 – 15 define our two parameters of $ComputerName and $Name. A parameter set is used so that these two parameters cannot be used at the same time. $ComputerName is designed to be used from a object that contains a property called “ComputerName”. $Name is designed to accept a string of names.
Line 17 – 34 is our begin block. It contains a function that creates a new, empty object. Line 28 assigned a typename to our object. This method of creating a object is done to make updating the object with new properties easier and also to reduce clutter when populating the objects properties.
Lines 35 – 82 executes for each object passed to this cmdlet.
Lines 41 and 42 ensure that no matter which parameter is used, the data is processed.
Lines 45 – 81 loops through each client.
Lines 47 and 64 are the Try..Catch blocks that will handle any clients that are not online. A possible error may occur on line 58 where the script reaches out to the remote client. If the client is online, the currently logged on user name is extracted. If it is not online, the CATCH block executes and populates the object with user “n\a” and Online = $False.
Line 76 starts the FINALLY block which will execute no matter if a connection error occurred or not. It wends the object to the PowerShell pipeline.
Comments
1) Enable PowerShell remoting: http://mctexpert.blogspot.com/2011/03/enable-powershell-v2-remote-management.html
2) Change line 50 from 'ClassName' to 'Class"
Change line 58 from Get-CIMInstance to Get-WMIObject.
hope this helps.
You can also place it into a personal module. http://mctexpert.blogspot.com/2011/04/creating-powershell-module.html
In the end, you need to type the cmdlet name to get it to work.