如何在不影响 SYSTEM/IE 代理的情况下为 Webbrowser Control 设置代理

Posted

技术标签:

【中文标题】如何在不影响 SYSTEM/IE 代理的情况下为 Webbrowser Control 设置代理【英文标题】:How to set a proxy for Webbrowser Control without effecting the SYSTEM/IE proxy 【发布时间】:2011-01-30 18:30:05 【问题描述】:

如何在不为 IE 设置代理的情况下为 Webbrowser Control 设置代理?

基本上我希望我的应用程序使用某个代理,但是显然我不想更改用户的 IE 代理设置。

【问题讨论】:

嗨@dr。邪恶!你找到任何解决方案吗?如果是,请分享,我面临着类似的问题。 您可以拦截每个请求并通过代理手动发送:***.com/questions/9035911/… 看看我的answer here对你有没有帮助。 @dr.evil 查看答案:***.com/questions/28717411/… -- 让我知道它是否有帮助:) 【参考方案1】:

试试 UrlMkSetSessionOption INTERNET_OPTION_PROXY 和 UrlMkSetSessionOption INTERNET_OPTION_REFRESH

如果您的代理有密码认证,您可能需要在您的 WebBrowserSiteBase 派生类中实现 IAuthenticate(Ex)。

【讨论】:

这听起来很不错,现在我只需要处理 Webbrowser 控制 COM 的疯狂了! :) 谢谢。【参考方案2】:

我在网上看到了一些可怕的解决方案。大多数涉及为整台机器设置代理,然后将其关闭。这是一个类,它允许您仅为控件所在的进程设置它。您可以这样调用它:

WinInetInterop.SetConnectionProxy(“localhost:8888”);

然后通过此调用将其恢复为 IE 中的默认设置:

// 读取 IE 的默认设置并将其恢复为代理

WinInetInterop.RestoreSystemProxy();

如果您认为这很有用,请告诉我!

上市:

using System;
using System.Runtime.InteropServices;


