PowerShell function Get-QUser will parse results of “query user” into an array

This PowerShell function will help Windows administrators use the output of “query user” or “quser” as a PowerShell array.

query user: raw output

“query user” or “quser” output in Windows looks like this:

1
2
3
 USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
 username1                                 1  Disc        19:12  9/22/2023 8:38 AM
 username2             console             2  Active      none   9/27/2023 3:51 PM

This format is not very helpful for PowerShell. PowerShell admins would prefer this data to be an array.

Get-QUser: a PowserShell function

Using Trim() and Replace() I was able to easily convert the raw output to a comma-delimited format. But there is one pesky problem: Sometimes the value for SESSIONNAME is empty.

When SESSIONNAME is empty for a row, all of the data shifts one column to the left. My Get-QUser fuction attempts to find those rows and add in an empty space.

I also thought it would be helpful to add two columns with calculated values. I added IDLE_MINTUES and IDLE_HOURS.

Get-QUser: demo

Here’s the result.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Get-QUser -Computer COMPUTERNAME
 
USERNAME     : username1
SESSIONNAME  : 
ID           : 1
STATE        : Disc
IDLE_TIME    : 19:08
LOGON_TIME   : 9/22/2023 8:38 AM
IDLE_MINUTES : 1148
IDLE_HOURS   : 19.13
 
USERNAME     : username2
SESSIONNAME  : console
ID           : 2
STATE        : Active
IDLE_TIME    : none
LOGON_TIME   : 9/27/2023 3:51 PM
IDLE_MINUTES : 0
IDLE_HOURS   : 0

Get-QUser PowerShell Function

Here’s the funtion. I hope it helps.

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
<#
.SYNOPSIS
    A function to get the output of quser as a comma-separated array with additional calculated idle time.
 
.DESCRIPTION
    This function runs quser on a specified computer (or the local computer if no computer name is provided), 
    and returns the output as a comma-separated array. If quser doesn't output a value for SESSIONNAME, 
    an extra comma is added to ensure each row has exactly six values. Additionally, it calculates idle time in minutes and hours.
 
.PARAMETER ComputerName
    The name of the computer to run quser on. If no computer name is provided, the function defaults to the local computer.
 
.EXAMPLE
    PS C:\> Get-QUser -ComputerName "RemoteComputerName"
 
    This command runs quser on the computer named "RemoteComputerName" and returns the output as a comma-separated array with additional calculated idle time.
 
.EXAMPLE
    PS C:\> Get-QUser
 
    This command runs quser on the local computer and returns the output as a comma-separated array with additional calculated idle time.
#>
function Get-QUser {
    param (
        [string]$ComputerName = $env:COMPUTERNAME
    )
 
    # Get the raw output of quser
    $QuserRaw = Invoke-Command -ComputerName $ComputerName -ScriptBlock { quser }
 
    # Modify the output by making it comma delimited
    $QuserCSV = $QUserRaw.Trim().Replace("  ",",").Replace(", ",",").Replace(" ,",",").Replace(",,,,,",",").Replace(",,,,",",").Replace(",,,",",").Replace(",,",",")
 
    # Convert the CSV string to an array
    $QuserArray = $QuserCSV -split "`n"
 
    # Iterate over each row in the array to find any row with only five data values and add an extra comma for SESSIONNAME
    for ($i=0; $i -lt $QuserArray.Length; $i++) {
 
        # Count the number of commas in the row
        $commaCount = ([regex]::Matches($QuserArray[$i], ",")).Count
 
        # If there are only four commas, replace the first comma with two commas
        if ($commaCount -eq 4) {
            $firstCommaIndex = $QuserArray[$i].IndexOf(",")
            $QuserArray[$i] = $QuserArray[$i].Insert($firstCommaIndex + 1, ",")
        }
    }
 
    # Convert string array to CSV object and remove first row (header)
    $QuserArray = $QuserArray | ConvertFrom-Csv -Header "USERNAME","SESSIONNAME","ID","STATE","IDLE_TIME","LOGON_TIME"
    $QuserArray = $QuserArray | Select-Object -Skip 1
 
    # Add IDLE_MINUTES and IDLE_HOURS columns
    foreach ($row in $QuserArray) {
        if ($row.IDLE_TIME -match "(\d+)\+(\d+):(\d+)") {
            # Format is days+hours:minutes
            $idleMinutes = [int]$matches[1]*24*60 + [int]$matches[2]*60 + [int]$matches[3]
        } elseif ($row.IDLE_TIME -match "(\d+):(\d+)") {
            # Format is hours:minutes
            $idleMinutes = [int]$matches[1]*60 + [int]$matches[2]
        } elseif ($row.IDLE_TIME -match "(\d+)") {
            # Format is minutes
            $idleMinutes = [int]$matches[1]
        } else {
            # Unknown format, set to 0
            $idleMinutes = 0
        }
 
        # Add calculated values to new columns
        $row | Add-Member -NotePropertyName IDLE_MINUTES -NotePropertyValue $idleMinutes
 
        $idleHours = [math]::Round($idleMinutes / 60, 2)
        $row | Add-Member -NotePropertyName IDLE_HOURS -NotePropertyValue $idleHours
    }
 
    # Output the corrected array with added columns
    return $QuserArray
}