我有以下代码:
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0A00
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <iostream>
#pragma comment(lib, "winhttp.lib")
int wmain(int argc, wchar_t* argv[]) {
if (argc != 2) {
std::wcerr << L"Parameters: <Domain>" << std::endl;
return 1;
}
// Get proxy settings
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ProxyConfig;
ZeroMemory(&ProxyConfig, sizeof(ProxyConfig));
if (!WinHttpGetIEProxyConfigForCurrentUser(&ProxyConfig)) {
std::wcerr << L"WinHttpGetIEProxyConfigForCurrentUser failed, error: "
<< GetLastError() << std::endl;
return 1;
}
if (ProxyConfig.lpszProxy != NULL) {
// Check bypass list
if (ProxyConfig.lpszProxyBypass != NULL) {
wchar_t* domain = wcstok(ProxyConfig.lpszProxyBypass, L";");
while (domain != NULL) {
if (wcscmp(domain, argv[1]) == 0) {
std::wcout << L"Proxy Bypass" << std::endl;
GlobalFree(ProxyConfig.lpszProxy);
GlobalFree(ProxyConfig.lpszProxyBypass);
return 0;
}
domain = wcstok(NULL, L";");
}
GlobalFree(ProxyConfig.lpszProxyBypass);
}
std::wcout << L"Proxy: " << ProxyConfig.lpszProxy << std::endl;
GlobalFree(ProxyConfig.lpszProxy);
return 0;
}
// Set AUTOPROXY options
WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions;
ZeroMemory(&AutoProxyOptions, sizeof(AutoProxyOptions));
if (ProxyConfig.fAutoDetect) {
AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
AutoProxyOptions.dwAutoDetectFlags =
WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
}
if (ProxyConfig.lpszAutoConfigUrl != NULL) {
AutoProxyOptions.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
AutoProxyOptions.lpszAutoConfigUrl = ProxyConfig.lpszAutoConfigUrl;
}
if (AutoProxyOptions.dwFlags == NULL) {
std::wcout << L"No Proxy" << std::endl;
return 0;
}
AutoProxyOptions.fAutoLogonIfChallenged = TRUE;
// Create WinHTTP session
HINTERNET hSession = WinHttpOpen(
L"Windows",
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0
);
if (hSession == NULL) {
std::wcerr << L"WinHttpOpen failed, error: "
<< GetLastError() << std::endl;
return 1;
}
// Get proxy info from PAC
std::wstring wurl = L"http://" + (std::wstring)argv[1] + L"/";
WINHTTP_PROXY_INFO ProxyInfo;
ZeroMemory(&ProxyInfo, sizeof(ProxyInfo));
if (!WinHttpGetProxyForUrl(
hSession,
wurl.c_str(),
&AutoProxyOptions,
&ProxyInfo
)) {
std::wcerr << L"WinHttpGetProxyForUrl failed, error: "
<< GetLastError() << std::endl;
WinHttpCloseHandle(hSession);
return 1;
}
// ProxyInfo.lpszProxy contains the address of the proxy server
if (ProxyInfo.lpszProxy != NULL) {
std::wcout << L"Proxy: " << ProxyInfo.lpszProxy << std::endl;
GlobalFree(ProxyInfo.lpszProxy);
} else {
std::wcout << L"Proxy: NULL" << std::endl;
}
// Cleanup
if (ProxyConfig.lpszAutoConfigUrl != NULL) {
GlobalFree(ProxyConfig.lpszAutoConfigUrl);
}
WinHttpCloseHandle(hSession);
return 0;
}
它使用
WinHttpGetProxyForUrl
函数根据系统设置检索 PAC 文件中指定的代理服务器地址。
WinHttpGetProxyForUrl
函数执行成功,没有返回错误,但给定的ProxyInfo.lpszProxy
变量值始终为空。
以下是我使用的原始PAC文件的内容:
var pHost = "Proxy.local";
var pPort = "1080";
var Socks5 = "SOCKS5 " + pHost + ":" + pPort + "; ";
var Socks = "SOCKS " + pHost + ":" + pPort + "; ";
var Direct = "DIRECT; ";
function FindProxyForURL(url, host) {
if (shExpMatch(dnsResolveEx(host), "*.*.*.*")) {
return Socks5 + Socks + Direct;
} else {
return Direct;
}
}
以下是始终返回代理服务器的 PAC 文件的简化版本:
function FindProxyForURL(url, host) {
return "SOCKS Proxy.local:1080";
}
我都尝试过,但是
ProxyInfo.lpszProxy
变量仍然为空。
我的代码是否存在问题,或者
WinHttpGetProxyForUrl
函数是否表现出意外行为?
我已经重现了您的问题。 ProxyInfo.lpszProxy 为 NULL 的原因是您在 WinHttpGetProxyForUrl 函数中设置了错误的 lpcwszUrl 地址。
您应该将其设置为被代理的目标的地址。而不是服务器代理地址。 那么输出指针不为NULL。
在我的pac文件中,我使用localhost:8000来代理baidu.com。
function FindProxyForURL(url, host) {
if (shExpMatch(url, "*baidu.com*")){
return "PROXY localhost:8000; DIRECT";
}else{
return "DIRECT";
}
}