namespace SetProxy

    public static class WinInetInterop
    
        public static string applicationName;

            [DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
            private static extern IntPtr InternetOpen(
                string lpszAgent, int dwAccessType, string lpszProxyName,
                string lpszProxyBypass, int dwFlags);

            [DllImport("wininet.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool InternetCloseHandle(IntPtr hInternet);

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            private struct INTERNET_PER_CONN_OPTION_LIST
            
                public int Size;

                // The connection to be set. NULL means LAN.
                public System.IntPtr Connection;

                public int OptionCount;
                public int OptionError;

                // List of INTERNET_PER_CONN_OPTIONs.
                public System.IntPtr pOptions;
            
            private enum INTERNET_OPTION
            
                // Sets or retrieves an INTERNET_PER_CONN_OPTION_LIST structure that specifies
                // a list of options for a particular connection.
                INTERNET_OPTION_PER_CONNECTION_OPTION = 75,

                // Notify the system that the registry settings have been changed so that
                // it verifies the settings on the next call to InternetConnect.
                INTERNET_OPTION_SETTINGS_CHANGED = 39,

                // Causes the proxy data to be reread from the registry for a handle.
                INTERNET_OPTION_REFRESH = 37

            

            private enum INTERNET_PER_CONN_OptionEnum
            
                INTERNET_PER_CONN_FLAGS = 1,
                INTERNET_PER_CONN_PROXY_SERVER = 2,
                INTERNET_PER_CONN_PROXY_BYPASS = 3,
                INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
                INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5,
                INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6,
                INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7,
                INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8,
                INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9,
                INTERNET_PER_CONN_FLAGS_UI = 10
            
            private const int INTERNET_OPEN_TYPE_DIRECT = 1;  // direct to net
            private const int INTERNET_OPEN_TYPE_PRECONFIG = 0; // read registry
            /// <summary>
            /// Constants used in INTERNET_PER_CONN_OPTON struct.
            /// </summary>
            private enum INTERNET_OPTION_PER_CONN_FLAGS
            
                PROXY_TYPE_DIRECT = 0x00000001,   // direct to net
                PROXY_TYPE_PROXY = 0x00000002,   // via named proxy
                PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,   // autoproxy URL
                PROXY_TYPE_AUTO_DETECT = 0x00000008   // use autoproxy detection
            

            /// <summary>
            /// Used in INTERNET_PER_CONN_OPTION.
            /// When create a instance of OptionUnion, only one filed will be used.
            /// The StructLayout and FieldOffset attributes could help to decrease the struct size.
            /// </summary>
            [StructLayout(LayoutKind.Explicit)]
            private struct INTERNET_PER_CONN_OPTION_OptionUnion
            
                // A value in INTERNET_OPTION_PER_CONN_FLAGS.
                [FieldOffset(0)]
                public int dwValue;
                [FieldOffset(0)]
                public System.IntPtr pszValue;
                [FieldOffset(0)]
                public System.Runtime.InteropServices.ComTypes.FILETIME ftValue;
            

            [StructLayout(LayoutKind.Sequential)]
            private struct INTERNET_PER_CONN_OPTION
            
                // A value in INTERNET_PER_CONN_OptionEnum.
                public int dwOption;
                public INTERNET_PER_CONN_OPTION_OptionUnion Value;
            
            /// <summary>
            /// Sets an Internet option.
            /// </summary>
            [DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
            private static extern bool InternetSetOption(
                IntPtr hInternet,
                INTERNET_OPTION dwOption,
                IntPtr lpBuffer,
                int lpdwBufferLength);

            /// <summary>
            /// Queries an Internet option on the specified handle. The Handle will be always 0.
            /// </summary>
            [DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true,
                EntryPoint = "InternetQueryOption")]
            private extern static bool InternetQueryOptionList(
                IntPtr Handle,
                INTERNET_OPTION OptionFlag,
                ref INTERNET_PER_CONN_OPTION_LIST OptionList,
                ref int size);

            /// <summary>
            /// Set the proxy server for LAN connection.
            /// </summary>
            public static bool SetConnectionProxy(string proxyServer )
            

                IntPtr hInternet = InternetOpen(applicationName,INTERNET_OPEN_TYPE_DIRECT, null, null, 0);

                //// Create 3 options.
                //INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[3];

                // Create 2 options.
                INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[2];

                // Set PROXY flags.
                Options[0] = new INTERNET_PER_CONN_OPTION();
                Options[0].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS;
                Options[0].Value.dwValue = (int)INTERNET_OPTION_PER_CONN_FLAGS.PROXY_TYPE_PROXY;

                // Set proxy name.
                Options[1] = new INTERNET_PER_CONN_OPTION();
                Options[1].dwOption =
                    (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER;
                Options[1].Value.pszValue = Marshal.StringToHGlobalAnsi(proxyServer);

                //// Set proxy bypass.
                //Options[2] = new INTERNET_PER_CONN_OPTION();
                //Options[2].dwOption =
                //    (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_BYPASS;
                //Options[2].Value.pszValue = Marshal.StringToHGlobalAnsi("local");

                //// Allocate a block of memory of the options.
                //System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0])
                //    + Marshal.SizeOf(Options[1]) + Marshal.SizeOf(Options[2]));

                // Allocate a block of memory of the options.
                System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0])
                    + Marshal.SizeOf(Options[1]));

                System.IntPtr current = buffer;

                // Marshal data from a managed object to an unmanaged block of memory.
                for (int i = 0; i < Options.Length; i++)
                
                    Marshal.StructureToPtr(Options[i], current, false);
                    current = (System.IntPtr)((int)current + Marshal.SizeOf(Options[i]));
                

                // Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
                INTERNET_PER_CONN_OPTION_LIST option_list = new INTERNET_PER_CONN_OPTION_LIST();

                // Point to the allocated memory.
                option_list.pOptions = buffer;

                // Return the unmanaged size of an object in bytes.
                option_list.Size = Marshal.SizeOf(option_list);

                // IntPtr.Zero means LAN connection.
                option_list.Connection = IntPtr.Zero;

                option_list.OptionCount = Options.Length;
                option_list.OptionError = 0;
                int size = Marshal.SizeOf(option_list);

                // Allocate memory for the INTERNET_PER_CONN_OPTION_LIST instance.
                IntPtr intptrStruct = Marshal.AllocCoTaskMem(size);

                // Marshal data from a managed object to an unmanaged block of memory.
                Marshal.StructureToPtr(option_list, intptrStruct, true);

                // Set internet settings.
                bool bReturn = InternetSetOption(hInternet,
                    INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION, intptrStruct, size);

                // Free the allocated memory.
                Marshal.FreeCoTaskMem(buffer);
                Marshal.FreeCoTaskMem(intptrStruct);
                InternetCloseHandle(hInternet);

                // Throw an exception if this operation failed.
                if (!bReturn)
                
                    throw new ApplicationException(" Set Internet Option Failed!");
                

                return bReturn;
            




            /// <summary>
            /// Backup the current options for LAN connection.
            /// Make sure free the memory after restoration. 
            /// </summary>
            private static INTERNET_PER_CONN_OPTION_LIST GetSystemProxy()
            

                // Query following options. 
                INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[3];

                Options[0] = new INTERNET_PER_CONN_OPTION();
                Options[0].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS;
                Options[1] = new INTERNET_PER_CONN_OPTION();
                Options[1].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER;
                Options[2] = new INTERNET_PER_CONN_OPTION();
                Options[2].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_BYPASS;

                // Allocate a block of memory of the options.
                System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0])
                    + Marshal.SizeOf(Options[1]) + Marshal.SizeOf(Options[2]));

                System.IntPtr current = (System.IntPtr)buffer;

                // Marshal data from a managed object to an unmanaged block of memory.
                for (int i = 0; i < Options.Length; i++)
                
                    Marshal.StructureToPtr(Options[i], current, false);
                    current = (System.IntPtr)((int)current + Marshal.SizeOf(Options[i]));
                

                // Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
                INTERNET_PER_CONN_OPTION_LIST Request = new INTERNET_PER_CONN_OPTION_LIST();

                // Point to the allocated memory.
                Request.pOptions = buffer;

                Request.Size = Marshal.SizeOf(Request);

                // IntPtr.Zero means LAN connection.
                Request.Connection = IntPtr.Zero;

                Request.OptionCount = Options.Length;
                Request.OptionError = 0;
                int size = Marshal.SizeOf(Request);

                // Query internet options. 
                bool result = InternetQueryOptionList(IntPtr.Zero,
                    INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
                    ref Request, ref size);
                if (!result)
                
                    throw new ApplicationException(" Set Internet Option Failed! ");
                

                return Request;
            

            /// <summary>
            /// Restore the options for LAN connection.
            /// </summary>
            /// <param name="request"></param>
            /// <returns></returns>
            public static bool RestoreSystemProxy()
            

                IntPtr hInternet = InternetOpen(applicationName, INTERNET_OPEN_TYPE_DIRECT, null, null, 0);

                INTERNET_PER_CONN_OPTION_LIST request = GetSystemProxy();
                int size = Marshal.SizeOf(request);

                // Allocate memory. 
                IntPtr intptrStruct = Marshal.AllocCoTaskMem(size);

                // Convert structure to IntPtr 
                Marshal.StructureToPtr(request, intptrStruct, true);

                // Set internet options.
                bool bReturn = InternetSetOption(hInternet,
                    INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
                    intptrStruct, size);

                // Free the allocated memory.
                Marshal.FreeCoTaskMem(request.pOptions);
                Marshal.FreeCoTaskMem(intptrStruct);

                if (!bReturn)
                
                    throw new ApplicationException(" Set Internet Option Failed! ");
                

                // Notify the system that the registry settings have been changed and cause
                // the proxy data to be reread from the registry for a handle.
                InternetSetOption(hInternet, INTERNET_OPTION.INTERNET_OPTION_SETTINGS_CHANGED,
                    IntPtr.Zero, 0);
                InternetSetOption(hInternet, INTERNET_OPTION.INTERNET_OPTION_REFRESH,
                    IntPtr.Zero, 0);

                InternetCloseHandle(hInternet);

                return bReturn;
            

    

