Public/Get-LoggedOnUser.ps1

#requires -Version 3
function Get-LoggedOnUser
{
    [cmdletbinding()]

    Param(
        [Parameter(Mandatory = $False)]
        [string[]]$ComputerName = 'Localhost',
        
        [Parameter(Mandatory = $False)]
        [string]$Username = $null,

        [Parameter(Mandatory = $False)]
        [switch]$RPC,
        
        [Parameter(Mandatory = $False)]
        [pscredential]$Credential = $null
    )

    Begin{
        $Jobs = @()
        
        $Computer = $null
        
        [scriptblock]$Scriptblock = {
            $Computer = $Using:Computer
            
            $VerboseSwitch = $Using:PSBoundParameters.Verbose
            $WarningPreference = $Using:WarningPreference
            
            $LockScreenPresent = Get-Process -Name LogonUI -ErrorAction SilentlyContinue
            
            If($LockScreenPresent){$LockScreenActive = $True}
            Else{$LockScreenActive = $False}

            $ProcessInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo
            $ProcessInfo.FileName = "$env:windir\System32\quser.exe"
            $ProcessInfo.RedirectStandardError = $true
            $ProcessInfo.RedirectStandardOutput = $true
            $ProcessInfo.UseShellExecute = $False
            
            If($null -ne $Computer)
            {
                $ProcessInfo.Arguments = "/Server:$Computer"
            }
            Else
            {
                $Computer = $env:COMPUTERNAME
            }
            
            $Process = New-Object -TypeName System.Diagnostics.Process
            
            If(Test-Path -Path "$env:windir\System32\quser.exe")
            {
                $Process.StartInfo = $ProcessInfo
                $null = $Process.Start()
                $Process.WaitForExit()
                $ProcessOutput = $Process.StandardOutput.ReadToEnd().Trim() -split "`n" |
                Select-Object -Skip 1 |
                ForEach-Object -Process {
                    $CurrentLine = $_.Trim() -Replace '\s+', ' ' -Split '\s'
                    $HashProps = @{
                        Username     = $CurrentLine[0] -replace '>'
                        ComputerName = $Computer.ToUpper()
                        LockScreenActive = $LockScreenActive
                    }

                    If($CurrentLine[2] -eq 'Disc') 
                    {
                        $HashProps.SessionName = $null
                        $HashProps.Id = $CurrentLine[1]
                        $HashProps.State = $CurrentLine[2]
                        $HashProps.IdleTime = $CurrentLine[3]
                        $HashProps.LogonTime = $CurrentLine[4..6] -join ' '
                    } 
                    Else
                    {
                        $HashProps.SessionName = $CurrentLine[1]
                        $HashProps.Id = $CurrentLine[2]
                        $HashProps.State = $CurrentLine[3]
                        $HashProps.IdleTime = $CurrentLine[4]
                        $HashProps.LogonTime = $CurrentLine[5..7] -join ' '
                    }

                    New-Object -TypeName PSCustomObject -Property $HashProps |
                    Where-Object -FilterScript {
                        $_.UserName -match '\w'
                    } |
                    Select-Object -Property UserName, ComputerName, LockScreenActive, SessionName, Id, State, IdleTime, LogonTime
                }
                $ProcessError = $Process.StandardError.ReadToEnd().Trim()

                If($ProcessError -notmatch '\w')
                {
                    $ProcessOutput
                }
                ElseIf($ProcessError -match 'No User exists for *')
                {
                    Write-Verbose -Message "No users logged on to $($Computer.ToUpper())." -Verbose:$VerboseSwitch
                }
                ElseIf($ProcessError -match 1722)
                {
                    Write-Warning -Message "Cannot connect to $($Computer.ToUpper()). The RPC server is unavailable."
                }
                ElseIf($ProcessError -match 5)
                {
                    Write-Warning -Message "Cannot connect to $($Computer.ToUpper()). Access is denied."
                }
                Else
                {
                    $ProcessError
                }
            }
            Else
            {
                Write-Warning -Message "Quser is not available on $($Computer.ToUpper())."
            }
        }
    }

    Process{
        If($RPC)
        {
            $ThrottledArray = Split-Array -InputObject $ComputerName
            
            Foreach($Array in $ThrottledArray)
            {
                $Jobs = @()
            
                Foreach($Computer in $Array)
                {
                    $Jobs += Start-Job -ScriptBlock $Scriptblock -WarningAction $WarningPreference
                }

                If($PSBoundParameters.ContainsKey('Username'))
                {
                    $Jobs |
                    Wait-Job |
                    Receive-Job |
                    Where-Object -Property Username -EQ -Value $Username
                }
                Else
                {
                    $Jobs |
                    Wait-Job |
                    Receive-Job
                }

                $Jobs | Remove-Job -Force
            }
        }
        Else
        {
            $InvokeArgs = @{
                ComputerName = $ComputerName
            }
    
            If($null -ne $Credential)
            {
                $InvokeArgs.Credential = $Credential
            }
        
            $InvokeArgs.ComputerName = Test-PSRemoting @InvokeArgs -WarningAction $WarningPreference
        
            If($null -eq $InvokeArgs.ComputerName)
            {
                Break
            }
        
            $InvokeArgs.ScriptBlock = $Scriptblock
        
            $Results = Invoke-Command @InvokeArgs -HideComputerName

            If($PSBoundParameters.ContainsKey('Username'))
            {
                $Results | Where-Object -Property Username -EQ -Value $Username
            }
            Else
            {
                $Results
            }
        }
    }
}