Public/Invoke-RPAReboot.ps1
<#
.SYNOPSIS Checks if a specified service on a computer is operational. .DESCRIPTION This function attempts to verify if a computer is responsive and if a specified service is actively running. It continuously checks the system's WMI accessibility and the service status until the service is running or a timeout occurs. .PARAMETER ComputerName The name of the computer to check. .PARAMETER ServiceName The name of the service to check for running status. .PARAMETER TimeoutSeconds The maximum time in seconds to wait for the system and service to become responsive. .EXAMPLE Check-SystemState -ComputerName "Server01" -ServiceName "loginagent" -TimeoutSeconds 100 Checks if the "loginagent" service on "Server01" is running, with a timeout of 100 seconds. .NOTES Ensure that the computer is accessible over the network and that WMI services are enabled. #> Function Check-SystemState { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ComputerName, [Parameter(Mandatory = $true)] [string]$ServiceName, [int]$TimeoutSeconds = 100 ) $startTime = [datetime]::Now while (!(Get-WmiObject Win32_Bios -ComputerName $ComputerName -ErrorAction SilentlyContinue)) { Start-Sleep -Seconds 5 if (([datetime]::Now - $startTime).TotalSeconds -gt $TimeoutSeconds) { Write-Output "Connection to $ComputerName timed out." return $false } } Write-Output "$ComputerName is responsive. Checking if the 'loginagent' service is started." do { $service = Get-Service -ComputerName $ComputerName -Name $ServiceName -ErrorAction SilentlyContinue Start-Sleep -Seconds 5 } while ($service.Status -ne 'Running' -and ([datetime]::Now - $startTime).TotalSeconds -lt $TimeoutSeconds) if ($service.Status -eq 'Running') { Write-Output "The 'loginagent' service on $ComputerName has started successfully." return $true } else { Write-Output "Failed to verify that the 'loginagent' service is running on $ComputerName." return $false } } <# .SYNOPSIS Retrieves the logged-in status of a user on a specified remote computer. .DESCRIPTION This function checks if any user is currently logged into the specified computer. It uses WMI to retrieve user login status and outputs whether a user is logged in or not. .PARAMETER ComputerName The name of the computer to check the login status of. .EXAMPLE Get-LoggedInStatus -ComputerName "Server01" Checks if any user is logged in on "Server01". .NOTES Requires network connectivity and appropriate permissions to access WMI on the target computer. #> Function Get-LoggedInStatus { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ComputerName ) if (Test-Connection -ComputerName $ComputerName -Count 2 -Quiet) { try { $userDetails = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $ComputerName -ErrorAction Stop if ($userDetails.UserName) { Write-Output "Computer in use." } else { Write-Output 'Not logged on.' } } catch { Write-Output "Failed to retrieve user information: $_" } } else { Write-Output 'Computer offline.' } } <# .SYNOPSIS Initiates a reboot of a specified host and verifies its operational status afterward. .DESCRIPTION This function reboots the server if no users are logged on. Post-reboot, it confirms if a specified service is running on the system. .PARAMETER HostName The name of the host to reboot. .PARAMETER ServiceName The service to check for operational status post-reboot. .EXAMPLE Invoke-RPAReboot -HostName "Server01" -ServiceName "loginagent" Attempts to reboot "Server01" and checks if the "loginagent" service is running post-reboot. .NOTES The function checks for user logoff before initiating a reboot. It requires network access and administrative privileges on the target host. #> Function Invoke-RPAReboot { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0)] [string]$HostName, [Parameter(Mandatory = $true, Position = 1)] [string]$ServiceName ) if (Test-Connection -ComputerName $HostName -Count 2 -Quiet) { $status = Get-LoggedInStatus -ComputerName $HostName if ($status -eq 'Not logged on.') { Write-Output "Please wait while we reboot the server $HostName." try { if ((Get-WmiObject Win32_OperatingSystem -ComputerName $HostName | Invoke-WmiMethod -Name Win32Shutdown -ArgumentList 6).ReturnValue -eq 0) { Start-Sleep -Seconds 15 if (Check-SystemState -ComputerName $HostName -ServiceName $ServiceName) { Write-Output "$(Get-Date) - $HostName Successfully Restarted" } else { Write-Output "Failed to verify restart on $HostName." } } else { Write-Output "Failed to initiate reboot on $HostName." } } catch { Write-Output "Error during reboot process: $_" } } elseif ($status -eq 'Computer in use.') { $userDetails = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $HostName -ErrorAction Stop Write-Output "$($userDetails.UserName) is logged in already on $HostName. Please log off the user before retrying." } } else { Write-Output "$HostName is not reachable." } } |