WinINet InternetGetProxyInfo:错误 1003 ERROR_CAN_NOT_COMPLETE

Posted

技术标签:

【中文标题】WinINet InternetGetProxyInfo:错误 1003 ERROR_CAN_NOT_COMPLETE【英文标题】:WinINet InternetGetProxyInfo : error 1003 ERROR_CAN_NOT_COMPLETE 【发布时间】:2011-10-21 09:19:09 【问题描述】:

我正在尝试使应用程序与 WinINet 库提供的 自动代理 API 兼容,以便制作本地 pac 文件工作,并在尝试调用 InternetGetProxyInfo 时遇到错误 ERROR_CAN_NOT_COMPLETE...

我一直在关注 here 中 Eric Loewenthal(开发者@Microsoft,所以我希望他的建议是 A-OK ;p)的帖子 这个想法应该是:

调用InternetInitializeAutoProxyDll函数; 调用 InternetGetProxyInfo 以获取每个给定请求 URL 的代理 URL; 最后调用 InternetDeInitializeAutoProxyDll。

这是我的代码的样子:

// Start by initializing the Auto proxy stuff
BOOL ok = InternetInitializeAutoProxyDll(0, pathToTheProxyPACFile, 
                                         NULL, NULL, NULL);
// Here ok is true so I consider the initialization was a success

// [...]

// Later on, I try to get the proxy used for each requested URL like this:
LPSTR proxyURL = NULL;
DWORD proxyURLLength = 0;
BOOL ok = InternetGetProxyInfo(requestedURL,
                               requestedURLLength,
                               hostName,
                               hostNameLength,
                              &proxyURL,
                              &proxyURLLength);
// Here ok is false, the proxy url and length are left as is, 
// and a call to GetLastError() returns 1003 :s

我看不出有什么问题,在网上找不到任何令人信服的例子(而且文档严重缺乏......)。

请注意,我尝试为 proxyURL 分配缓冲区并将其大小设置为 proxyURLLength,因为文档不清楚应如何处理内存,但它不起作用,我的理解是我应该让 WinINet 处理它无论如何,如果成功,请在 proxyURL 上使用 GlobalFree。

我还尝试使用 InternetCrackUrlA 来获取主机名,以防万一我用来从请求的 URL 获取主机名的类与此 API 不兼容(实际上,InternetCrackUrlA 认为端口是主机名...),但它也没有帮助。

请让我知道任何可能有助于我让它工作的建议;)

PS:我一直在使用 WinHTTP 在代码的同一部分执行相同的操作,并且它可以正常工作。 PPS:我正在安装 IE8 的 Windows XP 上进行测试。

编辑 ==========> 我编写了另一个只调用这些函数的程序,在这种情况下我没有遇到任何问题,所以我想我的问题不是来自我调用的方式InternetGetProxyInfo 但从我调用它时的状态来看,即在 the event sink used for our embedded IE 的实现,除非我的包含或类似的东西有问题..?

【问题讨论】:

你看到的和我一样吗=>“这不被支持。”?我偶然发现了几个这样的页面,但我认为这是因为 msdn 上的文档严重缺乏,而不是因为该功能真的不支持:) 哦...您知道使本地代理 pac 文件正常工作的另一种方法吗?因为 MSDN 说它不适用于 WinHTTP(它应该是更好的 WinINet 但根本不能使用本地路径>_>)。 IE 可以使用本地 pac 文件,所以应该有可用的东西!?虽然我认为它使用 WinINet... 【参考方案1】:

WinHTTP 不应该是更好的 WinINet,引用 [MSDN][1]:

Microsoft Windows HTTP 服务 (WinHTTP) 面向需要访问 HTTP 客户端堆栈的中间层和后端服务器应用程序。 Microsoft Windows Internet (WinINet) 为客户端应用程序提供 HTTP 客户端堆栈,以及对文件传输协议 (FTP)、SOCKSv4 和 Gopher 协议的访问。 http://msdn.microsoft.com/en-us/library/windows/desktop/aa384068(v=vs.85).aspx

如果你真的想使用 WinHTTP,你绝对可以在动态加载“jsproxy.dll”时让它工作,然后按照here 的描述使用这个动态加载的 DLL 中的 InternetGetProxyInfo。

要完全支持复杂 PAC 文件的解析,您必须实现所有(或至少大部分)“自动代理回调函数”并将函数指针数组传递给动态加载的 InternetInitializeAutoProxyDll 函数动态链接库。

除此之外,请注意,您必须处理代理身份验证的部分质询/响应处理(“域代理”除外),因为 WinHTTP 不会自动处理 407 代理密码质询并选择最佳身份验证方案作为WinINet 可以。这也是相当多的手动工作。

如果我真的不能使用 WinINet,我只会付出相当大的努力。

【讨论】:

感谢您的回答,但我不确定我是否完全理解:我一直在使用 WinHTTP 处理 pac 文件,它与 FindProxyForURL 函数一起工作非常简单(请参阅 msdn.microsoft.com/en-us/library/windows/desktop/…) .我对 WinHTTP 的问题是它不适用于本地地址(如上一个链接所述,“WinHTTP 仅支持“http:”和“https:”PAC URL;例如,它不支持“file:” URLS.",所以据我所知,我唯一的其他选择是使用 WinINet,因此将 InternetGetProxyInfo 与 jsproxy.dll 一起使用,但失败:s 这个答案让我注意到了 WinHTTP 和 WinINet 之间的真正区别。谢谢! msdn.microsoft.com/en-us/library/windows/desktop/… 说,“除了少数例外,WinINet 是 WinHTTP 的超集。在两者之间进行选择时,您应该使用 WinINet,除非您计划在需要模拟和会话隔离的服务或类似服务的进程中运行。” 【参考方案2】:

在确保它适用于新项目后,我追踪了问题的原因,并且在调用 OleInitialize 后,获取代理信息的调用开始失败。现在,here 中有一条关于它的评论,但我不知道这家伙在说什么(上帝知道我希望我永远不知道)所以当我第一次阅读它时它并没有帮助我。

简而言之,如果您使用 OleInitialize 初始化 COM,您将拥有一个“单线程单元”线程,这意味着 InternetGetProxyInfo 将失败并出现神秘错误 ERROR_CAN_NOT_COMPLETE。我使用的解决方案是让另一个线程完成这项工作。

PS关于InternetGetProxyInfo的签名:

看来最后两个参数应该按我的预期设置为 NULL 和 0,如果需要,应该在字符串上调用 GlobalFree 以释放其内存。

主机名和主机名长度是可选的。

感谢您的帮助:)

【讨论】:

其实主机名和主机名长度不是可选的。或者确切地说,它们在 XP 上是可选的,但在 Win7 上是必需的。否则我得到一个可怕的 ERROR_CAN_NOT_COMPLETE

以上是关于WinINet InternetGetProxyInfo:错误 1003 ERROR_CAN_NOT_COMPLETE的主要内容,如果未能解决你的问题,请参考以下文章

WinInet - 没有 Internet Explorer 就无法工作?

以编程方式清除 WinInet DNS 缓存

Delphi - 使用 Wininet 下载文件?

Wininet 缓存包装器

Wininet上传文件TCHAR问题

Delphi 中用于 FTP 的 WinInet 包装器