Fedor Pinega
Fedor Pinega

Reputation: 73

Need to run app on N remotes hosts and handle them all

Im using this code to run app on N remote hosts and need to wait until all of them are finished and get their results. But the execution just passes throuhg, all jobs are being marked Completed and code exits. How to make it wait till apps finished their execution?

$procArray = [System.Collections.ArrayList]@()

foreach ($key in $simulatorServers.keys) {

    $unitHost = $simulatorServers[$key][0]
    $EXE="C:\app.exe"
    Wr-DebugReg "Running $EXE on $unitHost "
    $ScriptString="Start-Process -FilePath $EXE "
    $ScriptBlock=[System.Management.Automation.ScriptBlock]::Create($ScriptString)
    $Session=New-PSSession -ComputerName $unitHost -EnableNetworkAccess -Name "session$counter" -Credential $crNonProd
    $rez2 = Invoke-Command -Session $Session -ScriptBlock $ScriptBlock -AsJob
    $rez00=$procArray.Add($rez2)
    Wr-DebugReg "Running process id=$($rez2.id) name=$($proc.Name)on $unitHost"
    Wr-DebugReg ""
}
$procArray | Wait-Job
$procArray | Receive-Job

these jobs gone to status Completed even if launched processes still running enter image description here

Upvotes: 0

Views: 71

Answers (2)

Fedor Pinega
Fedor Pinega

Reputation: 73

This code is working. -Wait is the key to make it wait until all jobs are finished.

$procArray = [System.Collections.ArrayList]@()

foreach ($key in $hosts.keys) {
    $unitHost = $hosts[$key][0]
    $EXE="c:\app.exe"

    $Session=New-PSSession -ComputerName $unitHost -EnableNetworkAccess -Name "session$counter" -Credential $crNonProd
    $rez2 = Invoke-Command -Session $Session -ScriptBlock {Start-Process -FilePath $args[0] -Wait} -ArgumentList  $EXE -AsJob
    $rez00=$procArray.Add($rez2)
    Wr-DebugReg "Starting process id=$($rez2.id) name=$($proc.Name)on $unitHost"
    Wr-DebugReg ""
}

while ($procArray.State -contains 'Running')
{
    Start-Sleep -Seconds 1
}

Upvotes: 0

Toni
Toni

Reputation: 1816

let invoke-command handle the the amount of jobs/sessions to open in parallel - you will receive 1 job with childs:

$scriptBlock = {
    start-process -FilePath 'C:\app.exe' 
}

$sessions = @(
    foreach ($key in $simulatorServers.keys) {
        $unitHost = $simulatorServers[$key][0]
        New-PSSession -ComputerName $unitHost -EnableNetworkAccess -Name "session$counter" -Credential $crNonProd
    }
)

$job = Invoke-Command -Session $Sessions -ScriptBlock $ScriptBlock -AsJob

$result = receive-job -Wait -Job $job

btw. I do not see, based on this sample, what you want to receive. you want to execute "start-process -FilePath 'C:\app.exe' " on the target machines but this won't give you anything back.

to get the information back modify the scriptblock like this:

$scriptBlock = {
    $result = start-process -FilePath 'C:\app.exe' -wait -PassThru
    return $result
}

Upvotes: 2

Related Questions