【问题标题】:Change proxy setting for IE instance using Watin使用 Watin 更改 IE 实例的代理设置
【发布时间】:2014-08-03 19:09:31
【问题描述】:

我知道我可以更改计算机全局代理设置 Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings,以影响使用 Watin 创建的 IE 实例。

但是有没有办法拦截 IE 浏览器发出的请求并通过代理运行它们?我的目标是运行多个 IE 实例,每个实例都有自己的代理,这在我上面的当前解决方案中是不可能的。

【问题讨论】:

  • 我认为不使用注册表就无法代理 Internet Explorer。
  • 我想要一个不使用计算机全局代理设置的替代解决方案 - 您是否只需要使用 Watin 和 IE 进行此操作?
  • 也许更好的选择是使用 Selenium 而不是 WatiN :P.

标签: c# asp.net unit-testing watin


【解决方案1】:

WatiN IE 创建多个 ProcessIDs(单个实例 IE 创建多个进程 ID)。为了使用 Fiddler Core 覆盖 WatiN 的代理设置,我们需要获取由 WatiN IE 创建的所有子进程 ID。帮助类可以在这里找到PInvoke: Getting all child handles of window – Svett Ralchev类。然后我们检查 BeforeRequest 事件中的所有进程 id 并等待 watin 进程 id 覆盖代理设置。

    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];
        }
    } 

工作测试应用程序可以在这里下载http://www.rentanadviser.com/downloads/WatiN-2.1.0.1196.zip

下面使用不同匿名代理的测试结果。 (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

示例代码:

    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];
        }
    }    

【讨论】:

  • 我还没有时间尝试这个,但我会奖励你,因为它最接近我的要求。谢谢!
  • 顺便说一句,您的示例项目仅包含 WaitiN 解决方案
  • WatiN.sln vs2010版本里面包含WatinTest解决方案。您可能需要更新 ip-proxy 列表,因为它们可能会关闭。当代理匿名时,您的 ip 似乎是代理 ip。
  • 是的,但是当我尝试打开它时出现错误。可能是因为我使用的是 VS 2012?但没关系 - 我可以创建一个新的。
  • 对了,你知道如何修改请求头吗?尽管我在FiddlerApplication_BeforeRequest 中修改了它们,但它们似乎对我没有改变
【解决方案2】:

我创建了一个名为 Process Proxifier 的应用程序,它使用 FiddlerCore 将代理设置动态添加到 Windows 应用程序。你可以在这里找到它的完整源代码:https://processproxifier.codeplex.com/

我还应该提到,此解决方案仅限于具有系统默认“CERN”代理设置(指向 Fiddler/FiddlerCore)的目标进程。

【讨论】:

  • 在 windows 7 中 Process Proxifier 需要 以管理员身份运行 因为在 ProcessesListManager 中您调用 process.MainModule .FileName 获取进程 exe 路径。 Windows vista 和更高版本的 process.MainModule.FileName 需要以管理员身份运行。为防止这种情况发生,请将 ProcessFileNameFinderClass 添加到 Process Proxifier 并在 ProcessesListManager 类中,您应该将 process.MainModule.FileName; 行更改为 ProcessFileNameFinderClass.GetProcessExecutablePath(process);
【解决方案3】:

IE 甚至 WebBrowser(它只是 IE 的一个实例)都无法做到这一点。

但是您可以操纵 WebBrowser 的行为来实现您想要的功能。

可以编写自定义 WebBrowser,通过发送包含不同代理的自定义 WebRequest 来获取数据。

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

【讨论】:

  • 谢谢,这可能适用于WebBrowser。如何将它与使用 WaitN 创建的IE 实例集成?
  • 您可以编写一个派生自WatiN.Core.Browser 的新类并使用您的自定义WebBrowser 而不是运行InternetExplorer.exe 这当然意味着在WatIn 中编写代码。
  • 这个问题是在加载文档流后发出的所有其他请求都不会使用代理。
  • 可以,演示很简单。对于一个完整的解决方案,我们需要覆盖来自自定义 WebBrowser 的所有请求。
【解决方案4】:

我知道您正在寻找 an alternative solution without using the computers global proxy setting,但我想在此处添加此内容,以便其他没有此限制的人知道。

解决方案就在您的问题上 - The Windows Registry

在运行时全局更改代理设置很简单,您需要使用Microsoft.Win32 命名空间中的Microsoft.Win32.Registry 类更改您感兴趣的注册表项。

您可以在此处找到 MSDN 文档:http://msdn.microsoft.com/en-us/library/microsoft.win32.registry(v=vs.110).aspx

请参阅下面的示例,了解如何执行此操作。

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

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

现在要更改盒子上的代理设置,您需要更改或创建正确的代理注册表键,您可以在以下位置找到所有可用键:

以下是您需要设置的几个键。每个版本的 IE 都有自己的密钥,但下面的密钥对所有浏览器都是相同的。

使用代理服务器 REG_DWORD

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

代理服务器和端口 REG_DWORD

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

代理覆盖 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

用户特定

请记住,这些是当前用户注册表项,因此您可能需要在 Windows 身份的上下文中设置它们。此外,查看这些键的值的最简单方法是在 Internet 设置对话框中应用代理更改并在 RegEdit.exe 上检查它们。

自动创建用户

这是您的可取之处,因为您可以在本地 Windows 帐户上运行您的 watin 进程,而无需更改自己的代理设置。

然后,您可以让一个名为 WatinUser 的用户针对您设置代理设置,然后可以使用 System.DirectoryServices.AccountManagement Namespace 类自动创建该用户。

【讨论】:

    【解决方案5】:

    Proxifier 这样的产品可以让您设置规则,根据应用程序名称、IP 地址、主机名和端口号将流量路由到不同的代理。这不会让您为多个 IE 进程使用不同的代理,但如果这些进程访问不同的 URL,您可以通过单独的代理服务器路由流量。 Proxifier 使用 WinSocks 堆栈工作,类似于许多杀毒软件使用的,并且对应用层是透明的。

    【讨论】:

      【解决方案6】:

      另一个建议是编写自己的 Web 请求拦截器/代理服务器,它将从请求的 url 中获取代理服务器信息并将规范化的 url 转发到真正的代理服务器。 例如从你启动 url "someurl?ProxyServer=10.10.10.12" 现在这将被你自己的代理服务器拦截,它将使用代理服务器参数将请求的 url 即 "someurl" 重定向到 10.10.10.12 你的代理服务器实现可以设置运行时代理详细信息,并使用动态代理从您的服务器获取结果。

      我希望这有点道理。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-23
        • 1970-01-01
        相关资源
        最近更新 更多