使用代理通过 HTTP 下载 Powershell 并检查第二个文件的远程文件大小失败

使用代理通过 HTTP 下载 Powershell 并检查第二个文件的远程文件大小失败

我正在开发一个 powershell 脚本,它将通过代理从 HTTP 服务器下载文件并在服务器上包含 UN/PW。

我的文件下载得很好,但有些文件非常大,所以我添加了一个函数来检查文件是否已更改(检查大小)。这在第一个文件上有效。但它在第二个文件的这一行超时了:

$test = $wc2.OpenRead($source) | Out-Null)

我的脚本代码(不包括凭证)如下所示。如果您能提供建议,告诉我如何正确关闭连接(我怀疑没有发生这种情况),或者如何使用 Powershell 通过 HTTP 获取远程文件的大小,我将不胜感激。

Function getWebClient {
    $webClient = new-object System.Net.WebClient 

    $pxy = new-object System.Net.WebProxy $proxy  
    $pxy.Credentials = New-Object System.Net.NetworkCredential ("tnad\$proxy_un", "$proxy_pw") 
    $webClient.proxy=$pxy  
    $webClient.Headers.Add("user-agent", "Windows Powershell WebClient Header") 

    $WebClient.Credentials = New-Object System.Net.Networkcredential($un, $pw)

    return $WebClient
}

foreach ($ds in $datasetsTest) {
    Write-Host "Checking: $ds"
    $source = "$server$ds"
    $dest = "$destFolder$ds"

    #Test whether the destination file already exists, if it exists, compare file sizes.
    $destExists = Test-Path $dest

    if($destExists -eq $false) {
        Try {
            $wc1 = getWebClient
            $wc1.DownloadFile($source, $dest)
            $wc1.Dispose()
            Write-Host "File downloaded"  -foregroundcolor "green"
        } Catch {
            Write-Host "Downloading $ds failed..." -foregroundcolor "red"
        }
    } else {
        $localFileSize = (Get-Item $dest).length
        $wc2 = getWebClient
        $test = $wc2.OpenRead($source) | Out-Null
        $wc2.Dispose()

        $remoteFileSize = $wc2.ResponseHeaders["Content-Length"]

        Write-Host "Local file size: $localFileSize, remote file size: $remoteFileSize"
        if(!($localFileSize -eq $remoteFileSize)) {
            #file exists, but the server version changed...
            Try {
                Remove-Item $dest
                $wc3 = getWebClient
                $wc3.DownloadFile($source, $dest) 
                $wc3.Dispose($true)
                Write-Host "File downloaded"  -foregroundcolor "green"
            } Catch {
                Write-Host "Downloading $ds failed..." -foregroundcolor "red"
            }
        } else {
            Write-Host "Skipping, file exists and hasn't changed"  -foregroundcolor "magenta"
        }
    }
}

答案1

我无法就这个特定问题本身发表评论,但我想提供一些一般性建议。过去几年,我编写了一些非常关键的 PS 代码,其中一些通过 HTTPS 与远程遥测设备交互。这些代码要么成功,要么失败,并且日志记录非常详细。这些代码虽然在 Windows VM 中运行,但被视为“嵌入式系统/设备”。

我真诚地建议在脚本中添加错误处理代码。诚然,互联网上充斥着 PowerShell 代码的 bang-bang-bang 示例,每个后续步骤都假设前一个步骤成功。过度使用 PS 管道有时会使情况变得更糟,例如:enumerate-something | foreach-object{ do-something },其中一些 do-something 会失败,这意味着您经常处于无法回滚的境地。

好了,废话不多说了。建议:

  1. 启用严格模式。这将防止任何无意的类型转换/强制转换。使用正确的类型定义预先声明变量。
  2. 尽可能使用 -erroraction silentlyContinue,并使用“if ($?)”检查捕获错误...或使用 try{} catch{} 结构包装生成异常的调用。并非所有 PS 函数都会引发异常!
  3. 写入大量日志数据
  4. 识别更有可能失败的操作并尽可能编写重试逻辑。

我就到此为止!

祝你好运。

答案2

您的问题是由于 $test 变量被分配了一个空值。

当你建立变量 $test

$test = $wc2.OpenRead($source) | Out-Null

“| Out-Null”部分使结果为空,导致将 null 分配给 $test,将其删除,这样就不会出现问题了。

关于您关于关闭 System.Net.WebClient 连接的问题,顺便说一下:您无需采取行动,所有 HTTP 连接都会在需要时关闭,并且不会干扰建立第二个连接。打开持久连接将允许在与同一 URL 的后续连接上更及时、更高效地建立连接。有关持久 HTTP 连接的更多信息,请参见这里

相关内容