Private/Get-LoggedInUser.ps1
<#
.SYNOPSIS This function gets the current user sesions on a remote or local computer. .DESCRIPTION This function uses quser.exe to get the current user sessions from a remote or local computer. .PARAMETER ComputerName Use this paramter to specify the computer you want to run the command aganist using its name or IPAddress. .EXAMPLE PS C:\> Get-LoggedInUser ComputerName UserName ID SessionType State ScreenLocked IdleTime ------------ -------- -- ----------- ----- ------------ -------- DESKTOP-D7FU4K5 pwsh.cc 1 DirectLogon Active False 0 This examples gets the logged in users of the local computer. .EXAMPLE Get-LoggedInUser -ComputerName $env:COMPUTERNAME,dc01v ComputerName UserName ID SessionType State ScreenLocked IdleTime ------------ -------- -- ----------- ----- ------------ -------- DESKTOP-D7FU4K5 pwsh.cc 1 DirectLogon Active False 0 dc01v administrator 1 DirectLogon Active False 0 This example gets the currently logged on users for the local computer and a remote computer called dc01v. .INPUTS System.String You can pipe a string that contains the computer name. .OUTPUTS AdminTools.LoggedInuser Outputs a custom powershell object .NOTES Requires Admin .LINK https://github.com/MrPig91/SysAdminTools/wiki/Get%E2%80%90LoggedInUser #> Function Get-LoggedInUser () { [CmdletBinding()] Param ( [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline)] [Alias("CN", "Name", "MachineName")] [string[]]$ComputerName = $ENV:ComputerName ) PROCESS { foreach ($computer in $ComputerName) { try { Write-Information "Testing connection to $computer" -Tags 'Process' if ($True) { $Users = quser.exe /server:$computer 2>$null | Select-Object -Skip 1 if (!$?) { Write-Information "Error with quser.exe" -Tags 'Process' if ($Global:Error[0].Exception.Message -eq "") { throw $Global:Error[1] } elseif ($Global:Error[0].Exception.Message -like "No User exists*") { Write-Warning "No users logged into $computer" } else { throw $Global:Error[0] } } $LoggedOnUsers = foreach ($user in $users) { [PSCustomObject]@{ PSTypeName = "AdminTools.LoggedInUser" ComputerName = $computer UserName = (-join $user[1 .. 20]).Trim() SessionName = (-join $user[23 .. 37]).Trim() SessionId = [int](-join $user[38 .. 44]) State = (-join $user[46 .. 53]).Trim() IdleTime = (-join $user[54 .. 63]).Trim() LogonTime = [datetime](-join $user[65 .. ($user.Length - 1)]) LockScreenPresent = $false LockScreenTimer = (New-TimeSpan) SessionType = "TBD" } } try { Write-Information "Using WinRM and CIM to grab LogonUI process" -Tags 'Process' $LogonUI = Get-CimInstance -ClassName win32_process -Filter "Name = 'LogonUI.exe'" -ComputerName $Computer -Property SessionId, Name, CreationDate -OperationTimeoutSec 1 -ErrorAction Stop } catch { Write-Information "WinRM is not configured for $computer, using Dcom and WMI to grab LogonUI process" -Tags 'Process' $LogonUI = Get-WmiObject -Class win32_process -ComputerName $computer -Filter "Name = 'LogonUI.exe'" -Property SessionId, Name, CreationDate -ErrorAction Stop | Select-Object name, SessionId, @{n = "Time"; e = { [DateTime]::Now - $_.ConvertToDateTime($_.CreationDate) } } } foreach ($user in $LoggedOnUsers) { if ($LogonUI.SessionId -contains $user.SessionId) { $user.LockScreenPresent = $True $user.LockScreenTimer = ($LogonUI | Where-Object SessionId -EQ $user.SessionId).Time } if ($user.State -eq "Disc") { $user.State = "Disconnected" } $user.SessionType = switch -wildcard ($user.SessionName) { "Console" { "DirectLogon"; Break } "" { "Unkown"; Break } "rdp*" { "RDP"; Break } default { "" } } if ($user.IdleTime -ne "None" -and $user.IdleTime -ne ".") { if ($user.IdleTime -Like "*+*") { $user.IdleTime = New-TimeSpan -Days $user.IdleTime.Split('+')[0] -Hours $user.IdleTime.Split('+')[1].split(":")[0] -Minutes $user.IdleTime.Split('+')[1].split(":")[1] } elseif ($user.IdleTime -like "*:*") { $user.idleTime = New-TimeSpan -Hours $user.IdleTime.Split(":")[0] -Minutes $user.IdleTime.Split(":")[1] } else { $user.idleTime = New-TimeSpan -Minutes $user.IdleTime } } else { $user.idleTime = New-TimeSpan } $user | Add-Member -Name LogOffUser -Value { logoff $this.SessionId /server:$($this.ComputerName) } -MemberType ScriptMethod $user | Add-Member -MemberType AliasProperty -Name ScreenLocked -Value LockScreenPresent Write-Information "Outputting user object $($user.UserName)" -Tags 'Process' $user } #foreach } #if ping else { $ErrorRecord = [System.Management.Automation.ErrorRecord]::new( [System.Net.NetworkInformation.PingException]::new("$computer is unreachable"), 'TestConnectionException', [System.Management.Automation.ErrorCategory]::ConnectionError, $computer ) $PSCmdlet.WriteError($ErrorRecord) } } #try catch [System.Management.Automation.RemoteException] { if ($_.Exception.Message -like "*The RPC server is unavailable*") { Write-Warning "quser.exe failed on $comptuer, Ensure 'Netlogon Service (NP-In)' firewall rule is enabled" $PSCmdlet.WriteError($_) } else { $PSCmdlet.WriteError($_) } } catch [System.Runtime.InteropServices.COMException] { Write-Warning "WMI query failed on $computer. Ensure 'Windows Management Instrumentation (WMI-In)' firewall rule is enabled." $PSCmdlet.WriteError($_) } catch { Write-Information "Unexpected error occurred with $computer" $PSCmdlet.WriteError($_) } } #foreach } #process } |