Search code examples
powershellssl-certificateinvoke-webrequest

Unable to download files from a server with unverified certificate


I am trying to download some files from a website that doesn't have a verified SSL certificate. I have used the method explained here to ignore the SSL warning: Ignore SSL warning with powershell downloadstring

###################### Download ###################### 
## download zipped files from WebPage/download (No Valid SSL Certificate)
$myDownloadUrl = 'www.SomeWebPage.com/Download/MyFiles.zip'

## installation folder (always under %appdata%\Company\MyFolder)
$myZipFile = "MyFiles.zip"
$installdir = "\Company\MyFolder\"
$myInstallDir = -join @($env:APPDATA, $installdir)
$myFilePath = -join@($myInstallDir, $myZipFile)

## make sure the folder exists
New-Item -ItemType Directory -Force -Path $myInstallDir

## Skip certificate
$code= @"
        using System.Net;
        using System.Security.Cryptography.X509Certificates;
        public class TrustAllCertsPolicy : ICertificatePolicy {
            public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
                return true;
            }
        }
"@
Add-Type -TypeDefinition $code -Language CSharp
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

echo ">> Downloading the Files..."
Invoke-WebRequest -Uri $myDownloadUrl -OutFile $myFilePath
Start-Sleep -s 2

This works as intended most of the times. However, sometimes it returns an error:

ERROR: Unable to  read data from the transport connection: An existing connection was forcibly closed by the remote host.
ERROR: Exception calling ".ctor" with "3" argument(s): "End of Central Directory record could not be found."

I tried adding something like this to my script, but the issue persisted. I still may get an error once but not the other time. (Source: Invoke-WebRequest SSL fails?)

$AllProtocols = [System.Net.SecurityProtocolType]'Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

Can I do a try-catch routine to make sure the file was downloaded properly before proceeding?

Here's an overview summary of that server


Solution

  • As I explained above, downloading the files sometimes has no issues and sometimes fails. So, I added a try-catch to keep trying until it's successful. This is based on this thread: Catching FULL exception message

    I am not sure what's causing this issue, and would consider this to be a workaround rather than a solution.

    ## set ErrorActionPreference to stop
    $ErrorActionPreferenceBak = $ErrorActionPreference
    $ErrorActionPreference    = 'Stop'
    
    While($True){
        try{
            ## downloading the files
            Invoke-WebRequest -Uri $myDownloadUrl -OutFile $myFilePath
            break
        }
        catch{
            Write-Host "Something failed while downloading the files; trying again"
            Start-Sleep -s 1
        }
        finally{
            ## reset ErrorActionPreference
            $ErrorActionPreference = $ErrorActionPreferenceBak
        }
    }