workholic
workholic

Reputation: 135

logic for powershell for-each loop

I was using below powershell script to loop thru servers in the list to perform particular tasks depending upon the server's hostname. In the below script if $server = 'server1' I want to perform different set of tasks in contrast to other servers, But this loop is directly executing 'else' loop. I'm I missing anything here?

$servernames = @("server1", "server2", "server3")
$user = '**********'
$Password = '*******'
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $user, $SecurePassword

foreach($server in $servernames)
{
    Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {          
        if ($server -eq 'server1')
        {
            #do some task on server1
        }
        else
        {
            #do tasks for remaining servers
        }
    } 

    if ($error) { exit 1 }
}

Upvotes: 0

Views: 118

Answers (3)

Bacon Bits
Bacon Bits

Reputation: 32230

The value for the $server variable goes out of scope once it gets passed to the remote system. To prevent that from happening, you need to pass the parameters you need. To do that, you treat the script block you use as a function and define parameters for it, and then use the ArgumentList parameter of Invoke-Command to pass the values:

foreach ($server in $servernames) {
    Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {          
        Param($server)
        if ($server -eq 'server1') {
            #do some task on server1
        }
        else {
            #do tasks for remaining servers
        }
    } -ArgumentList $server

    if ($error) { exit 1 }
}

To be a little more clear about what's happening, I'll rename the parameter that the script block uses:

foreach ($server in $servernames) {
    Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {          
        Param($MyServer)
        if ($MyServer -eq 'server1') {
            #do some task on server1
        }
        else {
            #do tasks for remaining servers
        }
    } -ArgumentList $Server

    if ($error) { exit 1 }
}

Upvotes: 0

Maximilian Burszley
Maximilian Burszley

Reputation: 19704

Your scriptblock is in a different scope and doesn't see $server. I'd suggest figuring out your logic before executing the command.

If ($Server -eq 'server1')
{ Invoke-Command -ComputerName $Server -Credential $Cred -ScriptBlock {} }

Upvotes: 1

BenH
BenH

Reputation: 10054

Since $Server is inside the script block of the invoke command, it doesn't exist in that scope. You could pass it with -Argumentlist or the "using" scope (PS3+) e.g. if ($using:server -eq 'server1') But likely makes more sense, to put the if statement outside of the Invoke-Command.

if ($server -eq 'server1') {
    Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock { 
        "Stuff to do on Server1"
    }
} else { "Other Servers"}

Upvotes: 1

Related Questions