Windows Server 2019中Robocopy脚本迁移异常排查求助
我之前也碰到过类似的跨PowerShell版本的Robocopy参数问题,结合你的描述,大概率是PS5和PS4在外部命令参数处理、编码解析上的行为差异导致的,下面给你一步步排查和解决的方案:
1. 核心问题:PowerShell数组转外部命令参数的逻辑变化
在PS4中,把数组$RoboArgs传递给robocopy.exe时,PowerShell会直接将数组元素作为独立参数传递;但PS5对包含空格的路径/参数的引号处理更严格,经常出现参数被意外拆分的情况——比如带空格的日志路径会被拆成多个参数,导致Robocopy误判源、目标和日志路径的边界。
解决方法:用停止解析符号--%绕过PowerShell的参数解析
这个符号会告诉PowerShell,从该位置开始的参数直接传递给外部程序,不再进行PowerShell的语法解析(比如变量替换、引号处理),完美匹配PS4的参数传递逻辑:
# 原来的执行方式: # & robocopy $RoboArgs # 修改为: & robocopy --% $RoboArgs
2. 变量截断的根源:CSV读取的编码差异
Windows Server 2019的默认文本编码和2008不同,BCP生成的CSV文件默认是ASCII编码,但PS5默认用UTF-8读取,这会导致路径字符串中出现隐藏的乱码字符,最终引发变量截断。
解决方法:读取CSV时显式指定编码
确保和BCP生成的编码一致(BCP默认是ASCII):
# 原来的读取代码: # $folderList = Import-Csv -Path "latest.csv" # 修改为: $folderList = Import-Csv -Path "latest.csv" -Encoding ASCII
如果BCP用了其他编码(比如Unicode),对应调整-Encoding参数即可。
3. 修复日志路径的语法错误(ERROR 123)
ERROR 123是路径语法错误,本质是Robocopy没正确识别到日志路径的边界,把日志路径的一部分当成了源参数。这通常是因为带空格的路径没有被正确传递。
更可靠的参数构造方式:用Start-Process执行Robocopy
如果--%还是有问题,可以用Start-Process明确传递参数列表,彻底避免参数拆分:
# 构造完整的参数数组,手动给带空格的路径加双引号 $RoboArgs = @( $FileSource, $FileDestination, "/E", "/COPYALL", "/LOG:`"$LogPath`"" ) # 执行Robocopy,等待执行完成且不弹出新窗口 Start-Process -FilePath "robocopy.exe" -ArgumentList $RoboArgs -Wait -NoNewWindow
4. 调试技巧:确认实际执行的命令
在脚本中加入调试输出,对比PS4和PS5的参数差异,快速定位问题点:
# 输出即将执行的完整命令 Write-Host "即将执行的Robocopy命令:robocopy $($RoboArgs -join ' ')"
把PS4和PS5的输出对比,就能直观看到参数是否被截断、拆分,进而针对性修复。
内容的提问来源于stack exchange,提问作者Alex1088

