How do I set TIdHTTP to use IE proxy configuration?
It should be compatible with XP/Vista/Win7 and reliable.
Indy doesn't use Internet Explorer's proxy settings and so you have to get it by yourself, for instance by using InternetQueryOption
function.
Update:
Here is the code using WinHTTP
which should try to receive the settings from IE. If they are available and auto-detect proxy settings or auto-config script URL options are set, then the proxy detection will be performed. Auto-detection will also be performed when the IE settings are not available.
Disclaimer:
The following code has been tested only for the easiest case, when the IE settings are available and the proxy settings are not configured to be detected automatically (don't have the environment). Also please note that some of the functions, structures and constant are additional in this unit.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
HINTERNET = Pointer;
{$EXTERNALSYM HINTERNET}
INTERNET_PORT = Word;
{$EXTERNALSYM INTERNET_PORT}
PWinHTTPProxyInfo = ^TWinHTTPProxyInfo;
WINHTTP_PROXY_INFO = record
dwAccessType: DWORD;
lpszProxy: LPWSTR;
lpszProxyBypass: LPWSTR;
end;
{$EXTERNALSYM WINHTTP_PROXY_INFO}
TWinHTTPProxyInfo = WINHTTP_PROXY_INFO;
LPWINHTTP_PROXY_INFO = PWinHTTPProxyInfo;
{$EXTERNALSYM LPWINHTTP_PROXY_INFO}
PWinHTTPAutoProxyOptions = ^TWinHTTPAutoProxyOptions;
WINHTTP_AUTOPROXY_OPTIONS = record
dwFlags: DWORD;
dwAutoDetectFlags: DWORD;
lpszAutoConfigUrl: LPCWSTR;
lpvReserved: Pointer;
dwReserved: DWORD;
fAutoLogonIfChallenged: BOOL;
end;
{$EXTERNALSYM WINHTTP_AUTOPROXY_OPTIONS}
TWinHTTPAutoProxyOptions = WINHTTP_AUTOPROXY_OPTIONS;
LPWINHTTP_AUTOPROXY_OPTIONS = PWinHTTPAutoProxyOptions;
{$EXTERNALSYM LPWINHTTP_AUTOPROXY_OPTIONS}
PWinHTTPCurrentUserIEProxyConfig = ^TWinHTTPCurrentUserIEProxyConfig;
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG = record
fAutoDetect: BOOL;
lpszAutoConfigUrl: LPWSTR;
lpszProxy: LPWSTR;
lpszProxyBypass: LPWSTR;
end;
{$EXTERNALSYM WINHTTP_CURRENT_USER_IE_PROXY_CONFIG}
TWinHTTPCurrentUserIEProxyConfig = WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
LPWINHTTP_CURRENT_USER_IE_PROXY_CONFIG = PWinHTTPCurrentUserIEProxyConfig;
{$EXTERNALSYM LPWINHTTP_CURRENT_USER_IE_PROXY_CONFIG}
function WinHttpOpen(pwszUserAgent: LPCWSTR; dwAccessType: DWORD;
pwszProxyName, pwszProxyBypass: LPCWSTR; dwFlags: DWORD): HINTERNET; stdcall;
external 'winhttp.dll' name 'WinHttpOpen';
{$EXTERNALSYM WinHttpOpen}
function WinHttpConnect(hSession: HINTERNET; pswzServerName: LPCWSTR;
nServerPort: INTERNET_PORT; dwReserved: DWORD): HINTERNET; stdcall;
external 'winhttp.dll' name 'WinHttpConnect';
{$EXTERNALSYM WinHttpConnect}
function WinHttpOpenRequest(hConnect: HINTERNET; pwszVerb: LPCWSTR;
pwszObjectName: LPCWSTR; pwszVersion: LPCWSTR; pwszReferer: LPCWSTR;
ppwszAcceptTypes: PLPWSTR; dwFlags: DWORD): HINTERNET; stdcall;
external 'winhttp.dll' name 'WinHttpOpenRequest';
{$EXTERNALSYM WinHttpOpenRequest}
function WinHttpQueryOption(hInet: HINTERNET; dwOption: DWORD;
lpBuffer: Pointer; var lpdwBufferLength: DWORD): BOOL; stdcall;
external 'winhttp.dll' name 'WinHttpQueryOption';
{$EXTERNALSYM WinHttpQueryOption}
function WinHttpGetProxyForUrl(hSession: HINTERNET; lpcwszUrl: LPCWSTR;
pAutoProxyOptions: LPWINHTTP_AUTOPROXY_OPTIONS;
var pProxyInfo: WINHTTP_PROXY_INFO): BOOL; stdcall;
external 'winhttp.dll' name 'WinHttpGetProxyForUrl';
{$EXTERNALSYM WinHttpGetProxyForUrl}
function WinHttpGetIEProxyConfigForCurrentUser(
var pProxyInfo: WINHTTP_CURRENT_USER_IE_PROXY_CONFIG): BOOL; stdcall;
external 'winhttp.dll' name 'WinHttpGetIEProxyConfigForCurrentUser';
{$EXTERNALSYM WinHttpGetIEProxyConfigForCurrentUser}
function WinHttpCloseHandle(hInternet: HINTERNET): BOOL; stdcall;
external 'winhttp.dll' name 'WinHttpCloseHandle';
{$EXTERNALSYM WinHttpCloseHandle}
const
WINHTTP_NO_REFERER = nil;
{$EXTERNALSYM WINHTTP_NO_REFERER}
WINHTTP_NO_PROXY_NAME = nil;
{$EXTERNALSYM WINHTTP_NO_PROXY_NAME}
WINHTTP_NO_PROXY_BYPASS = nil;
{$EXTERNALSYM WINHTTP_NO_PROXY_BYPASS}
WINHTTP_DEFAULT_ACCEPT_TYPES = nil;
{$EXTERNALSYM WINHTTP_DEFAULT_ACCEPT_TYPES}
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
{$EXTERNALSYM WINHTTP_ACCESS_TYPE_DEFAULT_PROXY}
WINHTTP_ACCESS_TYPE_NO_PROXY = 1;
{$EXTERNALSYM WINHTTP_ACCESS_TYPE_NO_PROXY}
WINHTTP_OPTION_PROXY = 38;
{$EXTERNALSYM WINHTTP_OPTION_PROXY}
WINHTTP_OPTION_PROXY_USERNAME = $1002;
{$EXTERNALSYM WINHTTP_OPTION_PROXY_USERNAME}
WINHTTP_OPTION_PROXY_PASSWORD = $1003;
{$EXTERNALSYM WINHTTP_OPTION_PROXY_PASSWORD}
WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001;
{$EXTERNALSYM WINHTTP_AUTOPROXY_AUTO_DETECT}
WINHTTP_AUTOPROXY_CONFIG_URL = $00000002;
{$EXTERNALSYM WINHTTP_AUTOPROXY_CONFIG_URL}
WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001;
{$EXTERNALSYM WINHTTP_AUTO_DETECT_TYPE_DHCP}
WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002;
{$EXTERNALSYM WINHTTP_AUTO_DETECT_TYPE_DNS_A}
WINHTTP_FLAG_BYPASS_PROXY_CACHE = $00000100;
{$EXTERNALSYM WINHTTP_FLAG_BYPASS_PROXY_CACHE}
WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
{$EXTERNALSYM WINHTTP_FLAG_REFRESH}
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TProxyInfo = record
ProxyURL: WideString;
ProxyBypass: WideString;
ProxyAutoDetected: Boolean;
end;
function GetProxyInfo(const AURL: WideString; var AProxyInfo: TProxyInfo): DWORD;
var
Session: HINTERNET;
AutoDetectProxy: Boolean;
WinHttpProxyInfo: TWinHTTPProxyInfo;
AutoProxyOptions: TWinHTTPAutoProxyOptions;
IEProxyConfig: TWinHTTPCurrentUserIEProxyConfig;
begin
// initialize the result
Result := 0;
// initialize auto-detection to off
AutoDetectProxy := False;
// initialize the result structure
AProxyInfo.ProxyURL := '';
AProxyInfo.ProxyBypass := '';
AProxyInfo.ProxyAutoDetected := False;
// initialize the auto-proxy options
FillChar(AutoProxyOptions, SizeOf(AutoProxyOptions), 0);
// check if the Internet Explorer's proxy configuration is
// available and if so, check its settings for auto-detect
// proxy settings and auto-config script URL options
if WinHttpGetIEProxyConfigForCurrentUser(IEProxyConfig) then
begin
// if the Internet Explorer is configured to auto-detect
// proxy settings then we try to detect them later on
if IEProxyConfig.fAutoDetect then
begin
AutoProxyOptions.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT;
AutoProxyOptions.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
AutoDetectProxy := True;
end;
// if the Internet Explorer is configured to use the proxy
// auto-config script then we try to use it
if IEProxyConfig.lpszAutoConfigURL <> '' then
begin
AutoProxyOptions.dwFlags := AutoProxyOptions.dwFlags or
WINHTTP_AUTOPROXY_CONFIG_URL;
AutoProxyOptions.lpszAutoConfigUrl := IEProxyConfig.lpszAutoConfigUrl;
AutoDetectProxy := True;
end;
// if IE don't have auto-detect or auto-config set, we are
// done here and we can fill the AProxyInfo with the IE settings
if not AutoDetectProxy then
begin
AProxyInfo.ProxyURL := IEProxyConfig.lpszProxy;
AProxyInfo.ProxyBypass := IEProxyConfig.lpszProxyBypass;
AProxyInfo.ProxyAutoDetected := False;
end;
end
else
begin
// if the Internet Explorer's proxy configuration is not
// available, then try to auto-detect it
AutoProxyOptions.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT;
AutoProxyOptions.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
AutoDetectProxy := True;
end;
// if the IE proxy settings are not available or IE has
// configured auto-config script or auto-detect proxy settings
if AutoDetectProxy then
begin
// create a temporary WinHttp session to allow the WinHTTP
// auto-detect proxy settings if possible
Session := WinHttpOpen(nil, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
// if the WinHttp session has been created then try to
// get the proxy data for the specified URL else we assign
// the last error code to the function result
if Assigned(Session) then
try
// get the proxy data for the specified URL with the
// auto-proxy options specified, if succeed then we can
// fill the AProxyInfo with the retrieved settings else
// we assign the last error code to the function result
if WinHttpGetProxyForUrl(Session, LPCWSTR(AURL),
@AutoProxyOptions, WinHttpProxyInfo) then
begin
AProxyInfo.ProxyURL := WinHttpProxyInfo.lpszProxy;
AProxyInfo.ProxyBypass := WinHttpProxyInfo.lpszProxyBypass;
AProxyInfo.ProxyAutoDetected := True;
end
else
Result := GetLastError;
finally
WinHttpCloseHandle(Session);
end
else
Result := GetLastError;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Result: DWORD;
ProxyInfo: TProxyInfo;
begin
Result := GetProxyInfo('http://www.example.com', ProxyInfo);
case Result of
0:
ShowMessage(
'Proxy URL: ' + ProxyInfo.ProxyURL + sLineBreak +
'Proxy bypass: ' + ProxyInfo.ProxyBypass + sLineBreak +
'Proxy autodetected: ' + BoolToStr(ProxyInfo.ProxyAutoDetected, True));
12166: ShowMessage('Error in proxy auto-config script code');
12167: ShowMessage('Unable to download proxy auto-config script');
12180: ShowMessage('WPAD detection failed');
else
ShowMessage('Last error: ' + IntToStr(Result));
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := True;
end;
end.
For an alternative Delphi code you can check e.g. this tip
.
Here's an example of how to setup a TIdHTTP
with obtained proxy settings (actually you just parse the obtained proxy URL and pass it to the ProxyServer
and ProxyPort
properties):
uses
IdGlobal;
procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
Result: DWORD;
ProxyInfo: TProxyInfo;
begin
Result := GetProxyInfo('http://www.example.com', ProxyInfo);
if Result <> 0 then
IdHTTP1.ProxyParams.Clear
else
begin
S := ProxyInfo.ProxyURL;
IdHTTP1.ProxyParams.ProxyServer := Fetch(S, ':');
IdHTTP1.ProxyParams.ProxyPort := StrToInt(S);
end;
end;