Setting a Proxy without changing your #PowerShell Code

Hardcoding a proxy server is an anti-pattern and you are probably aware of this. But how do you handle it when your PowerShell code is executed in different environment with and without a proxy server. You certainly do not want to add parameters for this because this would only be the beginning. $PSDefaultParameterValues to the rescue!

I bet you already know where to add the proxy server because you see where the code stalls and eventually fails. In most cases, this will be cmdlets like Invoke-WebRequest and Invoke-RestMethod but there are a few more. A quick search for cmdlets with a proxy parameter shows a total of 22 cmdlets:

PS> Get-Command -ParameterName Proxy

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Find-Command                                       1.0.0.1    PowerShellGet
Function        Find-DscResource                                   1.0.0.1    PowerShellGet
Function        Find-Module                                        1.0.0.1    PowerShellGet
Function        Find-RoleCapability                                1.0.0.1    PowerShellGet
Function        Find-Script                                        1.0.0.1    PowerShellGet
Function        Install-Module                                     1.0.0.1    PowerShellGet
Function        Install-Script                                     1.0.0.1    PowerShellGet
Function        Register-PSRepository                              1.0.0.1    PowerShellGet
Function        Save-Module                                        1.0.0.1    PowerShellGet
Function        Save-Script                                        1.0.0.1    PowerShellGet
Function        Set-PSRepository                                   1.0.0.1    PowerShellGet
Function        Update-Module                                      1.0.0.1    PowerShellGet
Function        Update-Script                                      1.0.0.1    PowerShellGet
Cmdlet          Find-Package                                       1.0.0.1    PackageManagement
Cmdlet          Find-PackageProvider                               1.0.0.1    PackageManagement
Cmdlet          Install-Package                                    1.0.0.1    PackageManagement
Cmdlet          Install-PackageProvider                            1.0.0.1    PackageManagement
Cmdlet          Invoke-RestMethod                                  3.1.0.0    Microsoft.PowerShell.Utility
Cmdlet          Invoke-WebRequest                                  3.1.0.0    Microsoft.PowerShell.Utility
Cmdlet          Register-PackageSource                             1.0.0.1    PackageManagement
Cmdlet          Save-Package                                       1.0.0.1    PackageManagement
Cmdlet          Set-PackageSource                                  1.0.0.1    PackageManagement

Instead of modifying all the calls to the listed cmdlets, you can simply tell PowerShell to add a parameter to the required cmdlets using $PSDefaultParameterValues:

PS> $Proxy = 'http://proxy.mydomain.com:3128'
PS> $PSDefaultParameterValues = @{
    'Invoke-WebRequest:Proxy' = $Proxy
    'Invoke-RestMethod:Proxy' = $Proxy
}

If you are already using $PSDefaultParameterValues please add new entries to the hash:

PS> $Proxy = 'http://proxy.mydomain.com:3128'
PS> $PSDefaultParameterValues.Add('Invoke-WebRequest:Proxy', $Proxy)
PS> $PSDefaultParameterValues.Add('Invoke-RestMethod:Proxy', $Proxy)

I recommend you do not add a proxy to all cmdlets using $PSDefaultParameterValues.Add('*:Proxy', 'http://proxy.mydomain.com:3128') because a cmdlet can have such a parameter with a different meaning.

When using $PSDefaultParameterValues all calls to the specified cmdlets will receive the additional parameter as long as they are in the same session and unless they explicitly override the value.

Feedback is always welcome! If you'd like to get in touch with me concerning the contents of this article, please use Twitter.