http://blogs.msdn.com/b/jpsanders/archive/2011/04/26/how-to-set-the-proxy-for-the-webbrowser-control-in-net.aspx

【讨论】:

【参考方案3】:
    public struct Struct_INTERNET_PROXY_INFO
    
        public int dwAccessType;
        public IntPtr proxy;
        public IntPtr proxyBypass;
    ;

    [DllImport("wininet.dll", SetLastError = true)]
    public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int lpdwBufferLength);

    //to activate use like this strProxy="85.45.66.25:3633"
    //to deactivate use like this strProxy=":"
    public static void RefreshIESettings(string strProxy)
    
        try
        
            const int INTERNET_OPTION_PROXY = 38;
            const int INTERNET_OPEN_TYPE_PROXY = 3;

            Struct_INTERNET_PROXY_INFO struct_IPI;

            // Filling in structure 
            struct_IPI.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
            struct_IPI.proxy = Marshal.StringToHGlobalAnsi(strProxy);
            struct_IPI.proxyBypass = Marshal.StringToHGlobalAnsi("local");

            // Allocating memory 
            IntPtr intptrStruct = Marshal.AllocCoTaskMem(Marshal.SizeOf(struct_IPI));

            // Converting structure to IntPtr 
            Marshal.StructureToPtr(struct_IPI, intptrStruct, true);

            bool iReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY, intptrStruct, Marshal.SizeOf(struct_IPI));
        
        catch (Exception ex)
        

            //TB.ErrorLog(ex);
        
    

[1]https://social.msdn.microsoft.com/Forums/fr-FR/f4dc3550-f213-41ff-a17d-95c917bed027/webbrowser-control-for-setting-proxy?forum=winforms

【讨论】:

【参考方案4】:

不,你不能。 WebBrowser 控件是 IE。就是下面的IE渲染引擎。基本上 IE.exe 有点像它周围的 UI。

【讨论】:

嗯,WebBrowser 控件允许您覆盖很多东西,我不知道为什么它不支持如此简单明了的要求。有什么聪明的解决方法吗?还是我必须记住用户的代理设置,然后在应用程序完成工作时将其恢复。

以上是关于如何在不影响 SYSTEM/IE 代理的情况下为 Webbrowser Control 设置代理的主要内容,如果未能解决你的问题,请参考以下文章

如何在不影响实时功能的情况下为 React 和 React-native 托管通用的 Firebase 后端代码?

如何在不使用 @Composable 注释的情况下为撰写函数创建扩展?

如何在不重新启动 apache 的情况下为站点重新加载 apache 配置?

如何在不限制其维度的情况下为函数参数指定类型?

如何在不更改标准滑块形状的情况下为 Qslider 手柄重新着色?

如何在不放弃主线程的情况下为 Python 使用 CoreBluetooth