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
}

Use PowerShell’s Invoke-WebRequest to report if a website is up or down

If Internet Control Message Protocol (ICMP) — a protocol used to communicate problems with data transmission — is disabled, PowerShell’s Invoke-WebRequest can be a helpful alternative to use to monitor of a website is up or down.

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
# What website would you like to check if it is up or down?
$website = "https://example.com/"
 
# How many seconds do you wish to pause between attempts?
$seconds = 3
 
# Loop indefinitely
while($true) {
 
    # Clear previous result
    $response = $null
 
    # Send an HTTP request to a website and store the response object in $response
    try {
        $response = Invoke-WebRequest -Uri $website #-ErrorAction SilentlyContinue -UseBasicParsing -DisableKeepAlive
    } catch {
        $response = $null
    }
 
    # If the HTTP status code is 200 (OK), write "OK" to the console with a green background
    if($response.StatusCode -eq 200) {
        Write-Host (Get-Date).ToString() "Okay" -BackgroundColor Green
    } 
 
    # If the HTTP status code is not 200 (OK), write "Fail" to the console with a red background and play a sound
    else {
        Write-Host (Get-Date).ToString() "Failed" -BackgroundColor Red
        [System.Console]::Beep(200,1500)
    }
 
    # Wait for X seconds (defined above) before sending another request
    Start-Sleep -Seconds $seconds
}

Booe North Carolina genealogy books

My grandmother Sarah Alexander Pearce enjoyed genealogy. She most enjoyed researching the Booe surname (mostly from North Carolina), and created four books on the Booe surname.

They feature her ancestors:

Booe Genealogy Book Red Binding

SaAlPe Booe Genealogy red book (2015 May)

Booe Genealogy Book Blue Binding

SaAlPe Booe Genealogy blue book (2015 May)

Booe Genealogy Book III

SaAlPe Booe Genealogy book III (2015 May)

Booe Genealogy Book: Booe Who

SaAlPe Booe Genealogy Booe! Who? (2015 May)

Chinanethost.org Domain Registration Scam

This scam is so old I forgot about it. Goes back to at least 2010.

Basically, the scammer says they run a domain name registrar and noticed someone trying to buy .cn, .net.cn, .org.cn, and other variations of a domain name you already own.

At first, they imply that they want confirmation from you to block the sale of similar domain names. In reality, they want you to block the sale by buying the domains from them yourself.

Don’t fall for it. Very few can afford to by every top level domain variation of their domain name. Learn more about this scam here and here.

This is the version of the scam I received in 2022 July:

Subject: exampledomain From: [email protected] (It’s very urgent, therefore we kindly ask you to forward this email to your CEO. If you believe this has been sent to you in error, please ignore it. Thanks) Dear CEO, This is a formal email. We are the Domain Registration Service company in Shanghai, China. Here I have something to confirm with you. On July 7, 2022, we received an application from Hongmei Ltd requested “exampledomain” as their internet keyword and China (CN) domain names (exampledomain.cn, exampledomain.com.cn, exampledomain.net.cn, exampledomain.org.cn). But after checking it, we find this name conflict with your company name or trademark. In order to deal with this matter better, it’s necessary to send email to you and confirm whether this company is your distributor in China? Best Regards Robert Liu | Service & Operations Manager China Registry (Head Office) Tel: +86-2161918696 Fax: +86-2161918697 Mob: +86-13816428671 6012, Xingdi Building, No. 1698 Yishan Road, Shanghai 201103, China This email contains privileged and confidential information intended for the addressee only. If you are not the intended recipient, please destroy this email and inform the sender immediately. We appreciate you respecting the confidentiality of this information by not disclosing or using the information in this email.

If you want to setup mail filtering rules to block this particular scammer, here’s some email header information:

As you can see, this particular scammer is using valid SPF, DKIM, and DMARC records.

Keyboard Shortcuts for InPrivate, Incognito, and Private browsers on Windows

Most browsers have a mode you may use that will not remember your history or cookies when closed. For a Windows machine, these are their keyboard shortcuts.