IEのProxy設定を取得する その2
前回の記事を書いてから良く考えて見直してみると、Proxyの例外を無視してます。
それに、「設定を自動的に検出する」とか「自動構成スクリプトを使用する」にチェックが入ってると機能しないんじゃないかと。
そこで、その辺りも加味してProxyを取得する関数をここを参考に作ってみました。
HOSTが例外に該当するかのチェックに正規表現使って確認してるんですが、こういうのの定石みたいな方法あるんですかね?ネットで調べて見たらPathMatchSpecを使ってチェックしてるソースもあったんですけど、それもどうなのか判断つきませんでした。
unit ProxyUtils; interface uses Windows, WinInet, IdURI, StrUtils, RegularExpressions, Classes, SysUtils; type // winhttp.h から必要な定義をコピー PWINHTTP_CURRENT_USER_IE_PROXY_CONFIG = ^TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG; TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG = record fAutoDetect: BOOL; lpszAutoConfigUrl: LPWSTR; lpszProxy: LPWSTR; lpszProxyBypass: LPWSTR; end; PWINHTTP_AUTOPROXY_OPTIONS = ^TWINHTTP_AUTOPROXY_OPTIONS; TWINHTTP_AUTOPROXY_OPTIONS = record dwFlags: DWORD; dwAutoDetectFlags: DWORD; lpszAutoConfigUrl: LPCWSTR; lpvReserved: LPVOID; dwReserved: DWORD; fAutoLogonIfChallenged: BOOL; end; PWINHTTP_PROXY_INFO = ^TWINHTTP_PROXY_INFO; TWINHTTP_PROXY_INFO = record dwAccessType: DWORD; // see WINHTTP_ACCESS_* types below lpszProxy: LPWSTR; // proxy server list lpszProxyBypass: LPWSTR; // proxy bypass list end; const // WinHttpOpen dwAccessType values (also for WINHTTP_PROXY_INFO::dwAccessType) WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0; WINHTTP_ACCESS_TYPE_NO_PROXY = 1; WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3; // WinHttpOpen prettifiers for optional parameters WINHTTP_NO_PROXY_NAME = Nil; WINHTTP_NO_PROXY_BYPASS = Nil; WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001; WINHTTP_AUTOPROXY_CONFIG_URL = $00000002; WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000; WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000; // // Flags for dwAutoDetectFlags // WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001; WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002; function WinHttpOpen(pszAgentW: LPCWSTR; dwAccessType: DWORD; pszProxyW: LPCWSTR; pszProxyBypassW: LPCWSTR; dwFlags: DWORD): HINTERNET; stdcall; external 'Winhttp.dll'; function WinHttpCloseHandle(hInternet: HINTERNET): Boolean; stdcall; external 'Winhttp.dll'; function WinHttpGetProxyForUrl(hSession: HINTERNET; lpcwszUrl: LPCWSTR; pAutoProxyOptions: PWINHTTP_AUTOPROXY_OPTIONS; var pProxyInfo: TWINHTTP_PROXY_INFO): Boolean; stdcall; external 'Winhttp.dll'; function WinHttpGetIEProxyConfigForCurrentUser(var pProxyConfig: TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG): Boolean; stdcall; external 'Winhttp.dll'; { URLにアクセス先のURLを渡すと、ProxyServer、ProxyPortに値が返ってくるはず } function GetProxy(const URL: String; var ProxyServer: String; var ProxyPort: Integer): Boolean; implementation function GetProxy(const URL: String; var ProxyServer: String; var ProxyPort: Integer): Boolean; var ProxyConfig: TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG; AutoProxyConfig: TWINHTTP_AUTOPROXY_OPTIONS; ProxyInfo: TWINHTTP_PROXY_INFO; ClnPos: Integer; hSession: HINTERNET; Proxy: String; ProxyBypass: String; Strs: TStrings; Idx: Integer; URI: TIdURI; Pattern: String; begin ZeroMemory(@ProxyConfig, SizeOf(TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG)); WinHttpGetIEProxyConfigForCurrentUser(ProxyConfig); Proxy := ''; if ProxyConfig.fAutoDetect Or Assigned(ProxyConfig.lpszAutoConfigUrl) then begin // 「設定を自動的に検出する」「自動構成スクリプトを使用する」の場合 hSession := WinHttpOpen(Nil, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY , WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if Assigned(hSession) then begin ZeroMemory(@AutoProxyConfig, SizeOf(TWINHTTP_AUTOPROXY_OPTIONS)); if ProxyConfig.fAutoDetect then begin //「設定を自動的に検出する」の場合 AutoProxyConfig.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT; AutoProxyConfig.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP Or WINHTTP_AUTO_DETECT_TYPE_DNS_A; end else begin //「自動構成スクリプトを使用する」の場合 AutoProxyConfig.dwFlags := WINHTTP_AUTOPROXY_CONFIG_URL; AutoProxyConfig.lpszAutoConfigUrl := ProxyConfig.lpszAutoConfigUrl; end; WinHttpGetProxyForUrl(hSession, PChar(URL), @AutoProxyConfig, ProxyInfo); if Assigned(ProxyInfo.lpszProxy) then begin Proxy := ProxyInfo.lpszProxy; GlobalFree(Cardinal(ProxyInfo.lpszProxy)); end; if Assigned(ProxyInfo.lpszProxyBypass) then begin // 例外設定がある場合 ProxyBypass := ProxyInfo.lpszProxyBypass; GlobalFree(Cardinal(ProxyInfo.lpszProxyBypass)); end; WinHttpCloseHandle(hSession); end; end else if Assigned(ProxyConfig.lpszProxy) then begin Proxy := ProxyConfig.lpszProxy; if Assigned(ProxyConfig.lpszProxyBypass) then begin // 例外設定がある場合 ProxyBypass := ProxyConfig.lpszProxyBypass; end; end; if Proxy <> '' then begin ClnPos := Pos(':', Proxy); if ClnPos > 0 then begin ProxyServer := LeftStr(Proxy, ClnPos - 1); ProxyPort := StrToIntDef(RightStr(Proxy, Length(Proxy) - ClnPos), 0); end; if ProxyBypass <> '' then begin URI := TIdURI.Create(URL); Strs := TStringList.Create; Strs.Delimiter := ';'; Strs.DelimitedText := ProxyBypass; // 例外設定がある場合 // URLのHOSTが該当するか確認 for Idx := 0 to Strs.Count - 1 do begin Pattern := Strs.Strings[Idx]; Pattern := StringReplace(Pattern, '.', '\.', [rfReplaceAll]); Pattern := StringReplace(Pattern, '*', '.*', [rfReplaceAll]); if TRegEx.IsMatch(URI.Host, Pattern) then begin ProxyServer := ''; ProxyPort := 0; break; end; end; FreeAndNil(URI); end; end else begin ProxyServer := ''; ProxyPort := 0; end; Result := (ProxyServer <> ''); if Assigned(ProxyConfig.lpszAutoConfigUrl) then GlobalFree(Cardinal(ProxyConfig.lpszAutoConfigUrl)); if Assigned(ProxyConfig.lpszProxy) then GlobalFree(Cardinal(ProxyConfig.lpszProxy)); if Assigned(ProxyConfig.lpszProxyBypass) then GlobalFree(Cardinal(ProxyConfig.lpszProxyBypass)); end; end.