Sam
Sam

Reputation: 7678

Variables in Start-Job do not get evaluated

My Powershell code doesn't evaluate the $agent variable:

foreach ($agent in $agentcomputers) {
    Write-Output 'Starting agent on '$agent
    # psexc to start the agent
    Start-Job -ScriptBlock {& psexec $agent c:\grinder\examples\startAgent.cmd}
}

This link is similar to my problem, except I'm not calling an external Powershell script.

I tried adding that in, using $args[0] for $agent, and adding the -ArgumentList parameters, but that didn't work.


Edits/Replies

$agentcomputers is just a list of computer names - each on its own line:

$agentcomputers = Get-Content c:\grinder-dist\agent-computers.txt

I have also tried this - and $args[0] doesn't evaluate:

Start-Job -ScriptBlock {& psexec $args[0] c:\grinder\examples\startAgent.cmd} -ArgumentList @($agent)

Upvotes: 3

Views: 17547

Answers (2)

T.CK
T.CK

Reputation: 421

Here are 3 different ways I would do it. First, all aligned and pretty.

$agents = Get-Content c:\grinder-dist\agent-computers.txt
$jobs = {
     Param($agent)
         write-host "Starting agent on" $agent
         & psexec \\$agent c:\grinder\examples\startAgent.cmd
}
foreach($agent in $agents) {
     Start-Job -ScriptBlock $jobs -argumentlist $agent | Out-Null
}
Get-Job | Wait-Job | Receive-Job

Or you could just put it all on one line without creating any variables.

(Get-Content c:\grinder-dist\agent-computers.txt) | %{ Start-Job -ScriptBlock { param($_) write-host "Starting agent on" $_; & psexec \\$_ c:\grinder\examples\startAgent.cmd } -argumentlist $_ | Out-Null }
Get-Job | Wait-Job | Receive-Job

And in this final example, you could manage how many threads are run concurrently by doing it this way.

$MaxThreads = 5
$agents = Get-Content c:\grinder-dist\agent-computers.txt
$jobs = {
     Param($agent)
         write-host "Starting agent on" $agent
         & psexec \\$agent c:\grinder\examples\startAgent.cmd
}
foreach($agent in $agents) {
     Start-Job -ScriptBlock $jobs -argumentlist $agent | Out-Null
     While($(Get-Job -State 'Running').Count -ge $MaxThreads) {
          sleep 10
     }
     Get-Job | Wait-Job | Receive-Job
} 

Upvotes: 11

Sam
Sam

Reputation: 7678

Here is the solution. As Andy said, I needed to use $args array with the -ArgumentList parameter. This other thread was helpful: Powershell: passing parameters to a job

foreach($agent in $agentcomputers){
$agentslash = "\\"+$agent
$args = ($agentslash,"c:\grinder\examples\startAgent.cmd")
Write-Output 'Starting agent on '$agent

#psexc to start the agent
$ScriptBlock = {& 'psexec' @args } 

Start-Job -ScriptBlock $ScriptBlock -ArgumentList $args

}

Upvotes: 4

Related Questions