简体   繁体   English

在 windows 7 上使用 powershell 2.0 下载文件 - 来自 Microsoft

[英]Downloading files with powershell 2.0 on windows 7 - From Microsoft

I'm trying to automate the download of MSE definition files from Microsoft using powershell on Win7.我正在尝试在 Win7 上使用 powershell 自动从 Microsoft 下载 MSE 定义文件。 I'm looking for a poweshell script that will do this.我正在寻找可以执行此操作的 poweshell 脚本。

I cannot use the Windows Update service or BITS service as both of these are disabled to prevent the OS from automatically downloading updates that break the computer.我不能使用 Windows 更新服务或 BITS 服务,因为这两者都被禁用以防止操作系统自动下载破坏计算机的更新。 MSE uses the update service to get new definitions. MSE 使用更新服务来获取新定义。

I have a script (below) working for regular files hosted using https.我有一个脚本(如下)适用于使用https托管的常规文件。 EG https://www.7-zip.org/a/7z1604.exe EG https://www.7-zip.org/a/7z1604.exe

When I use a Microsoft download URL ( https://go.microsoft.com/fwlink/?linkid=87341 ), the script fails with this error:当我使用 Microsoft 下载 URL ( https://go.microsoft.com/fwlink/?linkid=87341 ) 时,脚本失败并出现以下错误:

Exception calling "DownloadFile" with "2" argument(s): "The underlying connecti on was closed: An unexpected error occurred on a send."使用“2”参数调用“DownloadFile”的异常:“底层连接已关闭:发送时发生意外错误。” At C:\temp\run.ps1:9 char:40在 C:\temp\run.ps1:9 char:40

Microsoft don't use regular https or ftp file links for some reason.出于某种原因,Microsoft 不使用常规的 https 或 ftp 文件链接。 I don't know what sort of link they use, but they don't work with the script below.我不知道他们使用什么样的链接,但他们不适用于下面的脚本。 It's not a https certificate problem either.这也不是 https 证书问题。 Files from https sources work just fine: https 来源的文件工作得很好:

$url = "https://go.microsoft.com/fwlink/?linkid=87341" 
$path = "C:\temp\update.exe" 
# param([string]$url, [string]$path) 

if(!(Split-Path -parent $path) -or !(Test-Path -pathType Container (Split-Path -parent $path))) { 
$targetFile = Join-Path $pwd (Split-Path -leaf $path) 
} 

(New-Object Net.WebClient).DownloadFile($url, $path) 
$path

I got the above script from this link: Downloading files with powershell 2.0 on windows 7我从这个链接得到了上面的脚本: Downloading files with powershell 2.0 on windows 7

I'm missing something obvious.我错过了一些明显的东西。 Any suggestions appreciated.任何建议表示赞赏。

Thanks.谢谢。

This code appears to do the trick:这段代码似乎可以解决问题:

$download = Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=87341"
$FileName = $download.BaseResponse.ResponseUri.Segments[-1]

$file = [System.IO.FileStream]::new("$PSScriptRoot\$FileName", [System.IO.FileMode]::Create)
$file.Write($download.Content, 0, $download.RawContentLength)
$file.Close()

From Matthew Hodgkins blog , and killingtime's link we get:从 Matthew Hodgkins 博客和 killtime 的链接我们得到:

$download = Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=87341"

But Hodgkins's code tries to use Content-Disposition , which does not exist in $download .但是 Hodgkins 的代码尝试使用$download中不存在的Content-Disposition Looking through $download I eventually found that $download.BaseResponse.ResponseUri gives us a Uri.通过$download我最终发现$download.BaseResponse.ResponseUri给了我们一个 Uri。 Searching around for getting a filename from a Uri eventually led me to Lee_Dailey's use of Segments[-1] , giving us:搜索从 Uri 获取文件名最终导致我Lee_Dailey使用Segments[-1] ,给我们:

$FileName = $download.BaseResponse.ResponseUri.Segments[-1]

As for a file destination, in my case I wanted it to be the same folder as the script, so $PSScriptRoot was used to make a small change to Hodgkins's example.至于文件目标,在我的情况下,我希望它与脚本位于同一个文件夹,因此使用$PSScriptRoot对 Hodgkins 的示例进行了一些小改动。

$file = [System.IO.FileStream]::new("$PSScriptRoot\$FileName", [System.IO.FileMode]::Create)
$file.Write($download.Content, 0, $download.RawContentLength)
$file.Close()

This function, which works in both PS v5.1 and PS v7.2.x, uses Invoke-WebRequest for downloading Microsoft links of the format https://go.microsoft.com/fwlink/?linkid=idNumber by first checking if the file name can be retrieved from Content-Disposition (As described in Matthew Hodgkins blog ), and, if that fails, then attempts to extract the file name from BaseResponse by determining its type and extracting the URI from the appropriate location.此 function 可在 PS v5.1 和 PS v7.2.x 中使用,使用Invoke-WebRequest下载格式https://go.microsoft.com/fwlink/?linkid=idNumber的 Microsoft 链接,首先检查是否可以从Content-Disposition中检索文件名(如 Matthew Hodgkins 博客中所述),如果失败,则通过确定其类型并从适当位置提取 URI 来尝试从BaseResponse中提取文件名。

If the code fails to determine the file name, it attempts to save the file with the file name Dowloaded.File , but this isn't tested and shouldn't be trusted.如果代码无法确定文件名,它会尝试使用文件名Dowloaded.File保存文件,但这未经测试且不应被信任。 Throwing an error is likely.可能会抛出错误。

NOTE: While this does work for the 3 example links in the code, the nature of this code is such that one should expect it to work for some links while failing for others.注意:虽然这对代码中的 3 个示例链接有效,但此代码的性质是人们应该期望它对某些链接有效,而对其他链接无效。 If anyone finds a failing link, and places it in the comments, I might be able figure how to extract the proper file name and modify the function to deal with it correctly.如果有人发现一个失败的链接,并将其放在评论中,我也许能够弄清楚如何提取正确的文件名并修改 function 以正确处理它。

function Invoke-WebRequestDownload {
    [OutputType([string])]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Uri,
        [Parameter(Mandatory = $false, Position = 1)]
        [string]$OutFile = "$PSScriptRoot\Downloaded.File"
    )
    $FileDownload = Invoke-WebRequest -Uri $Uri
    $FilePath = [System.IO.Path]::GetDirectoryName($OutFile)
    if(-not $FilePath) {$FilePath = $PSScriptRoot}
    $FileName = $null
    if([bool]$FileDownload.Headers['Content-Disposition']) {
        $FileName = [System.Net.Mime.ContentDisposition]::new($FileDownload.Headers["Content-Disposition"]).FileName
    } else {
        switch ($FileDownload.BaseResponse) {
            {$_ -is [System.Net.HttpWebResponse]} {
                $FileName = $FileDownload.BaseResponse.ResponseUri.Segments[-1]
            }
            {$_ -is [System.Net.Http.HttpResponseMessage]} {
                $FileName = $FileDownload.BaseResponse.RequestMessage.RequestUri.Segments[-1]
            }
            Default {
                $FileName = [System.IO.Path]::GetFileName($OutFile)
            }
        }
    }
    if(-not $FileName) {$FileName = 'Downloaded.File'}
    $FileNamePath = Join-Path -Path $FilePath -ChildPath $FileName
    $File = [System.IO.FileStream]::new($FileNamePath, [System.IO.FileMode]::Create)
    $File.Write($FileDownload.Content, 0, $FileDownload.RawContentLength)
    $File.Close()
    Return $FileNamePath
}
$OutFilePath = Invoke-WebRequestDownload -Uri 'https://go.microsoft.com/fwlink/?linkid=87341'
#$OutFilePath = Invoke-WebRequestDownload -Uri 'http://go.microsoft.com/fwlink/?LinkId=393217'
#$OutFilePath = Invoke-WebRequestDownload -Uri 'https://go.microsoft.com/fwlink/?linkid=2109047&Channel=Stable&language=en&consent=1'
$OutFilePath

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM