在C#中使用Wininet设置代理用户名和密码

这是Stack Overflow中的第一个问题。 我从这个网站得到了很大的帮助。

我正在使用.NET 2010上的C#应用​​程序。我正在尝试为http请求设置系统范围的代理服务器。 Proxy Server是基于Squid的代理,启用了“基本”身份validation。 我已经能够设置IE的代理。

现在在IE中设置代理后,IE要求代理的用户名和密码,现在我正在尝试自动执行此function,并且在过去的一周内我一直无法使其工作并且一直在搜索互联网但仍然没有成功。

下面是我用来设置IE代理的代码。

public static bool SetProxy(string strProxy, string username, string password, 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  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  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); } 

任何有助于使此function正常工作的帮助将不胜感激。

此致,Mudasir Mirza。

当您为WinINET设置代理时,无法存储所有客户端将从中受益的“全局”代理用户名和密码。 您只能基于每个进程缓存此用户名/密码。 在此过程中,您可以使用InternetSetOption API提供用户名和密码。 这只会设置WinINET的密码,而不是.NET或其他HTTP堆栈的密码。

看一下WebProxy类,看看是否允许你做你想做的事情?

以下列方式使用它(我将假设exception由’;’分隔):

 public static void SetProxy(string proxyAddress, string userName, string password, string exceptions) { var credential = new NetworkCredential(userName, password); string[] bypassList = null; if (!string.IsNullOrEmpty(exceptions)) { bypassList = exceptions.Split(';'); } WebRequest.DefaultWebProxy = new WebProxy(proxyAddress, true, bypassList, credential); } 

调用方法:

 SetProxy("http://proxy:8080", "user", "password", "http://site1;http://site2"); 

在处理身份validation和恼人的“Windows安全”窗口时,我遇到了与WebBrowser控件类似的问题。 首先,使用WinINET设置代理地址,然后使用您的凭据调用navigate方法。 它有助于为每个进程存储代理凭据:

 WebBrowser.Navigate("http://user:pass@geoip.hidemyass.com/"); 

WinINET方法设置完美的代理地址,但是您的代码使用INTERNET_OPTION_PER_CONNECTION_OPTION ,这不适合您的“全局代理”想法(如@EricLaw所述)。 尝试使用INTERNET_OPTION_PROXY ( documentaion )

此外,有四种不同的方法 ,没有直接的解决方案。 但它们非常方便。