Powershell + Robocopy

I know this is not strictly a powershell topic, but I am trying to use a powershell script to check for existence of files, and then if they don’t exist copy them from a network location to the current users %appdata% subdirectories
I have listed the code below and the error I am getting, I have tried multiple variations of this code.
Your assistance is greatly appreciated.

If (test-path $env:APPDATA"\microsoft\signatures\citywide signature.txt") {exit}
$source= “\addomainname\SYSVOL\deerpark.local\scripts\Citywide Signature"
$Destination= $env:APPDATA + “\microsoft\signatures"
$options= (”/r:5”,“/w:10”,“/e”)
invoke-expression “robocopy $source $destination $options”

ROBOCOPY :: Robust File Copy for Windows

Started : Tuesday, January 17, 2017 11:39:14 AM
Source - \deerpark.local\SYSVOL\deerpark.local\scripts\Citywide
Dest - C:\Users\ahollister\downloads\Citywide Signature\Signature\

Files : 

Options : /DCOPY:DA /COPY:DAT /R:1000000 /W:30

ERROR : Invalid Parameter #3 : "C:\Users\ahollister\AppData\Roaming\microsoft\signatures"

No need for Invoke-Expression and a double quotation was in the wrong place.

$source= "\\addomainname\SYSVOL\deerpark.local\scripts\Citywide Signature\"
$Destination= "$env:APPDATA\microsoft\signatures\"

If (-NOT(test-path "$env:APPDATA\microsoft\signatures\citywide signature.txt")) {
    robocopy $Source $Destination "/r:5","/w:10","/e"
} Else {Write-Verbose "File exists for $env:USERNAME" -Verbose}

using your method, I now see this error…

Started : Tuesday, January 17, 2017 12:49:48 PM
Source : \deerpark.local\SYSVOL\deerpark.local\scripts\Citywide Signature" C:\Users\ahollister\AppData\Roaming\microsoft\signatures\ \r:5,\w:10,\e
Dest -
Files : .
Options : . /DCOPY:DA /COPY:DAT /R:1000000 /W:30

ERROR : No Destination Directory Specified.

the best method I found for robocoopy is:

$source= "\\addomainname\SYSVOL\deerpark.local\scripts\Citywide Signature\"
$Destination= $env:APPDATA + "\microsoft\signatures\"
$options= $source, $destination, "/r:5","/w:10","/e"

& robocopy $options

shows the whole string as the source

ROBOCOPY :: Robust File Copy for Windows

Started : Wednesday, January 18, 2017 9:28:49 AM
Source : \deerpark.local\SYSVOL\deerpark.local\scripts\Citywide Signature" C:\Users\ahollister\AppData\Roaming\microsoft\signatures\ \r:5 \w:10 \e
Dest -

Files : *.*

Options : . /DCOPY:DA /COPY:DAT /R:1000000 /W:30

ERROR : No Destination Directory Specified.

I think you forget a comma or a quote between $source and $destination.
why you don’t post command executed, just result ? I haven’t a crystal ball :slight_smile:

PS C:\> $source= 'C:\111'
PS C:\> $Destination= 'C:\222'
PS C:\> $options= $source, $Destination, "/r:5", "/w:10", "/e"
PS C:\> & robocopy $options

   ROBOCOPY     ::     Robust File Copy for Windows

  Started : Thu Jan 19 11:06:44 2017

   Source : C:\111\
     Dest : C:\222\

    Files : *.*

  Options : *.* /S /E /COPY:DAT /R:5 /W:10


                           3    C:\111\
100%        New File                 233        disableIPV6.bat
100%        New File              931933        DynDNS.log
100%        New File               60617        log


               Total    Copied   Skipped  Mismatch    FAILED    Extras
    Dirs :         1         0         1         0         0         0
   Files :         3         3         0         0         0         0
   Bytes :   969.5 k   969.5 k         0         0         0         0
   Times :   0:00:00   0:00:00                       0:00:00   0:00:00

   Speed :            62048937 Bytes/sec.
   Speed :            3550.468 MegaBytes/min.

   Ended : Thu Jan 19 11:06:44 2017
1 Like


are you running this on Windows 10 build 14393 (Anniversary Update) or 14986? I’ve done some testing with above code and it looks like the PowerShell engine in both builds and may be later versions too is passing everything as one argument to robocopy instead of separate arguments. It works for me as expected on Windows 7 with PSVersion 5.0.10586.117 which is an older PS engine.

Yep that appears to be the problem.
I apologize for the late response.

I worked around this problem by using copy-item as opposed to calling robocopy
I don’t know if there is any performance difference, but even if there is it will not make a large difference on 25MB of files.

thanks for your help everyone.

Hello Max,

I’m so glad I stumbled across your post. I’ve been determined to get robocopy options to work in a variable like they do in my batch files.

It’s a bit clunky, but now that I got it working with your advice, it shouldn’t be too difficult to make changes as needed.

For others who stumble upon this thread:

For comparison, here is a truncated version of what the robocopy options look like in a batch script:

set cpe=/e /eta /mt:32 /xa:h /r:1 /w:1 /tee /v /z
robocopy %source% %dest% %cpe% %log%

Here is a truncated version of what the robocopy options look like in a PowerShell script:

$options = $source,$dest,$files,'/eta','/mt:32','/r:1','/w:1','/tee','/v','/z',"/log+:$source\$logfile"
& robocopy $options

Basically, you took the entire line of code and placed it in a variable ($options). I had no success before because I didn’t realize that each piece of the code needed to be place in either single or double quotes when it began with a special character other than the $, AND separated by a comma.

I discovered that the space between them is optional. I tried with a space at first, then removed them and it still worked.

Therefore, I didn’t need quotes for: $source,$dest,$files; only the robocopy options. However, if you add something to the variable - like a subfolder - then quotes are needed.

Such as from $source to "$source\Backup"

Regarding the LOG FILE:

The entire string needs to be enclosed in “double quotes”. PowerShell didn’t like the single quotes which I often use for strings not containing variables.

Here’s my full working code for testing this out in which I copied all of the PowerShell scripts located in my $source folder to a test $dest folder, creating a log file as well.

# Variables
$source = 'D:\Scripts\Test_Source'
$dest = 'D:\Scripts\Test_Dest'
$files ='*.ps1'
$logfile = "Copy Powershell scripts.txt"

# Run robocopy
$options = $source,$dest,$files,"/eta","/mt:32","/r:1","/w:1","/tee","/v","/z","/log+:$source\$logfile"
& robocopy $options

For those still having trouble, or just want a cleaner look, you can always run the options outside a variable like normal:

robocopy $source $dest $files /eta /mt:32 /r:1 /w:1 /tee /v /z /log+:"$source\$logfile"

This information may still be relevant to you and others who stumble across this thread.

I originally replied validating max’s solution and I was grateful that it worked. However, I just stumbled across an easier way that works pretty much the same way as in a batch script.

My initial interest revolved around using my Robocopy Options in a combined variable in POSH as I do in my batch scripts. The original method in this thread is more limited; I found this post helpful in understanding this process.

So, let me share what does work. I’ll keep it short…

I stumbled across this blog tackling the issue regarding the removal of an application using CMD in PowerShell:

cmd /c "msiexec /Lvx* c:\Temp\MsiUnInstall.log /x {2E64FC5C-9286-4A31-916B-0D8AE4B22954} /qn"

This looked very promising and simple enough to validate rather quickly.

So, I took my existing test code and placed my robocopy options into a single variable - like I do in my batch files- and lo and behold… it worked! :+1:t3:

$source = 'D:\Scripts\_WIP'
$dest = 'D:\COPY_TEST'
$files ='*.ps1'
$options = '/eta /mt:32 /r:1 /w:1 /tee /v /z'
$logfile = 'Copy PowerShell scripts.txt'

cmd /c "robocopy $source $dest $files $options /log+:`"$source\$logfile`""

The following code is what my longer test looks like. It’s more granular and it’s exactly how I use them in my batch files.

# Paths
$source = 'D:\Scripts\_WIP'
$dest = 'D:\COPY_TEST'

# Copy/Retry/Logging Options
$files ='*.ps1'
$cpf = '/eta /mt:32 /xa:h /r:1 /w:1 /tee /v /z'

# File Selection/Log File Options
$xa = '/xa:h'
$xf = '/xf Copy*.txt Mirror*.txt'
$xd = '/xd "System Volume Information" "$RECYCLE.BIN" "#recycle"'
$logfile = 'Copy PowerShell scripts.txt'
$log = "/log+:`"$source\$logfile`""

# Run Robocopy
cmd /c "robocopy $source $dest $files $cpf $xa $xf $xd $log"

Here you can see it ran exactly as it would in a batch script:


I like to use single quotes for all of my string values.
$source = 'D:\Scripts\_WIP'

Double quotes are required when the string contains a variable.
$log = "/log+:"$source$logfile""

Standalone variables don’t require quotes unless they are combined with something:
$source standalone
"$source\MyBackups" or "$source\My Backups"