10

I know that I can change the computers global proxy setting, Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings, to affect IE instances created using Watin.

But is there any way to intercept requests made by the IE browsers and run them through a proxy? My goal is to run multiple instances of IE, each with its own proxy, which isn't possible with my current solution above.

Fedor
  • 1,548
  • 3
  • 28
  • 38
Johan
  • 35,120
  • 54
  • 178
  • 293

6 Answers6

4

WatiN IE creates multiple ProcessIDs (single instance IE creates multiple process ids). in order to overwrite proxy settings just for WatiN by using Fiddler Core we need to get all child process ids which are created by WatiN IE. Helper class can be found here PInvoke: Getting all child handles of window – Svett Ralchev class. And then we check all process ids inside the BeforeRequest event and wait for watin process id to overwrite proxy settings.

    private void FiddlerApplication_BeforeRequest(Session sess)
    {
        //Debug.WriteLine("FiddlerApplication_BeforeRequest: " + sess.LocalProcessID.ToString());
        if (WatinIEprocessHolder.ContainsKey(sess.LocalProcessID))
        {                
            //see http://stackoverflow.com/questions/14284256/how-to-manually-set-upstream-proxy-for-fiddler-core
            sess["X-OverrideGateway"] = WatinIEprocessHolder[sess.LocalProcessID];
        }
    } 

Working Test Application can be downloaded here http://www.rentanadviser.com/downloads/WatiN-2.1.0.1196.zip

Test results with different anonymous proxy below. (ipaddress=browser.Text)

Process Ids:3852,7852,, Your IP address: 119.46.110.17, Proxy:119.46.110.17:8080
Process Ids:2508,6948,, Your IP address: 178.21.112.27, Proxy:178.21.112.27:3128
Process Ids:1348,1368,, Your IP address: 122.96.59.107, Proxy:122.96.59.107:83
Process Ids:7152,5104,, Your IP address: 136.0.16.217, Proxy:136.0.16.217:3127
Process Ids:4128,3480,, Your IP address: 198.52.199.152, Proxy:198.52.199.152:7808
Process Ids:2036,7844,, Your IP address: 122.96.59.107, Proxy:122.96.59.107:82

Sample code:

    private void this_FormClosing(object sender, FormClosingEventArgs e)
    {
        StopFiddler();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        this.FormClosing += this_FormClosing;

        ProxyHolder = new List<string>();
        ProxyHolder.Add("119.46.110.17:8080");
        ProxyHolder.Add("178.21.112.27:3128");
        ProxyHolder.Add("122.96.59.107:83");
        ProxyHolder.Add("136.0.16.217:3127");
        ProxyHolder.Add("198.52.199.152:7808");
        ProxyHolder.Add("122.96.59.107:82");

        StartFiddler();
        System.Threading.Thread.Sleep(500);

        for (var i = 0; i < ProxyHolder.Count; i++)
        {
            WhatIsMyIpThroughProxy(ProxyHolder[i]);
            Application.DoEvents();
            System.Threading.Thread.Sleep(500);
        }
        //WhatIsMyIpThroughProxy();
    }

    private Dictionary<int, string> WatinIEprocessHolder = new Dictionary<int, string>();
    private List<string> ProxyHolder = null;

    public void WhatIsMyIpThroughProxy(string ProxyIPandPort)
    {

        using (var browser = new IE(true))// we should not navigate now. Because we need process ids.
        {
            WindowHandleInfo ChildHandles = new WindowHandleInfo(browser.hWnd);
            foreach (var cHandle in ChildHandles.GetAllChildHandles())
            {
                int pid = new WatiN.Core.Native.Windows.Window(cHandle).ProcessID;
                if (WatinIEprocessHolder.ContainsKey(pid) == false)
                    WatinIEprocessHolder.Add(pid, ProxyIPandPort);
            }

            System.Text.StringBuilder processIDs = new System.Text.StringBuilder();
            foreach (var k in WatinIEprocessHolder.Keys)
            {
                processIDs.Append(k.ToString() + ",");
                //Debug.WriteLine(string.Format("{0}:{1}", k, WatinIEprocessHolder[k]));
            }

            //we got the process ids above. Navigate now.
            browser.GoTo("http://www.rentanadviser.com/en/common/tools.ashx?action=whatismyip");
            browser.WaitForComplete();

            WatinIEprocessHolder.Clear();

            System.Net.IPAddress ip;
            if (System.Net.IPAddress.TryParse(browser.Text, out ip))
            {
                Debug.WriteLine(string.Format("Process Ids:{0}, Your IP address: {1}, Proxy:{2}", processIDs.ToString(), browser.Text, ProxyIPandPort));
            }
            else
            {
                Debug.WriteLine(string.Format("Process Ids:{0}, Your IP address: {1}, Proxy:{2}", processIDs.ToString(), "Failed", ProxyIPandPort));
            }
        }
    }


    private void StartFiddler()
    {
        FiddlerApplication.BeforeRequest += FiddlerApplication_BeforeRequest;
        FiddlerApplication.Startup(8888, true, true, true);
    }

    private void StopFiddler()
    {
        FiddlerApplication.BeforeRequest -= FiddlerApplication_BeforeRequest;
        if (FiddlerApplication.IsStarted())
        {
            FiddlerApplication.Shutdown();
        }
    }


    private void FiddlerApplication_BeforeRequest(Session sess)
    {
        //Debug.WriteLine("FiddlerApplication_BeforeRequest: " + sess.LocalProcessID.ToString());
        if (WatinIEprocessHolder.ContainsKey(sess.LocalProcessID))
        {                
            //see http://stackoverflow.com/questions/14284256/how-to-manually-set-upstream-proxy-for-fiddler-core
            sess["X-OverrideGateway"] = WatinIEprocessHolder[sess.LocalProcessID];
        }
    }    
