Yesterday on PowerShell.com, I had the opportunity to help an IT Pro pull the last logged on user from every one of their client machines. What we discovered is that there are two places in the registry that hold this information.
For the last local account, we extracted the name from:
HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUsername
For the last domain user:
HKLM:\Software\Microsoft\windows\currentVersion\Authentication\LogonUI\LastLoggedOnUser
Just to add a little, and since it was right there, here is the last SID:
HKLM:\Software\Microsoft\windows\currentVersion\Authentication\LogonUI\LastLoggedOnUserSid
To do this one at a time would have been to time consuming. Also, what about the clients that were not online? How are you going to record them? Sitting in my Windows Server 2012 R2 class right now is an IT Pro with over 70,000 clients. This would have been a nightmare to perform manually. I am estimating that it would have taken about a minute per client to remote in, grab this information, and then move on. That means a total of 48 days of continuous work or 145 standard working days. I went ahead and enclosed this code inside of one of my tool templates to solve some issues and make this a bit of a more robust experience. Check out the help file.
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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
| Function Get-LastLoggedOnUser { [CmdletBinding()] Param(
[parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [String[]] $ComputerName
)
BEGIN { # Place all private functions here.
# Main Object Creation Function New-CustomObject { $Obj = New-Object -TypeName PSObject -Property @{ "ComputerName" = $Null "Online" = $False "TimeStamp" = $Null "DomainUser" = $Null "DomainSID" = $Null "LocalUser" = $Null } $obj.PSObject.TypeNames.Insert(0,'Object') Write-Output $Obj } # END: Function New-CustomObject
} # END: BEGIN BLOCK
PROCESS { # Get a fresh copy of the output object. $CustomeObject = New-CustomObject
# Cycle through each client and process. ForEach ($C in $ComputerName) { Write-Verbose "Connecting to: $C"
# Initialize the output data. $Data = $CustomeObject
# Add the name of the current client being processed to the Object. $Data.ComputerName = $C
# Add the current timestamp. $Data.TimeStamp = Get-Date
Try { # Establish the PowerShell Session $SO = New-PSSessionOption -OpenTimeout 500 -NoMachineProfile $SessionHash = @{ "ComputerName" = $C "SessionOption" = $SO "ErrorAction" = "Stop" }
# Establish the new session. $S = New-PSSession @SessionHash
# Execute on the remote client. $Hash = @{ "Session" = $S } $Data = Invoke-Command -Session $S -ScriptBlock { Param ($Obj, $Fixed)
# Set the ComputerName. $Obj.ComputerName = HostName
# Mark the client as being "Online" $Obj.Online = $True
$Splat = @{ "Path" = "HKLM:\Software\Microsoft\windows\currentVersion\Authentication\LogonUI" "ErrorAction" = "SilentlyContinue" } # Get the last Domain User to log on. $Obj.DomainUser = Get-ItemProperty @Splat -Name LastLoggedOnUser | Select -ExpandProperty LastLoggedOnUser
# Get the last Domain SID to log on. $Obj.DomainSID = Get-ItemProperty @Splat -Name LastLoggedOnUserSid | Select -ExpandProperty LastLoggedOnUserSid
$Splat = @{ "Path" = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" "ErrorAction" = "SilentlyContinue" }
# Get the last local account to log on. $Obj.LocalUser = Get-ItemProperty @Splat -Name DefaultUserName | Select-Object -ExpandProperty DefaultUsername
# End of remote commands. ------------------------------------- # Return the object to the calling client. Write-Output $Obj } -ArgumentList $Data
# Remove the PS Session. $S | Remove-PSSession
Write-Verbose "Finished processing: $C" } # END: TRY BLOCK Catch { Write-Verbose "Error connecting to: $C." $Data.ComputerName = $C } # END: CATCH BLOCK
# Write the data to the pipeline. Write-Output $Data } } # END: PROCESS BLOCK
END {
} # END: END BLOCK
<# .SYNOPSIS Gets the last logged on Domain and local user on a client.
.DESCRIPTION Gets the last logged on domain user and the last local account used to log on to a client.
.PARAMETER ComputerName The name of the client to recover drive information from.
.EXAMPLE Get-LastLoggedOnUser -ComputerName PHX-cl1, PHX-CL2
LocalUser : admin TimeStamp : 4/9/2015 3:40:51 PM DomainUser : MCTExpert\jyoder Online : True ComputerName : PHX-CL1 DomainSID : S-1-5-21-442550829-505139508-2737514282-1605 PSComputerName : lon-cl1 RunspaceId : 0bba2b2c-97df-4e32-94dc-cbc045db7a92
LocalUser : admin TimeStamp : 4/9/2015 3:40:52 PM DomainUser : MCTExpert\administrator Online : True ComputerName : PHX-CL2 DomainSID : S-1-5-21-442550829-505139508-2737514282-500 PSComputerName : LON-CL2 RunspaceId : 9f122008-d0da-4d40-9d4a-a81f2ba4c7b3
Returns information concerning the last logged on users for clients PHX-CL1 and PHX-CL2.
.EXAMPLE "PHX-cl1", "PHX-CL2" | Get-LastLoggedOnUser
Returns information concerning the last logged on users for clients PHX-CL1 and PHX-CL2.
.EXAMPLE "PHX-cl1", "PHX-CL2" | Get-LastLoggedOnUser | Export-CSV -Path D:\PS\Offline.csv
Exports the Results to a CSV File.
Import-CSV -Path D:\PS\Offline.csv | Where-Object Online -eq $False | Get-LastLoggedOnUser | Export-CSV -Path D:\PS\Offline2.csv
Imports the CSV file and filters for all clients that were offline during the previous run of this command. The previous offline clients are processed again and a CSV file is generated so any clients that are still offline can be processed again.
.NOTES Requirements: - PowerShell Remoting is enabled. - You are logged on with credentials that allow you to remote to other clients. =============================================================================== == Cmdlet: Get-LastLoggedOnUser == == Author: Jason A. Yoder == == Company: MCTExpert of Arizona == == Date: April 10, 2015 == == Copyright: All rights reserved. == == Version: 1.0.0.0 == == Legal: The user assumes all responsibility and liability for the usage of == == this PowerShell code. MCTExpert of Arizona, Its officers, shareholders, == == owners, and their relatives are not liable for any damages. As with all == == code, review it and understand it prior to usage. It is recommended that == == this code be fully tested and validated in a test environment prior to == == usage in a production environment. == == == == Does this code make changes: NO == =============================================================================== #> } # End Get-LastLoggedOnUser
|
Comments