When working with PowerShell web requests in corporate environments, you'll often need to route requests through proxy servers. The challenge is dynamically retrieving these settings rather than hardcoding them.
The most reliable method uses .NET's System.Net.WebRequest class. Here's a function that returns the current proxy configuration:
function Get-WebProxy {
$request = [System.Net.WebRequest]::Create("http://www.google.com")
$proxy = $request.Proxy.GetProxy($request.RequestUri)
if ($proxy -ne $request.RequestUri) {
return $proxy.AbsoluteUri
}
else {
Write-Warning "No proxy server detected"
return $null
}
}
$proxy = Get-WebProxy
if ($proxy) {
Invoke-WebRequest -Uri "http://example.com" -Proxy $proxy
}
For Windows systems, proxy settings are stored in the registry. This method reads them directly:
function Get-RegistryProxy {
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
$proxyServer = (Get-ItemProperty -Path $regPath).ProxyServer
if ($proxyServer) {
return "http://$proxyServer"
}
return $null
}
$proxy = Get-RegistryProxy
If your proxy requires authentication, you'll need to include credentials:
$proxyCred = Get-Credential
Invoke-WebRequest -Uri "http://example.com" -Proxy $proxy -ProxyCredential $proxyCred
Consider these additional scenarios when implementing proxy detection:
- PAC file configurations
- Bypass lists
- System-wide vs user-specific settings
# Example with bypass list handling
$bypassList = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings").ProxyOverride
if ($bypassList -and $Uri.Host -in $bypassList.Split(';')) {
# Skip proxy for this host
}
When working with PowerShell web requests (like Invoke-WebRequest
or Invoke-RestMethod
), you often need to configure proxy settings to route traffic through corporate or private proxy servers. The challenge is programmatically detecting and applying these settings.
Windows stores proxy configuration in the registry. Here's how to retrieve it:
function Get-SystemProxy {
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
$proxyServer = (Get-ItemProperty -Path $regPath).ProxyServer
$proxyEnable = (Get-ItemProperty -Path $regPath).ProxyEnable
if ($proxyEnable -eq 1 -and $proxyServer) {
return "http://$proxyServer"
}
return $null
}
$proxy = Get-SystemProxy
if ($proxy) {
Invoke-WebRequest -Uri "http://example.com" -Proxy $proxy
}
Proxy settings can be configured in multiple ways. Here's a more comprehensive approach:
function Get-WebProxy {
# Try IE settings first
$regProxy = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
if ($regProxy.ProxyEnable -eq 1 -and $regProxy.ProxyServer) {
return "http://$($regProxy.ProxyServer)"
}
# Check WinHTTP proxy
try {
$winHttpProxy = netsh winhttp show proxy
if ($winHttpProxy -match "Proxy Server$s$:\s+(.+:\d+)") {
return "http://$($matches[1])"
}
}
catch {}
# Check environment variables
if ($env:HTTP_PROXY) { return $env:HTTP_PROXY }
if ($env:HTTPS_PROXY) { return $env:HTTPS_PROXY }
return $null
}
Once you have the proxy address, you can use it with various PowerShell cmdlets:
$proxy = Get-WebProxy
if ($proxy) {
$params = @{
Uri = "https://api.example.com/data"
Proxy = $proxy
ProxyCredential = [System.Management.Automation.PSCredential]::new("username", (ConvertTo-SecureString "password" -AsPlainText -Force))
}
$response = Invoke-RestMethod @params
}
For authenticated proxies, you'll need to provide credentials:
$cred = Get-Credential -Message "Enter proxy credentials"
$proxy = Get-WebProxy
$webSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$webSession.Proxy = New-Object System.Net.WebProxy($proxy)
$webSession.Proxy.Credentials = $cred.GetNetworkCredential()
Invoke-WebRequest -Uri "https://example.com" -WebSession $webSession
For more control, you can use .NET's WebRequest class:
[System.Net.WebRequest]::GetSystemWebProxy() | Select-Object Address
This returns the system-configured proxy that .NET would use by default.
Always include proper error handling when working with proxies:
try {
$response = Invoke-WebRequest -Uri "https://example.com" -Proxy $proxy -ErrorAction Stop
}
catch [System.Net.WebException] {
if ($_.Exception.Status -eq [System.Net.WebExceptionStatus]::ProxyNameResolutionFailure) {
Write-Warning "Proxy server could not be resolved"
}
elseif ($_.Exception.Status -eq [System.Net.WebExceptionStatus]::ConnectFailure) {
Write-Warning "Could not connect to proxy server"
}
else {
Write-Warning "Web request failed: $_"
}
}