In search of this same solution, I found what I needed under a different question in stackoverflow: Powershell-log-off-remote-session. The below one line will return a list of logged on users.
query user /server:$SERVER
Answer from Quickmute on Stack OverflowI have a script that relies on retrieving the username of the user logged into the PC. I'm using the following line to get that information:
get-ciminstance win32_computersystem | % username
Problem is, it doesn't seem to return anything if the user is using Remote Desktop to log into the computer. Is there a way for me to retrieve the username of who is connected via RDP?
Need to find the logged on user on windows 10 machine
Powershell script to view logged on user
PowerShell: Find computers that a specific user is logged on with the LastLogonDate
who is logged on remote pc from which computer
Videos
In search of this same solution, I found what I needed under a different question in stackoverflow: Powershell-log-off-remote-session. The below one line will return a list of logged on users.
query user /server:$SERVER
Since we're in the PowerShell area, it's extra useful if we can return a proper PowerShell object ...
I personally like this method of parsing, for the terseness:
((quser) -replace '^>', '') -replace '\s{2,}', ',' | ConvertFrom-Csv
Note: this doesn't account for disconnected ("disc") users, but works well if you just want to get a quick list of users and don't care about the rest of the information. I just wanted a list and didn't care if they were currently disconnected.
If you do care about the rest of the data it's just a little more complex:
(((quser) -replace '^>', '') -replace '\s{2,}', ',').Trim() | ForEach-Object {
if ($_.Split(',').Count -eq 5) {
Write-Output ($_ -replace '(^[^,]+)', '$1,')
} else {
Write-Output $_
}
} | ConvertFrom-Csv
I take it a step farther and give you a very clean object on my blog.
I ended up making this into a module.
Molan, can you post what you are using?
I posted it in the SW Script center
https://community.spiceworks.com/scripts/show/4755-remote-trouble-shooting-and-information-gathering-script
@ericjennings2
I used to have a script that I would run to tell me what user is logged into a computer. We have stickers on each desktop with the computer name but many of these users don’t even know that.
Ideally it would display all computers within an OU with the user that is currently logged on.
The environment variable [System.Environment]::GetEnvironmentVariable('username') will give you the username for the executor of the script, in your case that is System because this is user who ran the code.
If you want to user the environment variable for the user, you must make it so the script been ran from or on behalf of the user, this also means that user must have "permissions" to modify the registry.
If I understand right, you need to know who is the "Logged in user" for the machine where that script runs, unfortunately there is nothing available from PowerShell that do that to my knowledge, instead you could use the build-in tool query for Windows machines, which will provide you with a list with all logged in users to that machine, you would need to further test it to get what you want from it, the output looks like this :
PS C:\Users\t-user> query user
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
>t-user console 1 Active none 8/29/2022 11:58 AM
The trick with query user is that it will provide you with the list of users in case more than one have logged in.
I see what you are trying to do, and here is a "dirty" example of doing it :
$loggedUserList= query user
if($loggedUserList.count -eq 2){
$user = $loggedUserList -split ">" -replace '\s\s+', ';' | convertfrom-csv -Delimiter ';' | select -ExpandProperty username
Write-Host "Logged in user is - $user"
}else{
Write-Host "More than one user have signed"
}
I realize this is a year old but this was answered here: Finding current logged on user(s) while running as SYSTEM (no environment variables)
That page provides two methods of obtaining the current logged on user from a powershell script running as the system user.
Displays User instead of Computer/User or Domain/User.
Get-WmiObject Win32_Process -Filter "Name='explorer.exe'" |
ForEach-Object { $_.GetOwner() } |
Select-Object -Unique -Expand User
Displays Computer/User or Domain/User 2 times
$User = tasklist /v /FI "IMAGENAME eq explorer.exe" /FO list | find "User Name:"
$User = $User.Substring(14)
The issue with Get-WmiObject Win32_LoggedOnUser | Select Antecedent -Unique is that it shows all sessions even those that have been closed since the last time the computer rebooted. The easiest way to poll sessions is unfortunately using the old executable query.exe.
You can convert the output of query.exe to objects using a bit of regex:
$Computer = $env:COMPUTERNAME
$Users = query user /server:$Computer 2>&1
$Users = $Users | ForEach-Object {
(($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1 none $2' -replace "\s{2,}", "," -replace "none", $null))
} | ConvertFrom-Csv
foreach ($User in $Users)
{
[PSCustomObject]@{
ComputerName = $Computer
Username = $User.USERNAME
SessionState = $User.STATE.Replace("Disc", "Disconnected")
SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
}
}
Which will give you output like this:
ComputerName Username SessionState SessionType
------------ -------- ------------ -----------
BSMITH-LT bobsm Active console
Taking it a lot further in to a function:
function Convert-QueryToObjects
{
[CmdletBinding()]
[Alias('QueryToObject')]
[OutputType([PSCustomObject])]
param
(
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 0)]
[Alias('ComputerName', 'Computer')]
[string]
$Name = $env:COMPUTERNAME
)
Process
{
Write-Verbose "Running query.exe against $Name."
$Users = query user /server:$Name 2>&1
if ($Users -like "*No User exists*")
{
# Handle no user's found returned from query.
# Returned: 'No User exists for *'
Write-Error "There were no users found on $Name : $Users"
Write-Verbose "There were no users found on $Name."
}
elseif ($Users -like "*Error*")
{
# Handle errored returned by query.
# Returned: 'Error ...<message>...'
Write-Error "There was an error running query against $Name : $Users"
Write-Verbose "There was an error running query against $Name."
}
elseif ($Users -eq $null -and $ErrorActionPreference -eq 'SilentlyContinue')
{
# Handdle null output called by -ErrorAction.
Write-Verbose "Error action has supressed output from query.exe. Results were null."
}
else
{
Write-Verbose "Users found on $Name. Converting output from text."
# Conversion logic. Handles the fact that the sessionname column may be populated or not.
$Users = $Users | ForEach-Object {
(($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1 none $2' -replace "\s{2,}", "," -replace "none", $null))
} | ConvertFrom-Csv
Write-Verbose "Generating output for $($Users.Count) users connected to $Name."
# Output objects.
foreach ($User in $Users)
{
Write-Verbose $User
if ($VerbosePreference -eq 'Continue')
{
# Add '| Out-Host' if -Verbose is tripped.
[PSCustomObject]@{
ComputerName = $Name
Username = $User.USERNAME
SessionState = $User.STATE.Replace("Disc", "Disconnected")
SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
} | Out-Host
}
else
{
# Standard output.
[PSCustomObject]@{
ComputerName = $Name
Username = $User.USERNAME
SessionState = $User.STATE.Replace("Disc", "Disconnected")
SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
}
}
}
}
}
}
and now you can do things like: Get-ADComputer -Filter {Name -like "SERVER*"} | Convert-QueryToObjects | ? {$_.SessionState -eq 'Active'}
Here's how I do it. It doesn't work for rdp sessions though.
$out = query session | where {$_ -match 'console'}
$array = $out -split('\s+')
$consoleuser = $array[1]
Or:
$consoleuser = query session | select-string console | foreach { -split $_ } |
select -index 1
We have a remote pc which is fairly unstable. (separate issue we’re working on it)
How can I remotely test IF that remote pc is logged IN. (not just ON but actually logged in)
The problem of course is if the pc is not logged in the reports do not run. I can test if it’s up through a variety of mechanisms (ping, test for admin share etc). IS there a way I can programmatically test if the pc is actually logged IN.
Windows 10 in an AD hybrid environment.
You can use Powershell to query WMI to get details about logged on users:
https://4sysops.com/archives/how-to-find-a-logged-in-user-remotely-using-powershell/
Try this
$MachineList = Get-Content -Path c:\ListOfMachines.txt; # One system name per line
foreach ($Machine in $MachineList){
($Machine + ": " + @(Get-WmiObject -ComputerName $Machine -Namespace root\cimv2 -Class Win32_ComputerSystem)[0].UserName);
}
Try this:
Get-Content -Path c:\ListOfMachines.txt | % {
Get-WmiObject -ComputerName $_ -Namespace root\cimv2 -Class Win32_ComputerSystem -erroraction silentlycontinue | % {
"$($_.Name): $($_.username)"
}
}