Powershell: Find Servers that Need a Reboot

Answered Powershell: Find Servers that Need a Reboot

  • Wednesday, February 20, 2013 3:44 PM
     
     

    I read this Hey Scripting guy blog post about locating servers that need a reboot. In the script that resulted, the author set the ErrorAction to silentlycontinue (-Ea 0). When I run the script, I get back the error: 

    Invoke-command : One or more computer names is not valid. If you are trying to pass a URI, use the -ConnectionUri parameter or pass URI objects instead of strings. At line:7 char:1

    + Invoke-command -ComputerName $servers.name -Ea silentlycontinue -ScriptBlock {

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (System.String[]:String[]) [Invoke-Command], ArgumentException

    + FullyQualifiedErrorId : PSSessionInvalidComputerName,Microsoft.PowerShell.Commands.InvokeCommandCommand

    I'm not surprised that there is a bad computer name, but I don't understand why the script dies when it finds it. I don't get any other output. What am I missing?

    Thanks.

All Replies

  • Wednesday, February 20, 2013 4:30 PM
     
     

    This script only works in a  domain with servers that you have permissions to read.  If $servers is null the script will fail.  You need to fix the script to check for null.


    ¯\_(ツ)_/¯

  • Wednesday, February 20, 2013 9:42 PM
     
     
    Yeah, I checked $servers and it certainly isn't null. There is a server called something like csd:203890921321. I assume that's what the script is choking on. Why wouldn't "-EA 0" cause the script just skip that server?
    • Edited by mhashemi Wednesday, February 20, 2013 9:42 PM
    •  
  • Wednesday, February 20, 2013 10:12 PM
     
     

    How are you laoding $servers.  Why would it not contain only computers?


    ¯\_(ツ)_/¯

  • Wednesday, February 20, 2013 10:15 PM
     
     

    Here is the run line for that script:

    Get-PendingReboot -ComputerName (Get-Content C:\ServerList.txt) | Format-Table -AutoSize 

    I do not see how you are getting the results you are getting unless you have loaded teh file with that name.

    ^The script fdor that blog is here: http://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542


    ¯\_(ツ)_/¯

  • Thursday, February 21, 2013 3:23 PM
     
      Has Code

    You and I are looking at different scripts. In this screenshot from the blog post, the author uses the following command to populate the $servers variable (line 3):

    $servers = Get-ADComputer -Filter * -Properties operatingsystem | Where operatingsystem -match 'server'

    No text file necessary.

  • Thursday, February 21, 2013 3:29 PM
     
      Has Code

    Just to be clear, the error is complaining about the following line: 

    Invoke-command -ComputerName $servers.name -ErrorAction silentlyContinue -ScriptBlock {

  • Thursday, February 21, 2013 4:17 PM
     
     

    What is in $servers?  It appears that you are not using the final scripts nor are you running the script correctly.  Since we cannot see your complete script it is impossible to know what is happening.

    $servers.name cannot work as intended unless you are using V3..  $servers is a collection.


    ¯\_(ツ)_/¯



  • Thursday, February 21, 2013 9:30 PM
     
     
    Looks like a problem with the the -EA. I'd say you'd be better off using a CATCH (example: http://stackoverflow.com/questions/6779186/powershell-try-catch-finally)
  • Wednesday, February 27, 2013 2:08 PM
     
     

    The variable $servers has a list of server names. You can see the completed script, if you look at either the link to the Scripting Guy blog post, or the screenshot I provided. That's all I've got.

    As indicated by the blog post and screen shot, I'm requiring version 3 (see "#requires") and I'm running the script from a Windows 8 laptop.

  • Wednesday, February 27, 2013 2:21 PM
     
     

    The variable $servers has a list of server names. You can see the completed script, if you look at either the link to the Scripting Guy blog post, or the screenshot I provided. That's all I've got.

    As indicated by the blog post and screen shot, I'm requiring version 3 (see "#requires") and I'm running the script from a Windows 8 laptop.

    You don't tell us how to you get $servers filled.  It is clear youa re getting the wrong information in serever names.  Server names cannot be URLs.  cid:...  is a URL.


    ¯\_(ツ)_/¯

  • Thursday, February 28, 2013 11:38 AM
    Moderator
     
     

    what version of PowerShell are you using? IF V2, then your error may be the $servers.name value for the computername parameter. In V2, $servers is an array and $servers.name will be null.

    Use a Foreach loop to loop throught the computers and invoke he command inside. Something like this:

    $servers = get-content foo.txt
    foreach ($server in $servers) {...  Invoke-command -computername $server ...}


    Thomas Lee <DoctorDNS@Gmail.Com>

  • Wednesday, March 06, 2013 2:15 PM
     
     
    As indicated by the blog post and screen shot, I'm requiring version 3 (see "#requires") and I'm running the script from a Windows 8 laptop.
  • Wednesday, March 06, 2013 3:36 PM
     
      Has Code
    As indicated by the blog post and screen shot, I'm requiring version 3 (see "#requires") and I'm running the script from a Windows 8 laptop.

    This is not a legal server name: "csd:203890921321"

    List all of your servers and find out why you are egetting names like that.

    # list all server names
    Get-ADComputer -Filter * -Properties operatingsystem |
       Where operatingsystem -match 'server' |
       select name


    ¯\_(ツ)_/¯

  • Wednesday, March 06, 2013 4:09 PM
     
     Answered Has Code

    Ok so I couldn't get all of the script that was posted in that blog but I do have an answer for you.  My function won't make a table for you but it will reboot the computers if you want.  The part that you'll find useful is the test-connection at the beginning of the foreach loop.  The test-connection will take care of any bad computernames you have in your array.  

    Function Get-RebootRequired {
    [CmdletBinding()]
    param
      (
        [Parameter(Mandatory=$false,
        ValueFromPipeline=$True,
        ValueFromPipelineByPropertyName=$True) ]
        [string[]]$computername	
      )
       process 
       {
       foreach ($computer in $computername) 
            {
            if (test-connection $computer -count -Quiet) 
                {
                Invoke-Command -ComputerName $computer -ScriptBlock {
                if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired")
                    {[String]$YN = read-host "Reboot Required on $computer, Do you want to Restart now? (Y/N)"
                    Switch ($YN) 
                        {
                        "Y" {Restart-Computer -computername $computer -Force} 
                        "N" {"End"}
                        }
                    }
                if ((Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") -eq $false) 
                    {"No Reboot Required on $computer"}
                }
                }
            Else {"$computer is not online"}
            }
        }
    }

    That way you can do get-reboot -computername ((Get-adcomputer -filter * -properties operatingsystem | where { $_.Operatingsystem -like 'Server' }).name) 

    I'm sure the script provided was good, if you're having a problem with it just use a foreach loop with a test-connection built in.  That'll deal with any bad names without causing any issues.

  • Tuesday, April 09, 2013 10:36 PM
     
     Answered Has Code

    It also looks like in your script $servers is an array.

    Foreach ($server in $servers)
        {invoke-command -ComputerName $server.name `
        -ErrorAction  silentlyContinue -ScriptBlock {'Somestuff'}
        }
    

    That might help


    Hope that helps! Jason