起初使用的方法是修改完一次代理之后就不能继续修改,需要重新启动一次进程才可以,最初代码是:
private void ShowProxyInfo() { if (!GetProxyStatus()) { lblInitInfo.Text = "代理未启用:"; } else { lblInitInfo.Text = "当前使用的代理是:" + GetProxyServer(); } } private void InitProxyData() { List<string> proxyList = new List<string>{ "http://web-proxy.cup.hp.com:8080","http://proxy.compaq.com:8080" }; combProxyList.DataSource = proxyList; combProxyList.SelectedIndex = 0; } public void SetProxy(string proxy) { //打开注册表 //RegistryKey regKey = Registry.CurrentUser; //string SubKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; //RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true); //更改健值,设置代理, //optionKey.SetValue("ProxyEnable", 1); //optionKey.SetValue("ProxyServer", proxy); ////激活代理设置【用于即使IE没有关闭也能更新当前打开的IE中的代理设置。】 //InternetSetOption(0, 39, IntPtr.Zero, 0); //InternetSetOption(0, 37, IntPtr.Zero, 0); //regKey.Flush(); //刷新注册表 //regKey.Close(); //ShowProxyInfo(); using (RegistryKey regKey = Registry.CurrentUser) { string SubKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true); //更改健值,设置代理 optionKey.SetValue("ProxyEnable", 1); optionKey.SetValue("ProxyServer", proxy); //激活代理设置【用于即使IE没有关闭也能更新当前打开的IE中的代理设置。】 InternetSetOption(0, 39, IntPtr.Zero, 0); InternetSetOption(0, 37, IntPtr.Zero, 0); regKey.Flush(); //刷新注册表 ShowProxyInfo(); } } public void DisableProxy() { //打开注册表 RegistryKey regKey = Registry.CurrentUser; string SubKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true); //更改健值,设置代理, optionKey.SetValue("ProxyEnable", 0); regKey.Flush(); //刷新注册表 InternetSetOption(0, 39, IntPtr.Zero, 0); InternetSetOption(0, 37, IntPtr.Zero, 0); regKey.Close(); ShowProxyInfo(); } [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); private void btnSetProxy_Click(object sender, EventArgs e) { string proxyStr = combProxyList.Text.Trim(); SetProxy(proxyStr); var currentProxy = GetProxyServer(); if (currentProxy == proxyStr && GetProxyStatus()) { lblInfo.Text = "设置代理:" + proxyStr + "成功!"; lblInfo.ForeColor = Color.Green; } else { if (!GetProxyStatus()) { lblInfo.Text = "设置代理:" + proxyStr + "代理未启用!"; } else { lblInfo.Text = "设置代理:" + proxyStr + "失败,正在使用" + currentProxy + "代理,请重试!"; } lblInfo.ForeColor = Color.Red; } ShowProxyInfo(); } /// <summary> /// 获取正在使用的代理 /// </summary> /// <returns></returns> private string GetProxyServer() { //打开注册表 RegistryKey regKey = Registry.CurrentUser; string SubKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true); //更改健值,设置代理, string actualProxy = optionKey.GetValue("ProxyServer").ToString(); regKey.Close(); return actualProxy; } private bool GetProxyStatus() { //打开注册表 RegistryKey regKey = Registry.CurrentUser; string SubKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true); //更改健值,设置代理, int actualProxyStatus = Convert.ToInt32(optionKey.GetValue("ProxyEnable")); regKey.Close(); return actualProxyStatus == 1 ? true : false; } //成功返回true,错误返回false public Boolean prcessBaidu() { HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create("http://www.163.com"); myRequest.Method = "POST"; //采用post方式提交访问163主页 // Get response try//当无法访问163网站时,下面的对象会有错误产生,所以用try..catch处理掉这些异常 { Stream newStream = myRequest.GetRequestStream();//获取请求流 // Send the data. newStream.Close();//关闭请求流 HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();//获取应答对象 StreamReader reader = new StreamReader(myResponse.GetResponseStream());//获取应答流 string content = reader.ReadToEnd();//将流对象读取到string 中 if (content.IndexOf("http://reg.163.com") > -1)//如果访问网站成功,则网页中包含置顶的关键字符串“http://reg.163.com”表示访问网页成功 { return true; } else { return false; } } catch (Exception ex) { return false; } return false; } private void btnDisableProxy_Click(object sender, EventArgs e) { DisableProxy(); if (!GetProxyStatus()) { lblInfo.Text = "取消代理完成!"; lblInfo.ForeColor = Color.Green; } else { lblInfo.Text = "取消失败,正在使用代理" + GetProxyServer(); lblInfo.ForeColor = Color.Red; } ShowProxyInfo(); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { } private void btnTestProxy_Click(object sender, EventArgs e) { string proxyStr = combProxyList.SelectedText; SetProxy(proxyStr); if (prcessBaidu()) { MessageBox.Show("代理可以正常访问。"); } else { MessageBox.Show("目前无法使用代理!"); } ShowProxyInfo(); }
有网友的结果是说在window7下, 在一个进程中, 设置和取消不能都执行,---- 要么设置,要么取消。 但如果第一次运行时,只进行设置代理,退出后再进运行,只进行取消,这是没有问题的。简单说说他给出的解决方案:每次设置或取消代理时,都新建一个进程,在新的进程中处理,处理完之后关掉进程。参考http://blog.csdn.net/debug__boy/article/details/8432879提供新的解决方案,国外大神的文章http://huddledmasses.org/setting-windows-internet-connection-proxy-from-c/:代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace IEProxyManagment { public class IEProxySetting { 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); } }
UnsetProxy方法为取消代理设置,SetProxy(string strProxy, string exceptions)方法为设置指定代理。
以下是我做的一个可以动态修改代理的Winform程序,备忘下载。