0

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 }
}

3 Answers 3

1

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"}
Sign up to request clarification or add additional context in comments.

Comments

1

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 {} }

Comments

0

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 }
}

2 Comments

Thanks for all the suggestions; In addition to that I had a unzip function which needs to be executed on all the servers in the list using invoke-command. Is there any better way to do rather than declaring unzip function inside invoke-command loop for each server? Add-Type -AssemblyName System.IO.Compression.FileSystem function Unzip { param([string]$zipfile, [string]$outpath) [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath) }
@workholic No, you will need to declare the function in the remote session somehow. The remote session is completely distinct from the local one. The only things that get passed to it are what you explicitly pass to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.