【发布时间】:2019-06-29 16:49:26
【问题描述】:
我正在编写一个脚本,它尝试使用两种文件下载方法下载文件。 我不打算详细介绍,但生成的函数看起来像这样:
function Download-FileRobust($url, $targetFile) {
try {
Download-File $url $targetFile
}
catch {
Download-FileWget $url $targetFile
}
}
当Download-File 函数失败时,PowerShell 不会松开在位置$targetFile 处创建的文件的句柄,并且Download-FileWget 无法写入该位置。
我习惯了 Python,所以我花了很长时间才弄清楚问题所在。
另外两个函数的源码如下:
function Download-FileWget($url, $targetFile){
$wgetDir = (Get-ChildItem -Path "$env:userprofile\Downloads\wget*win32").FullName
if($env:Path -notlike "*$wgetDir*"){
$env:Path = "$wgetDir;$env:Path"
}
Invoke-Expression "wget '$url' -O '$targetFile'"
}
function Download-File($url, $targetFile){
$uri = New-Object "System.Uri" "$url"
$request = [System.Net.HttpWebRequest]::Create($uri)
$request.set_Timeout(15000) #15 second timeout
$response = $request.GetResponse()
$totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
$responseStream = $response.GetResponseStream()
$targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $targetFile, Create
$buffer = new-object byte[] 10KB
$count = $responseStream.Read($buffer,0,$buffer.length)
$downloadedBytes = $count
while ($count -gt 0){
$targetStream.Write($buffer, 0, $count)
$count = $responseStream.Read($buffer,0,$buffer.length)
$downloadedBytes = $downloadedBytes + $count
Write-Progress -activity "Downloading file '$($url.split('/') | Select -Last 1)'" -status "Downloaded ($([System.Math]::Floor($downloadedBytes/1024))K of $($totalLength)K): " -PercentComplete ((([System.Math]::Floor($downloadedBytes/1024)) / $totalLength) * 100)
}
Write-Progress -activity "Finished downloading file '$($url.split('/') | Select -Last 1)'"
$targetStream.Flush()
$targetStream.Close()
$targetStream.Dispose()
$responseStream.Dispose()
}
【问题讨论】:
-
你用的是什么版本的powershell?
-
我使用的是 2.0 版。升级不是一种选择。我正在编写一个需要在旧的 Windows 7 机器上运行的脚本。
-
请发布您的
Download-File和Download-FileWget的内容 -
Powershell 不会松开在位置
$targetFile处创建的文件的句柄 这样做不是 PowerShell 的责任。Download-File负责关闭句柄,它不再计划使用。 -
我已经添加了另外两个函数。如果没有返回响应,我可能必须以某种方式在
Download-File的$response = $request.GetResponse()行中提前终止该函数。此时目标文件尚未打开。
标签: powershell powershell-2.0 webclient