PowerShell: Reboot remote computers

PowerShell logo

It looks like it’s going to be a week of scripting blog posts.  Today’s script is used to reboot a list of remote computers.  Sometimes, when deploying security patches, the computers fails to reboot.  So I use this script to force reboots.  It would be a piece of cake to modify the script, so that it turns off the computers instead.

One of my customers should find that useful.  Out of 2000 computers, about 150 computers get left powered on over the weekend.

What the script does:

  • reads the list of computers to be reset from C:\computer_lists\reboot_target_list.txt
    the format of the list is COMPUTERNAME,Reboot Reason
  • “Pings” the computer to see if it’s on the network.
  • checks to see if someone is logged on.  If someone is, don’t reboot.
  • reboots the computer.

Check and reboot computers.ps1

Clear-Host

$ok_does_not_exist = $True
$date = ( get-date ).ToString('yyyyMMdd')
$reboot_logfile = "C:\computer_lists\output\$date-check_and_reboot_computers.txt"

#check that the pc-list file does exist.
$file_exist_reboot_list = (Test-Path C:\computer_lists\reboot_target_list.txt)

# if it does, do some process (check that it's pingable, has assorted files etc.
if (! $file_exist_reboot_list)
    {
    exit
    }
#endif

$reboot_pcs = (Get-Content C:\computer_lists\reboot_target_list.txt)
foreach ($pc_to_be_rebooted in $reboot_pcs)
    {
        $access_denied_error = $False
        # get the first comma position
        $string_delimiter_position_1  = $pc_to_be_rebooted.indexof(",")
        # get the server name
        $pc_name = $pc_to_be_rebooted.substring(0,$string_delimiter_position_1)

        $pc_name + ": checking PC" | Out-File $reboot_logfile -append
        #
           $reboot_reason = $pc_to_be_rebooted.substring($string_delimiter_position_1 + 1,$pc_to_be_rebooted.length - $string_delimiter_position_1 - 1)
        $address_string = "Address=" + "'" + $pc_name +"'"
           $ping = Get-WmiObject -Class Win32_PingStatus -Filter $address_string
           if ($ping.StatusCode -ne 0)
               {
               Write-Host Server: $pc_name - Not pingable
               $pc_name + ": not pingable, skipping" | Out-File $reboot_logfile -append
               }

        Trap [System.UnauthorizedAccessException]{
            write-host "Problem encountered with $pc_name - Access denied"
            $access_denied_error = $True
            continue;
            }
            $wmi_status = (Get-WmiObject -query "select * from win32_service where name='Winmgmt'" -computername $pc_name)
        if ($wmi_status.status -ne "OK")
            {
                $pc_name + ": WMI not accessible, skipping" | Out-File $reboot_logfile -append
                Write-Host Server: $pc_name - WMI not accessible
                $access_denied_error = $True
            }
        If ($access_denied_error)
            {
                Write-Host Server: $pc_name access denied
            }
        else
            {
            $objWMI_pc_computer_system = Get-WmiObject -Class Win32_ComputerSystem -computername $pc_name
            If ($objWMI_pc_computer_system.UserName.length -ge 0)
                {
                $pc_name + ": user logged on - skipping " + $objWMI_pc_computer_system.UserName | Out-File $reboot_logfile -append
                Write-Host $pc_name ": user logged on - " $objWMI_pc_computer_system.UserName
                }
            else
                {
                $objWMI_pc_os = Get-WmiObject -Class Win32_operatingsystem -computername $pc_name
                $objWMI_pc_os.reboot()
                $pc_name + ": rebooting" | Out-File $reboot_logfile -append
                Write-Host $pc_name ": sent reboot"
                }
            }
        }
exit

You can download the script here.

Bookmark and Share