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-Host "$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 [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.Session) { 'Online' } else { 'Offline' }) `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 1)) { $this.Session = $null return ($old.Session) } if (-not ($this.Session)) { $this.Session = New-PSSession -ComputerName $this.Hostname -SessionOption (New-PSSessionOption -NoMachineProfile) } $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)" } else{ $this.LastUser = $null } } return (($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 } $date = Get-Date -Format "[MM/dd/yy HH:MM:ss]" if ($old.Session -ne $this.Session) { if ($old.Session -and $this.Session) { return "$date $($this.Hostname) | Session re-established" } elseif ($this.Session) { return "$date $($this.Hostname) | Online" } else { return "$date $($this.Hostname) | Offline" } } elseif ($old.LastUser -ne $this.LastUser) { if ($old.LastUser -and $this.LastUser) { return "$date $($this.Hostname) | $($old.LastUser) logged off and $($this.LastUser) logged on" } elseif ($old.LastUser) { return "$date $($this.Hostname) | $($old.LastUser) logged off" } else { return "$date $($this.Hostname) | $($this.LastUser) logged on" } } return $null } }