Skip to content

Instantly share code, notes, and snippets.

@kspeeckaert
Last active September 13, 2021 11:47
Show Gist options
  • Save kspeeckaert/ef4b00f22f35267e83c023e4b505e1bc to your computer and use it in GitHub Desktop.
Save kspeeckaert/ef4b00f22f35267e83c023e4b505e1bc to your computer and use it in GitHub Desktop.
Wait until a remote host comes online and has RDP available, after a reboot.
#Requires -Module BurntToast
[cmdletbinding()]
param (
[Parameter(Mandatory)][string]$ComputerName,
[Parameter(Mandatory)][string]$ConnectionID
)
function Test-TCPPort {
# Replacement for Test-NetConnection, because ping cannot be disabled.
param (
[Parameter(Mandatory)][string]$ComputerName,
[Parameter(Mandatory)][int]$Port
)
$Connection = New-Object System.Net.Sockets.TCPClient
try {
$Connection.Connect($ComputerName, $Port)
return $true
}
catch {
return $false
}
finally {
$Connection.Dispose()
}
}
function Get-DisplayName {
param (
[Parameter(Mandatory)][string]$ComputerName
)
if ($ComputerName -match '\d+\.\d+\.\d+\.\d+') {
# We have received an IP
$HostDisplayName = $ComputerName
} else {
# We received a hostname, possibly with FQDN
$HostDisplayName = $ComputerName.split('.')[0]
}
return $HostDisplayName
}
function Wait-RDPAvailable {
param (
[Parameter(Mandatory)][string]$ComputerName,
[Parameter()][int]$DelaySeconds = 2
)
Write-Host "Waiting for RDP to become available..."
while ($true) {
$ConnectSuccess = Test-TCPPort `
-ComputerName $ComputerName `
-Port 3389
if ($ConnectSuccess) {
break
}
Write-Verbose "Sleeping $DelaySeconds seconds..."
Start-Sleep $DelaySeconds
}
}
function Wait-StatusChange {
param (
[Parameter(Mandatory)][string]$ComputerName,
[Parameter(Mandatory)][bool]$Online,
[Parameter()][int]$DelaySeconds = 2
)
if ($Online) {
Write-Host "Waiting for $ComputerName to come online..."
} else {
Write-Host "Waiting for $ComputerName to go offline..."
}
while ($true)
{
$HostOnline = Get-OnlineStatus -ComputerName $ComputerName
if ($HostOnline -eq $Online) {
break
}
Write-Verbose "Sleeping $DelaySeconds seconds..."
Start-Sleep -Seconds $DelaySeconds
}
}
function Get-OnlineStatus {
param (
[Parameter(Mandatory)][string]$ComputerName
)
return $(Test-NetConnection -ComputerName $ComputerName -InformationLevel Quiet)
}
Set-Variable AppLogo -Option Constant -Value "C:\Work\scripts\royalts.png"
# Disable progress bars
$OriginalProgressPreference = $Global:ProgressPreference
$Global:ProgressPreference = 'SilentlyContinue'
try {
# Shorten the host's display name, if a FQDN is passed (otherwise it might be too long for the notification text)
$HostDisplayName = Get-DisplayName -ComputerName $ComputerName
# Bind hash table for notifications
$ToastDataBind = @{
FirstLine = "Host Monitor"
SecondLine = "Monitoring $HostDisplayName"
Thirdline = ''
ProgressStatus = ''
}
$ToastID = "HostMonitor_${HostDisplayName}"
$Progress = New-BTProgressBar -Status 'ProgressStatus' -Indeterminate
New-BurntToastNotification `
-AppLogo $AppLogo `
-Text 'FirstLine','SecondLine','Thirdline' `
-UniqueIdentifier $ToastID `
-DataBinding $ToastDataBind `
-ProgressBar $Progress
# Get the initial state
$HostOnline = Get-OnlineStatus -ComputerName $ComputerName
if ($HostOnline) {
# Host is still online, wait for it to go offline
Write-Verbose 'Host is online'
$ToastDataBind['Thirdline'] = "Host is online"
$ToastDataBind['ProgressStatus'] = 'Waiting to go offline...'
Update-BTNotification -UniqueIdentifier $ToastID -DataBinding $ToastDataBind
Wait-StatusChange -ComputerName $ComputerName -Online $false
}
Write-Verbose 'Host is offline'
$ToastDataBind['Thirdline'] = "Host is offline"
$ToastDataBind['ProgressStatus'] = 'Waiting to come online...'
Update-BTNotification -UniqueIdentifier $ToastID -DataBinding $ToastDataBind
Wait-StatusChange -ComputerName $ComputerName -Online $true
Write-Verbose 'Host is online'
$ToastDataBind['Thirdline'] = "Host is online"
$ToastDataBind['ProgressStatus'] = 'Waiting for RDP service...'
Update-BTNotification -UniqueIdentifier $ToastID -DataBinding $ToastDataBind
Wait-RDPAvailable -ComputerName $ComputerName
Write-Verbose 'RDP is available'
$ToastDataBind['Thirdline'] = "RDP is available"
# Provide a button to connect to the host using RoyalTS
$Button = New-BTButton -Content 'Connect' -Arguments "rtscli://local/action/connect?-id=${ConnectionID}"
# Replace the notification, thereby removing the progressbar and offer a connect button
New-BurntToastNotification `
-AppLogo $AppLogo `
-Text 'FirstLine','SecondLine','Thirdline' `
-Button $Button `
-UniqueIdentifier $ToastID `
-DataBinding $ToastDataBind
}
finally {
# Restore progress preference setting
$Global:ProgressPreference = $OriginalProgressPreference
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment