首先,我想通过修改注册表来设置IE代理。
以下是修改注册表的代码:
- //打开注册表
- Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
- //设置代理
- rk.SetValue("ProxyEnable", 1);
- rk.SetValue("ProxyServer", "8.8.8.8:8000");
- //取消代理
- //rk.SetValue("ProxyEnable", 0);
- rk.Flush(); //刷新注册表
- rk.Close();
然后调用 WinInet API ,激活代理设置。
- [DllImport(@"wininet",
- SetLastError = true,
- CharSet = CharSet.Auto,
- EntryPoint = "InternetSetOption",
- CallingConvention = CallingConvention.StdCall)]
- public static extern bool InternetSetOption(
- int hInternet,
- int dmOption,
- IntPtr lpBuffer,
- int dwBufferLength
- );
- void SetProxy() {
- //打开注册表
- Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
- //设置代理
- rk.SetValue("ProxyEnable", 1);
- rk.SetValue("ProxyServer", "8.8.8.8:8000");
- //取消代理
- //rk.SetValue("ProxyEnable", 0);
- rk.Flush(); //刷新注册表
- rk.Close();
- //激活代理设置
- InternetSetOption(0, 39, IntPtr.Zero, 0);
- InternetSetOption(0, 37, IntPtr.Zero, 0);
- }
到这里,应该能成功设置代理了,但是问题出现了,无法正常设置代理。
我的系统是Win7 专业版,在网上搜了一遍后发现,有人说这段代码在XP下能work,win7下会失效。
有人还发现:在window7下, 在一个进程中, 设置和取消不能都执行,---- 要么设置,要么取消。 但如果第一次运行时,只进行设置代理,退出后再进运行,只进行取消,这是没有问题的。
简单说说他给出的解决方案:每次设置或取消代理时,都新建一个进程,在新的进程中处理,处理完之后关掉进程。
这种方法可以work,但显得很蛋疼。
所以我没采用这种方法。
最后,找着国外一大神 的一篇文章Setting Windows internet connection proxy from C#
试了一下,完美解决。
代码如下:
- using System;
- using System.Runtime.InteropServices;
- using System.ComponentModel;
- namespace PoshHttp
- {
- public class Proxies
- {
- public static bool UnsetProxy()
- {
- return SetProxy(null, null);
- }
- public static bool SetProxy(string strProxy)
- {
- return SetProxy(strProxy, null);
- }
- public static bool SetProxy(string strProxy, string exceptions)
- {
- InternetPerConnOptionList list = new InternetPerConnOptionList();
- int optionCount = string.IsNullOrEmpty(strProxy) ? 1 : (string.IsNullOrEmpty(exceptions) ? 2 : 3);
- InternetConnectionOption[] options = new InternetConnectionOption[optionCount];
- // USE a proxy server ...
- options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS;
- options[0].m_Value.m_Int = (int)((optionCount < 2) ? PerConnFlags.PROXY_TYPE_DIRECT : (PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY));
- // use THIS proxy server
- if (optionCount > 1)
- {
- options[1].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_SERVER;
- options[1].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(strProxy);
- // except for these addresses ...
- if (optionCount > 2)
- {
- options[2].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS;
- options[2].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(exceptions);
- }
- }
- // default stuff
- list.dwSize = Marshal.SizeOf(list);
- list.szConnection = IntPtr.Zero;
- list.dwOptionCount = options.Length;
- list.dwOptionError = 0;
- int optSize = Marshal.SizeOf(typeof(InternetConnectionOption));
- // make a pointer out of all that ...
- IntPtr optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length);
- // copy the array over into that spot in memory ...
- for (int i = 0; i < options.Length; ++i)
- {
- IntPtr opt = new IntPtr(optionsPtr.ToInt32() + (i * optSize));
- Marshal.StructureToPtr(options[i], opt, false);
- }
- list.options = optionsPtr;
- // and then make a pointer out of the whole list
- IntPtr ipcoListPtr = Marshal.AllocCoTaskMem((Int32)list.dwSize);
- Marshal.StructureToPtr(list, ipcoListPtr, false);
- // and finally, call the API method!
- int returnvalue = NativeMethods.InternetSetOption(IntPtr.Zero,
- InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,
- ipcoListPtr, list.dwSize) ? -1 : 0;
- if (returnvalue == 0)
- { // get the error codes, they might be helpful
- returnvalue = Marshal.GetLastWin32Error();
- }
- // FREE the data ASAP
- Marshal.FreeCoTaskMem(optionsPtr);
- Marshal.FreeCoTaskMem(ipcoListPtr);
- if (returnvalue > 0)
- { // throw the error codes, they might be helpful
- throw new Win32Exception(Marshal.GetLastWin32Error());
- }
- return (returnvalue < 0);
- }
- }
- #region WinInet structures
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct InternetPerConnOptionList
- {
- public int dwSize; // size of the INTERNET_PER_CONN_OPTION_LIST struct
- public IntPtr szConnection; // connection name to set/query options
- public int dwOptionCount; // number of options to set/query
- public int dwOptionError; // on error, which option failed
- //[MarshalAs(UnmanagedType.)]
- public IntPtr options;
- };
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct InternetConnectionOption
- {
- static readonly int Size;
- public PerConnOption m_Option;
- public InternetConnectionOptionValue m_Value;
- static InternetConnectionOption()
- {
- InternetConnectionOption.Size = Marshal.SizeOf(typeof(InternetConnectionOption));
- }
- // Nested Types
- [StructLayout(LayoutKind.Explicit)]
- public struct InternetConnectionOptionValue
- {
- // Fields
- [FieldOffset(0)]
- public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime;
- [FieldOffset(0)]
- public int m_Int;
- [FieldOffset(0)]
- public IntPtr m_StringPtr;
- }
- }
- #endregion
- #region WinInet enums
- //
- // options manifests for Internet{Query|Set}Option
- //
- public enum InternetOption : uint
- {
- INTERNET_OPTION_PER_CONNECTION_OPTION = 75
- }
- //
- // Options used in INTERNET_PER_CONN_OPTON struct
- //
- public enum PerConnOption
- {
- INTERNET_PER_CONN_FLAGS = 1, // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags
- INTERNET_PER_CONN_PROXY_SERVER = 2, // Sets or retrieves a string containing the proxy servers.
- INTERNET_PER_CONN_PROXY_BYPASS = 3, // Sets or retrieves a string containing the URLs that do not use the proxy server.
- INTERNET_PER_CONN_AUTOCONFIG_URL = 4//, // Sets or retrieves a string containing the URL to the automatic configuration script.
- }
- //
- // PER_CONN_FLAGS
- //
- [Flags]
- public enum PerConnFlags
- {
- 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
- }
- #endregion
- internal static class NativeMethods
- {
- [DllImport("WinInet.dll", SetLastError = true, CharSet = CharSet.Auto)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool InternetSetOption(IntPtr hInternet, InternetOption dwOption, IntPtr lpBuffer, int dwBufferLength);
- }
- }
开源代码:
https://github.com/NoNeil/ProxySetting