Назад | Перейти на главную страницу

Загрузка Powershell через HTTP с использованием прокси и ошибка проверки размера удаленного файла для второго файла

У меня есть сценарий PowerShell, который я разрабатываю, который будет загружать файлы с HTTP-сервера через прокси и включать UN / PW на сервере.

У меня файлы загружаются нормально, но некоторые файлы очень большие, поэтому я добавил функцию, чтобы проверить, не изменился ли файл (проверка размера). Это работает с первым файлом. Но время ожидания второго файла в этой строке истекает:

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

Код моего сценария, за исключением учетных данных, приведен ниже. Я был бы признателен за совет о том, как правильно закрыть соединение (как я подозреваю, этого не происходит) или о том, как получить размер удаленного файла через HTTP с помощью Powershell.

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"
        }
    }
}

Я не могу комментировать этот конкретный вопрос как таковой, но хотел бы дать несколько общих рекомендаций. За последние несколько лет я написал очень важный код PS, некоторые из которых взаимодействуют с удаленным телеметрическим оборудованием через HTTPS. Этот код должен либо успешно завершиться, либо корректно завершиться с очень подробным ведением журнала. Код, хотя и выполняется на виртуальных машинах Windows, рассматривается как «встроенная система / устройство».

Я искренне рекомендую добавить в ваш скрипт код обработки ошибок. Конечно, в Интернете полно потрясающих примеров кода PowerShell, и каждый последующий шаг предполагает, что предыдущий был успешным. Иногда это усугубляется чрезмерным использованием конвейеров PS, например: enumerate-something | foreach-object {do-something}, где некоторые действия не работают, что означает, что вы часто попадаете в ситуацию невозможного отката.

Во всяком случае, хватит болтовни. Рекомендации:

  1. Включить строгий режим. Это предотвратит любое непреднамеренное приведение / принуждение типов. Предварительно объявите свои переменные с правильными определениями типов.
  2. Используйте -erroraction silentlyContinue там, где это возможно, и перехватывайте ошибки с помощью проверок if ($?) ... или завершайте вызовы, которые генерируют исключения, с помощью конструкций try {} catch {}. Не все функции PS вызывают исключения!
  3. Напишите много данных журнала
  4. Определите действия, которые с большей вероятностью завершатся ошибкой, и запрограммируйте логику повтора, где это возможно.

Я остановлюсь на этом!

Удачи.

Проблема связана с тем, что переменной $ test присвоено нулевое значение.

Когда вы создаете переменную $ test

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

часть "| Out-Null" обнуляет результаты, вызывая присвоение null $ test, удалите его, и у вас не должно быть проблем.

В качестве отступления от вашего вопроса о закрытии соединений System.Net.WebClient: Действие на вашем конце не требуется, все HTTP-соединения закрываются по мере необходимости и не должны мешать установлению второго соединения. Открытое постоянное соединение обеспечит более своевременное и эффективное соединение при последующих подключениях к тому же URL-адресу. Более подробную информацию о постоянных HTTP-соединениях можно найти Вот.