function Invoke-PCMonitor {
    param(
        [string[]] $comps
    )
    # Ask to notify
    $notify = $(Read-Host "Notify with pop-up window? (y/N)") -match "^[yY]"
    if ($notify) {
        Add-Type -AssemblyName PresentationFramework
    }
    $sleepTime = $(Read-Host "Checkin interval in seconds (Default: 300 [5 min])")
    if (-not ($sleepTime)) { $sleepTime = 300 }
    $dogs = @()
    # Initialize computer sessions
    foreach ($comp in $comps) {
        Write-Progress -Activity "Initializing sessions" -Status $comp -PercentComplete ($dogs.Length/$comps.Length)
        $dog = [WatchDog]::new($comp)
        $null = $dog.Update()
        $dogs += $dog
    }
    Write-Progress -Activity "Initializing sessions" -Completed
    while ($true) {
        $change = $false
        foreach ($dog in $dogs) {
            $msg = $dog.ReportChange()
            if ($msg) {
                $change = $true
                if ($notify) {
                    $null = [System.Windows.MessageBox]::Show($msg)
                }
                Write-Output "$msg"
            }
        }
        # Update date and time so user knows script hasn't frozen
        if (-not ($change)) {
            $date = Get-Date -Format "[MM/dd/yy HH:mm:ss]"
            Write-Host -NoNewline "$date     `r"
        }
        Start-Sleep $sleepTime
    }
}

class WatchDog {
    [string]$Hostname
    [System.Management.Automation.Runspaces.PSSession]$Session
    [bool]$Online
    [string]$LastUser
    WatchDog() { $this.Init(@{})}
    WatchDog([hashtable]$Properties) { $this.Init($Properties)}
    WatchDog([string]$Hostname) { $this.Init(@{Hostname = $Hostname})}
    [void] Init([hashtable]$Properties){
        foreach ($prop in $Properties.Keys) {
            $this.$prop = $Properties.$prop
        }
    }
    [string] ToString() {
        return `
        "Hostname:    $($this.Hostname) `n" +
        "Status:      $(if ($this.Online) { 'Online' } else { 'Offline' }) `n" +
        "Session:     $(if ($this.Session) { 'True' } else { 'False' }) `n"
        "User:        $($this.LastUser) `n"
    }
    [WatchDog] Copy() {
        $props = @{}
        foreach ($prop in $this.PSObject.Properties) {
            $props.$($prop.Name) = $prop.Value
        }
        return [WatchDog]$props
    }
    # Returns true if a value was updated
    [bool] Update() {
        $old = $this.Copy()
        if (-not (Test-Connection -ComputerName $this.Hostname -Count 3)) {
            $this.Session = $null 
            $this.Online = $false
            $this.LastUser = ""
            return ($old.Online)
        } else {
            $this.Online = $true
        }
        if (-not ($this.Session)) {
            $this.Session = New-PSSession -ComputerName $this.Hostname -SessionOption (New-PSSessionOption -NoMachineProfile)
        }
        if ($this.Session) {
            $this.LastUser = $(Invoke-Command -Session $this.Session {Get-ComputerInfo}).CSUserName
            if($null -eq $this.LastUser){

                $this.LastUser = (Invoke-Command -Session $this.Session -ScriptBlock {Get-Process Explorer -IncludeUsername  | Where-Object { $_.Username -notlike "*SYSTEM" }} ).Username
                
                if($null -ne $this.LastUser){
                    $this.LastUser = "$($this.LastUser) (RDP/Inactive)"
                }
            }
        }
        if ($null -eq $this.LastUser) {
            $this.LastUser = ""
        }
        return (($this.Online -ne $old.Online) -or ($this.Session -ne $old.Session) -or ($this.LastUser -ne $old.LastUser)) 
    }
    # Returns a message describing any changes
    [string] ReportChange() {
        $old = $this.Copy()
        if (-not ($this.Update())) { return $null }
        $msg = ""
        $date = Get-Date -Format "[MM/dd/yy HH:MM:ss]"
        if ($old.Session -ne $this.Session) {
            if ($old.Session -and $this.Session) {
                $msg += "$date $($this.Hostname) | Session re-established`r`n"
            } 
        }
        if ($old.Online -ne $this.Online) {
            if ($this.Online) {
                $msg += "$date $($this.Hostname) | Online`r`n"
            } else {
                $msg += "$date $($this.Hostname) | Offline`r`n"
            }
        } 
        if ($old.LastUser -ne $this.LastUser) {
            if ($old.LastUser -ne "") {
                $msg += "$date $($this.Hostname) | $($old.LastUser) logged off`r`n"
            } 
            if ($this.LastUser -ne "") {
                $msg += "$date $($this.Hostname) | $($this.LastUser) logged on`r`n"
            }
        } 
        return $msg.Trim()
    }
}