Search code examples
powershellparallel-processingrobocopystart-job

Powershell pass arguments to robocopy nested in a Start-Job


After a massive amount of headaches, I was able to get this almost functioning.

Problem: In the error/output Robocopy appears to be treating $args[4] (ref: $sourcePath) as everysingle IP in the range instead of just one object.

I'm assuming the rest of the syntax is correct, because if I switch $ip = 101..119 | foreach { "192.168.1.$_" } to $ip = "192.168.1.101" everything works correctly.

The Robocopy dumps into the console -source as all of the IP addresses in the range from $ip. What am I doing wrong here?

#####################################################
#Purpose: to ping an IP range of network locations in a loop until successful. When successful, copy new files from source onto storage.
#Each ping and transfer needs to be ran individually and simultaneously due to time constraints.
#####################################################

#define the IP range, source path & credentials, and storage path
$ip = 101..119 | foreach { "192.168.1.$_" } 
#$ip = "192.168.1.101"  #everything works if I comment above and uncomment here
$source = "\\$ip"
$sourcePath = "$source\admin\" 
$dest = "C:\Storage\"
$destFull = "$dest$ip\"
$username = "user"
$password = "password"

#This is how to test connection. Once returns TRUE, then copy new files only from source to destination.
#copy all subdirectories & files in restartable mode

foreach ($src in $ip){
Start-Job -ScriptBlock {
   DO {$ping = Test-Connection $args[0] -BufferSize 16 -Count 4 -quiet} 
   until ($ping)
    net use \\$args[1] $args[2] /USER:$args[3]
    robocopy $args[4] $args[5] /E /Z   
    } -ArgumentList $src, $source, $password, $username, $sourcePath, $destFull  -Name "$src"  #pass arguments to Start-Job's scriptblock
}

#get all jobs in session, supress command prompt until all jobs are complete. Then once complete, get the results.

Get-Job | Wait-Job 
Get-Job | Receive-Job

Solution

  • At the point you create $source, $ip is an array, so $source ends up as a very long string of all the items concatenated:

    \\192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104 ...
    

    You can see this for yourself, by running just these two lines, then examining the contents of $source:

    $ip = 101..119 | foreach { "192.168.1.$_" }
    $source = "\\$ip"
    

    This has a knock-on effect to $sourcePath which is used as $args[4] in your call to RoboCopy. You should build your paths inside your foreach loop, where you have access to each IP address ($src) from the $ip collection.