locked
Adding the results of Compare-Object to an array to loop through RRS feed

  • Question

  • I am attempting to create a Powershell script to reboot a pre-defined list of servers, from a named text file, excluding any server listed in a second, named input file that is also listed in the first, named input file. 

    I have a text file with a list of servers listed, one per line, within the source file (see 1000.txt). I have a second text file with a list of servers, one per line, see (exclusions.txt).

    1000.txt        exclusions.txt

    Server1      Server1

    Server2         Server4

    Server3

    Server4

    My goal is to use the Powershell Compare-Object cmdlet to compare the contents of the two files and add the results of the compare to an array.

    Next, using a ForEach loop, loop through the newly created array and reboot server that was added after the compare was done.

    Here is the code I have so far:

    # USAGE: .\Reboot-Servers -File <Filename> -Exclusions .\exclusions.txt

    Param( 
    [Parameter(Position=0, Mandatory=$true)] 
    [string] 
    [ValidateNotNullOrEmpty()] 
    [alias("f")] 
    $File,
    [Parameter(Position=1, Mandatory=$false)] 
    [string] 
    [ValidateNotNullOrEmpty()] 
    [alias("e")] 
    $Exclusions
    )#End Param
    #$ErrorActionPreference = "SilentlyContinue"



    [Array]$Servers = Compare-Object -ReferenceObject $(Get-Content $File) -DifferenceObject $(Get-Content $Exclusions) | Where-Object {$_.SideIndicator -eq "<="} | Select-Object -ExpandProperty InputObject | Sort-Object

    ForEach ($Server in $Servers) {
    $cmd = Restart-Computer -Wait -ThrottleLimit 2 -Force
    Invoke-Command -ComputerName $Server -ScriptBlock {$cmd}
    IF ($cmd.returnvalue -match "0") 
    {
    Write-Host "$Server - Reboot command is complete" -ForegroundColor Green
    } ELSE {
    Write-Host "$Server - Unable to send reboot command" -ForegroundColor Red
    }
    }
    $Servers = @()

    The Compare-Object cmdlet is working as expected and is creating a string object with the resulting list of servers in the following format

    Server2 Server 3

    The ForEach loop is correctly reading the first object in the array called $Servers. However, any subsequent object is ignored.  The IF, ELSE statement is being completely ignored.

    Could someone please shed some light on what I am doing wrong? Or perhaps suggest an alternate method of achieving the same result?


    H. Miller

    • Moved by Bill_Stewart Thursday, June 19, 2014 8:58 PM Abandoned
    Thursday, January 2, 2014 5:10 PM

Answers

  • There are a couple things that need to be fixed before it will work:
    1. The Restart-Computer command isn't valid. You're using both the -Wait and -ThrottleLimit parameters, and they are in different parameter sets.
    2. I'm assuming that you're trying to send the Restart-Computer command to the server to run locally via Invoke-Command. If  you are, you need to define cmd like this (notice the curly brackets): $cmd = { Restart-Computer [-Params] }
    3. If #2 is correct, another problem with Restart-Computer is that -Wait can't be run interactively (try 'Restart-Computer -Wait' interactively from your prompt)
    4. I don't think $cmd is going to have a returnvalue property

    Restart-Computer can take an array of computer names. You can run it as a background job using the -AsJob parameter. You could try something like this:

    $Jobs = Restart-Computer -ComputerName $Servers -AsJob
    $Results = $Jobs | Receive-Job
    $Results

    Or, if you want to truly wait on each server to come back up, you might try something like this (this way is going to take a lot more time since it will only work on one machine at a time):

    foreach ($Server in $Servers) {
        Write-Verbose "Working with $Server"
        Restart-Computer -ComputerName $Server -Wait -Force -WhatIf
    
        "$Server - Reboot command is complete"
    }
    


    It's entirely possible that I'm missing something, so let me know if you think that's the case.

    Friday, January 3, 2014 2:20 AM