在C中使用Wininet设置代理用户名和密码#
这是我在Stack Overflow中的第一个问题。我从这个网站得到了很大的帮助。在C中使用Wininet设置代理用户名和密码#
我正在使用.NET 2010上的C#应用程序。我试图为http请求设置系统范围的代理服务器。 代理服务器是启用了“基本”身份验证的基于Squid的代理服务器。 我已经能够设置IE的代理。
现在,在IE中设置代理后,IE为代理请求用户名和密码,现在我试图自动执行此功能,并且在过去的一周内,我一直无法使其工作,并且一直在搜索互联网,但是仍然没有成功。
下面是我用来设置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 < 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);
}
任何帮助获得此功能的工作将不胜感激。
Regards, Mudasir Mirza。
看看WebProxy课程,看看是否允许你做你想做的事?
使用它通过以下方式(我要去假设异常被分开的“;”):
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");
嗨,我也试过这个课,但没有成功。 – 2012-02-17 09:17:06
我用一个例子更新了它,它对你有用吗? – 2012-02-17 09:31:29
嗨@TrevorPilley有没有办法改变'ProxyEnable'复选框。 – Scorpion 2012-02-17 12:20:41
当您设置WinINET的代理,无法存储所有客户都能从中受益的“全局”代理用户名和密码。您只能按进程缓存该用户名/密码。在此过程中,您可以使用InternetSetOption API提供用户名和密码。这将只设置WinINET的密码,而不是.NET或其他HTTP堆栈。
我在处理认证和刺激“Windows安全”窗口时遇到了与WebBrowser控件类似的问题。首先,用WinINET设置代理地址,然后用您的凭据调用导航方法。它有助于存储每一个进程代理凭据:
WebBrowser.Navigate("http://user:[email protected]/");
的WinINET方法设置代理服务器地址完美的,但你的代码使用INTERNET_OPTION_PER_CONNECTION_OPTION
这是不适合你的“全球代理”的想法(如@EricLaw说的)。尝试解决与INTERNET_OPTION_PROXY
(documentaion)
此外有four different approaches没有直接的解决方案。但他们非常方便。
由于您将指针转换为32位,因此您的代理设置代码无法在64位计算机上使用。 – EricLaw 2012-08-17 21:01:58