在PowerShell v3中同时运行并发的Invoke-WebRequest作业

9

在PowerShell中同时运行后台任务非常简单,但似乎无法使用新的(在v3中)cmdlet Invoke-WebRequest正常工作。

我正在通过PowerShell以脚本方式下载数千个文件。效果很好,但逐一进行下载需要花费几天时间:

for($f=0;$f -lt $urlList.Count;$f++)
{
    $remote = $urlList[$f] + $fileList[$f]
    $local = 'C:\folder\' + $fileList[$f]
    Invoke-WebRequest $remote -Method Get -OutFile $local -UserAgent FireFox
}

我尝试了几次利用"AsJob"方法,但是要么出现错误,要么完成时没有保存本地文件。这是后者的一个例子:

for($f=0;$f -lt $urlList.Count;$f++)
{
    $remote = $urlList[$f] + $fileList[$f]
    $local = 'C:\folder\' + $fileList[$f]
    $command = "Invoke-WebRequest $remote -Method Get -OutFile $local -UserAgent FireFox"
    Start-Job {Invoke-Expression -Command $command}
}
Get-Job|Wait-Job

输出示例:
Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
--     ----            -------------   -----         -----------     --------             -------                  
339    Job339          BackgroundJob   Running       True            localhost            Invoke-Expression -Com...
341    Job341          BackgroundJob   Running       True            localhost            Invoke-Expression -Com...
343    Job343          BackgroundJob   Running       True            localhost            Invoke-Expression -Com...
339    Job355          BackgroundJob   Completed     True            localhost            Invoke-Expression -Com...
341    Job357          BackgroundJob   Completed     True            localhost            Invoke-Expression -Com...
343    Job359          BackgroundJob   Completed     True            localhost            Invoke-Expression -Com...

奇怪的是,以上的工作完成所需的时间与下载相关文件的时间几乎相同......因此看起来数据正在流向某个地方——只是没有到达我的保存位置。我猜数据正在进入内存,但在没有保存的情况下被释放了。尝试添加和删除“PassThru”选项,但无论哪种方式都得到相同的结果。还尝试将其管道传输到Out-File,仍无法解决。不确定为什么这个特定的cmdlet如此棘手。


请返回翻译后的文本:这里是绝妙的答案 - jkdba
1个回答

10
您需要以这样的方式传递参数,以确保它们被正确地传递到作业中。在V3中,您可以使用$using:语法来实现这一点:
for($f=0;$f -lt $urlList.Count;$f++)
{
    $remote = $urlList[$f] + $fileList[$f]
    $local = 'C:\folder\' + $fileList[$f]
    Start-Job {Invoke-WebRequest $using:remote -Method Get -OutFile $using:local -UserAgent FireFox}
}
Get-Job|Wait-Job

顺便说一下,您不需要使用Invoke-Expression。只需将要运行的代码放在作业中的脚本块内,即一组花括号{...}


这很好用。这个有文档吗?我已经阅读了关于工作和关于工作详细信息的手册,但是找不到任何关于$using:语法的参考。 - Local Needs
2
我在 $using 上找到了这个信息: link - jbockle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接