如何查找浏览器的代理设置?

26

我正在编写一个针对Windows的命令行工具,使用libcurl从互联网下载文件。

显然,当用户处于代理服务器后面时,下载就无法工作,因为需要配置代理。但是我希望我的工具尽可能简单,不必让用户负担配置代理的责任。我的工具甚至没有配置文件,所以用户否则必须在每个命令中传递代理设置,或设置环境变量等,这太麻烦了。

因此我想,每个人的浏览器通常已经设置正确,代理已经配置好了。这对于即使是最基本的用户来说也是真实的,否则“他们的互联网将无法工作”。

所以我想通过查看IE的代理设置来确定是否使用代理。

如何操作?更具体地说:

  • 在Windows中,是否存在一组“代理设置”,由所有浏览器(可能是IE)使用,还是我需要为IE、Firefox、Opera等编写不同的例程?
  • 我知道如果手动配置,则可以直接从适当的注册表位置读取值,但是“自动检测代理服务器”是否也适用?我是否需要费心处理该选项,或者它(几乎)从未使用过?

在人们开始建议替代方案之前:我正在使用C,因此仅限于Win32 API,并且我真的非常想继续使用C和libcurl。


1
在此处找到获取IE代理设置的代码:http://stackoverflow.com/a/12601449/559746 - PTT
4个回答

36
您要查找的功能是WinHttpGetIEProxyConfigForCurrentUser(),详细信息可参考http://msdn.microsoft.com/en-us/library/aa384096(VS.85).aspx。Firefox和Opera默认使用此函数获取代理设置,但您可以针对每个浏览器进行覆盖。不过,最好的做法(也是其他人所做的)是仅获取IE设置并假定它们是正确的,因为它们几乎总是正确的。以下是相关逻辑的示例,您可以根据自己的需求进行调整:
if( WinHttpGetIEProxyConfigForCurrentUser( &ieProxyConfig ) )
{
    if( ieProxyConfig.fAutoDetect )
    {
        fAutoProxy = TRUE;
    }

    if( ieProxyConfig.lpszAutoConfigUrl != NULL )
    {
        fAutoProxy = TRUE;
        autoProxyOptions.lpszAutoConfigUrl = ieProxyConfig.lpszAutoConfigUrl;
    }
}
else
{
    // use autoproxy
    fAutoProxy = TRUE;
}

if( fAutoProxy )
{
    if ( autoProxyOptions.lpszAutoConfigUrl != NULL )
    {
        autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
    }
    else
    {
        autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
        autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
    }

    // basic flags you almost always want
    autoProxyOptions.fAutoLogonIfChallenged = TRUE;

    // here we reset fAutoProxy in case an auto-proxy isn't actually
    // configured for this url
    fAutoProxy = WinHttpGetProxyForUrl( hiOpen, pwszUrl, &autoProxyOptions, &autoProxyInfo );
}

if ( fAutoProxy )
{
    // set proxy options for libcurl based on autoProxyInfo
}
else
{
    if( ieProxyConfig.lpszProxy != NULL )
    {
        // IE has an explicit proxy. set proxy options for libcurl here
        // based on ieProxyConfig
        //
        // note that sometimes IE gives just a single or double colon
        // for proxy or bypass list, which means "no proxy"
    }
    else
    {
        // there is no auto proxy and no manually configured proxy
    }
}

3
这是一个非常好的答案,但很可能也会存在缓存的代理凭据(用户名和密码),这些凭据需要以某种方式转发到代理服务器,我认为使用这种技术无法实现这一点。 - Antony

4

这是一个完整的代码示例,展示如何在C#中调用winhttp.dll库中的WinHttpGetIEProxyConfigForCurrentUser方法。

[TestClass]
public class UnitTest1
{
    [StructLayout(LayoutKind.Sequential)]
    public struct WinhttpCurrentUserIeProxyConfig
    {
        [MarshalAs(UnmanagedType.Bool)]
        public bool AutoDetect;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string AutoConfigUrl;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string Proxy;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string ProxyBypass;

    }

    [DllImport("winhttp.dll", SetLastError = true)]
    static extern bool WinHttpGetIEProxyConfigForCurrentUser(ref WinhttpCurrentUserIeProxyConfig pProxyConfig);

    [TestMethod]
    public void TestMethod1()
    {
        var config = new WinhttpCurrentUserIeProxyConfig();

        WinHttpGetIEProxyConfigForCurrentUser(ref config);

        Console.WriteLine(config.Proxy);
        Console.WriteLine(config.AutoConfigUrl);
        Console.WriteLine(config.AutoDetect);
        Console.WriteLine(config.ProxyBypass);
    }
}

1

当然,您可以直接获取这些值的注册表键。您也可以在 .NET 中轻松完成此操作。我相信 WebClient 对象会根据当前设置为您协商代理设置。在 C# 中,代码应类似于:

using System.Net;

string url = "http://www.example.com";
WebClient client = new WebClient();
byte[] fileBuffer = client.DownloadFile(url);

或者类似于这样的内容。


顺便提一下,您还可以使用同一类来检测代理。它有一个Proxy属性和一个GetProxy()方法。 - justin.m.chase
谢谢,但我正在使用C语言,所以这个不太适用(如果可以避免,我也不想使用COM)。我已经编辑了问题以澄清。 - rix0rrr

0

对于Firefox / Seamonkey来说,由于存在许多配置文件,问题有点棘手。

如果您想假定只有一个配置文件,则只需查找prefs.js。你可以解析network.proxy.type,然后使用它来决定要读取哪些相关值。

我正在为Mozilla准备一些文档,因此请将您的后续问题放在这里(选中wiki框),我会尽力为您提供所需的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接