khan
  • 4,479
  • 1
  • 15
  • 9
  • I haven't had time to try this yet, but I will reward you since it's the closest to what I'm asking for. Thanks! – Johan Aug 14 '14 at 07:59
  • Btw, your sample project only contains a WaitiN solution – Johan Aug 14 '14 at 09:11
  • inside the **WatiN.sln** vs2010 version contains **WatinTest** solution. You maybe need to update ip-proxy list because they might down. when proxy is anonymous your ip seems as proxy ip. – khan Aug 14 '14 at 09:24
  • Yea, but I'm getting errors when I try to open it. Might be because I'm using VS 2012? But it's ok - I can create a new one. – Johan Aug 14 '14 at 10:47
  • By the way, do you happen to know how to modify the request headers? They don't seem to change for me, even though I modify them in `FiddlerApplication_BeforeRequest` – Johan Aug 14 '14 at 11:13
  • inside the **BeforeRequest** adding **sess.oRequest["NewHeaderName"] = "New header value";** may help. Documentation here [Modifying a Request or Response with fiddler](http://docs.telerik.com/fiddler/knowledgebase/fiddlerscript/modifyrequestorresponse), to change existing header use **sess["ExistingHeaderName"] = "New header value";** – khan Aug 14 '14 at 11:38
  • another useful info here [Modifying All Request Headers in Fiddler](http://emtunc.org/blog/03/2014/modifying-all-request-headers-in-fiddler/) – khan Aug 14 '14 at 11:46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59353/discussion-between-khan-and-johan). – khan Aug 14 '14 at 12:25
3

I've created an app called Process Proxifier which uses FiddlerCore to add proxy settings to the Windows applications dynamically. You can find its full source code here: https://processproxifier.codeplex.com/

Also I should mention that this solution is limited to target processes with system's default "CERN" proxy setting (which is pointed at Fiddler/FiddlerCore).

VahidN
  • 18,457
  • 8
  • 73
  • 117
  • in windows 7 **Process Proxifier** requires **run as administrator** because inside the **ProcessesListManager** you call **process.MainModule.FileName** to get process exe path. Windows vista and later **process.MainModule.FileName** requires run as administrator. to prevent this add [ProcessFileNameFinderClass](http://stackoverflow.com/questions/25113693/c-sharp-how-to-check-if-browser-is-open) to **Process Proxifier** and inside the **ProcessesListManager** class you should change the **process.MainModule.FileName;** line to **ProcessFileNameFinderClass.GetProcessExecutablePath(process);** – khan Aug 14 '14 at 09:53
2

It's not possible to do that with IE or even with WebBrowser (it's just an instance of IE).

But you can manipute WebBrowser behavior to achieve your desired feature.

It's possible to write your custom WebBrowser which fetched data by sending your custom WebRequest that contain your different proxy.

How to load web browser with web response

HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://example.com");
webRequest.Proxy = new WebProxy(host, port);

HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
Stream receiveStream = response.GetResponseStream();

WebBrowser webBrowser = new WebBrowser();
webBrowser.DocumentStream = receiveStream;   

WebRequest.Proxy

Community
  • 1
  • 1
Hiệp Lê
  • 636
  • 4
  • 8
  • 1
    Thanks, this might work for a `WebBrowser`. How how to integrate it with an `IE` instance created using WaitN? – Johan Aug 06 '14 at 12:20
  • You can write a new class derived from WatiN.Core.Browser and use your custom WebBrowser instead of running InternetExplorer.exe This, of course, means write code in WatIn. – Hiệp Lê Aug 06 '14 at 15:42
  • 1
    problem with this is all the other requests made after the document stream is loaded will not use the proxy. – dmportella Aug 08 '14 at 08:11
  • It could, the demo is plainly simple. For a complete solution, we need to override all requests from the Custom WebBrowser. – Hiệp Lê Aug 11 '14 at 04:52
2

I know you are looking for an alternative solution without using the computers global proxy setting but I thought of adding this here so others who don't have this constraint know about it.

The solution was on your question - The Windows Registry.

It is simple to change the proxy settings globally at runtime, you need to change the registry keys you are interested in using the Microsoft.Win32.Registry class in the Microsoft.Win32 namespace.

You can find MSDN documentation for this here: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry(v=vs.110).aspx

See below an example of how to do this.

RegistryKey myKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Your key", true);

myKey.SetValue("My String Value", "Test Value", RegistryValueKind.String);

Now to change proxy settings on the box you need to change or create the right proxy registry keys you can find all the available keys at:

Below is a few of the keys you need to set. Each version of IE has their own keys but the ones below are identical to all browsers.

UseProxyServer REG_DWORD

  • HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable

ProxyServerAndPort REG_DWORD

  • HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer

ProxyOverride REG_SZ

  • HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyOverride

HTTP1_1ThroughProxy REG_DWORD

  • HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\HTTP1_1ThroughProxy

User Specific

Please bear in mind these are Current user registry entries so you may need to set them in the context of the windows identity. Also the simplest way to see what should be the values for these keys is to apply the proxy changes on the Internet Settings dialog and check them on RegEdit.exe.

Create user automatically

This is your saving grace here because you can run your process for watin on a local windows account with the settings that way you dont need to change your own proxy settings.

You can then have one user called WatinUser that the proxy settings are set against you can automate the creation of this user using the System.DirectoryServices.AccountManagement Namespace classses.

Community
  • 1
  • 1
dmportella
  • 4,614
  • 1
  • 27
  • 44
2

There are products like Proxifier that let you setup rules to route traffic to different proxies based on application names, IP addresses, hostnames and port numbers. This would not let you use different proxies for multiple IE processes, but if those processes were accessing different URLs you could route the traffic through separate proxy servers. Proxifier works using the WinSocks stack, similar to what many antivirus use, and it is transparent to the application layer.

Greg Bray
  • 14,929
  • 12
  • 80
  • 104
1

Another suggestion is to write your own web request interceptor/proxy server that will grab proxy server info from requested url and forward normalized url to the real proxy server. for e.g. from watin you launch url "someurl?ProxyServer=10.10.10.12" now this will be intercepted by your own proxy server and it will use the proxy server param to redirect requested url i.e. "someurl" to 10.10.10.12 your proxy server implementation can set proxy details at run time and fetch the results from your server using dynamic proxy.

I hope it makes some sense.

Gurpreet
  • 1,382
  • 11
  • 24