I think this is the most straightforward method to change the System Proxy settings on a System-wide basis.
Sometimes, a per-connection setting is preferable. See the linked documents in this case.
Use the Registry class to set the required value in the Internet Settings Subkey:
Software\Microsoft\Windows\CurrentVersion\Internet Settings
Then, perform a System notification of the change, using InternetSetOption with the INTERNET_OPTION_SETTINGS_CHANGED
and INTERNET_OPTION_REFRESH
Flags:
(These are flags, but should not be combined in this case)
INTERNET_OPTION_REFRESH
must also be called if INTERNET_OPTION_PER_CONNECTION_OPTION
is used to modify the settings on a per-connection basis.
Declaration of InternetSetOption
and a helper function.
Imports Microsoft.Win32
Imports System.Runtime.InteropServices
Imports System.Security.AccessControl
<SecurityCritical>
<DllImport("wininet.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Friend Shared Function InternetSetOption(hInternet As IntPtr, dwOption As Integer, lpBuffer As IntPtr, dwBufferLength As Integer) As Boolean
End Function
Friend Const INTERNET_OPTION_SETTINGS_CHANGED As Integer = 39
Friend Const INTERNET_OPTION_REFRESH As Integer = 37
<SecuritySafeCritical>
Private Sub InternetSetProxy(ProxyAddress As String, ProxyPort As Integer, UseProxy As Boolean)
Dim keyName As String = "Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Dim KeyValue As Object = ProxyAddress + ":" + ProxyPort.ToString()
Dim InternetSettingsKey As RegistryKey =
Registry.CurrentUser.OpenSubKey(keyName,
RegistryKeyPermissionCheck.ReadWriteSubTree,
RegistryRights.WriteKey)
InternetSettingsKey.SetValue("ProxyServer", KeyValue, RegistryValueKind.String)
InternetSettingsKey.SetValue("ProxyEnable", If(UseProxy, 1, 0), RegistryValueKind.DWord)
InternetSettingsKey.Close()
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0)
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0)
InternetSettingsKey.Dispose()
End Sub
You can test it with Internet Explorer.
If you are using Fiddler, call the helper method with these parameters to use it as the default system proxy:
InternetSetProxy("127.0.0.1", 8888, True)
To disable the Proxy setting, just set the UseProxy
parameter to False
:
InternetSetProxy("127.0.0.1", 8888, False)
Navigate an Internet address as usual:
WebBrowser1.Navigate("https://www.google.com")
A note about the .Net WebBrowser control.
The WebBrowser control uses the current cache (as specified in the Internet Explorer settings) to load visited resources as the pre-defined behavior.
If you enable the Proxy but you can still see the (first) page of a Website, this depends on this default behavior.
If you try to click on a link, this new link will not be reachable, and the message:
The proxy server isn’t responding
will be presented.
This kind of result is not constant, it depends on the cache settings.
Edit:
A way to let the WebBrowser
control Navigate
one or more Internet addresses, using a different Proxy server for each address:
Add an event handler for the WebBrowser
DocumentCompleted event.
When the WebBrowser.Navigate()
method is first called, the event handler will cycle through the list of Proxies (read from a ListBox
control Items
list).
This code supposes that the Proxy list is composed of strings that
include both the address and the port of each Proxy. (e.g.
"127.0.0.1:8888"
for Fiddler).
Here, as in the OP example, the Internet Address is the same for all Proxies (a parameter of the WaitDocumentsComplete()
method), but of course can be read from another List.
Both the DocumentCompleted
Handler and the helper method NavigateNextProxy()
are marked as Asynchronous, thus the UI is not blocked throughout the whole process.
This process can be stopped at any time, using the WebBrowser.Stop() method, or setting the ProxyIndex
field to a negative value.
If the process is interrupted before its natural completion, it's necessary to explicitly remove the Handler, using:
RemoveHandler WebBrowser1.DocumentCompleted, DocumentCompletedHandler
Event Handler declaration and the Wrapper and Helper functions:
Protected Friend DocumentCompletedHandler As WebBrowserDocumentCompletedEventHandler
Private Sub WaitDocumentsComplete(ByVal Address As String, ByVal TimeOutSeconds As Integer)
DocumentCompletedHandler =
Async Sub(s, e)
If WebBrowser1.ReadyState = WebBrowserReadyState.Complete AndAlso ProxyIndex > -1 Then
If (Not WebBrowser1.IsBusy) Then
Dim ProxyParts() As String = ListBox1.GetItemText(ListBox1.Items(ProxyIndex)).Split(":"c)
Await NavigateNextProxy(Address, ProxyParts(0), CInt(ProxyParts(1)), TimeOutSeconds)
ProxyIndex += 1
If ProxyIndex > ProxyIndexMaxValue Then
ProxyIndex = -1
RemoveHandler WebBrowser1.DocumentCompleted, DocumentCompletedHandler
End If
End If
End If
End Sub
AddHandler WebBrowser1.DocumentCompleted, DocumentCompletedHandler
End Sub
Protected Async Function NavigateNextProxy(Address As String, ByVal ProxyAddr As String, ProxyPort As Integer, TimeOutSeconds As Integer) As Task
InternetSetProxy(ProxyAddr, ProxyPort, True)
Await Task.Delay(TimeSpan.FromSeconds(TimeOutSeconds))
If WebBrowser1.IsBusy Then WebBrowser1.Stop()
WebBrowser1.Navigate(Address)
End Function
From a Button.Click()
event, set the Indexes of the first and last Proxy in the List, a Timeout value (in seconds) between each navigation
, and call the wrapper method WaitDocumentsComplete()
, which will initialize the DocumentCompleted
event handler.
To begin the process, initialize the WebBrowser
control with WebBrowser1.Navigate("")
It's also important to suppress the WebBrowser
script error dialog,
otherwise it will compromise the whole procedure.
Private ProxyIndex As Integer = -1
Private ProxyIndexMaxValue As Integer = 0
Private Sub btnForm2_Click(sender As Object, e As EventArgs) Handles btnForm2.Click
ProxyIndex = 0
ProxyIndexMaxValue = ListBox1.Items.Count - 1
Dim BrowsingTimeoutSeconds As Integer = 3
Dim Address As String = "https://www.google.com"
WaitDocumentsComplete(Address, BrowsingTimeoutSeconds)
WebBrowser1.ScriptErrorsSuppressed = True
WebBrowser1.Navigate("")
End Sub