AsyncHttps.psm1
# TESTING - Hardcode PowerShell to not validate certificates add-type @' 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; } } '@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy # TESTING - Hardcode PowerShell to use insecure protocols if necessary [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12' # Script to run in each thread. [System.Management.Automation.ScriptBlock]$ScriptBlock = { param($dnsName,$path) $uriRoot = New-Object System.UriBuilder('https',$dnsName) $uriRoot.Path = $path $result = New-Object PSObject -Property @{ 'Uri' = $uriRoot.Uri.AbsoluteUri; 'Status' = '00' 'BeginTime' = Get-Date -Format 'yyyy/MM/dd HH:mm:ss.fff' 'EndTime' = Get-Date -Format 'yyyy/MM/dd HH:mm:ss.fff' } try{ $httpResponse = Invoke-WebRequest -Uri $result.Uri if($null -ne $httpResponse) { $result.Status = $httpResponse.StatusCode $result.EndTime = Get-Date -Format 'yyyy/MM/dd HH:mm:ss.fff' $httpResponse.Dispose() } } catch [System.Net.WebException] { $e = $_ $result.EndTime = Get-Date -Format 'yyyy/MM/dd HH:mm:ss.fff' $responseCode = [int]([regex]::Match($e.Exception.Message,'[0-9]{3}')).Value if($responseCode -gt 0){ $result.Status = $responseCode } else { $result.Status = $e.Exception.Message } } catch { $e = $_ $result.EndTime = Get-Date -Format 'yyyy/MM/dd HH:mm:ss.fff' $result.Status = $e.Exception.Message } finally { if($null -ne $httpResponse) { $httpResponse.Dispose() } if($result.Status -eq '00') { $result.EndTime = Get-Date -Format 'yyyy/MM/dd HH:mm:ss.fff' } } return $result } # End $ScriptBlock function Invoke-AsyncHttps { <# .SYNOPSIS Uses Runspaces to issue async http requests. .EXAMPLE Invoke-AsyncHttps -DnsName www.contoso.com -UriPaths $('dir1','dir2','dir3') #> [CmdletBinding()] param( [parameter(Mandatory=$true)] [ValidateScript({Resolve-DnsName $_})] [System.String] # DNS name of target website $DnsName , [parameter(Mandatory=$true)] [System.String[]] # Uri Paths to request. $UriPaths , [parameter(Mandatory=$false)] [ValidateRange(3,10000)] [System.Int32] # Max number of threads for RunspacePool. $MaxThreads = 10 , [parameter(Mandatory=$false)] [ValidateRange(1,100000)] [System.Int32] # Milliseconds to wait for jobs. $WaitTime = 1000 ) Write-Host '*** WARNING ***' -ForegroundColor Red -BackgroundColor Black Write-Host 'This module is configured to:' -ForegroundColor Red -BackgroundColor Black Write-Host ' 1) Ignore invalid certificates' -ForegroundColor Red -BackgroundColor Black Write-Host " 2) Ignore insecure protocols`n" -ForegroundColor Red -BackgroundColor Black $Start = Get-Date $Results = @() $AllJobs = New-Object System.Collections.ArrayList $HostRunspacePool = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspacePool(2,$MaxThreads,$Host) $HostRunspacePool.Open() Write-Verbose -Message "Submitting async jobs." foreach($uriPath in $UriPaths) { $asyncJob = [System.Management.Automation.PowerShell]::Create().AddScript($ScriptBlock).AddParameter('dnsName',$DnsName).AddParameter('path',$uriPath) $asyncJob.RunspacePool = $HostRunspacePool $asyncJobObj = @{ JobHandle = $asyncJob; AsyncHandle = $asyncJob.BeginInvoke() } $AllJobs.Add($asyncJobObj) | Out-Null } Write-Verbose -Message "Finished submitting async jobs." Write-Verbose -Message "Processing completed jobs." $ProcessingJobs = $true Do { $CompletedJobs = $AllJobs | Where-Object { $_.AsyncHandle.IsCompleted } if($null -ne $CompletedJobs) { foreach($job in $CompletedJobs) { $result = $job.JobHandle.EndInvoke($job.AsyncHandle) if($null -ne $result) { $Results += $result } $job.JobHandle.Dispose() $AllJobs.Remove($job) } } else { if($AllJobs.Count -eq 0) { $ProcessingJobs = $false } else { Start-Sleep -Milliseconds $WaitTime } } Write-Verbose -Message "Jobs in progress $($AllJobs.Count)" } While ($ProcessingJobs) $HostRunspacePool.Close() $HostRunspacePool.Dispose() Write-Verbose -Message "Start $($Start.ToString('yyyy/MM/dd HH:mm:ss.fff'))" Write-Verbose -Message "Finish $(Get-Date -Format 'yyyy/MM/dd HH:mm:ss.fff')" return $Results } # End function Invoke-AsyncHttps |