Click here to Skip to main content
15,860,861 members
Articles / Programming Languages / C#
Article

Using PAC files proxy

Rate me:
Please Sign up or sign in to vote.
4.88/5 (12 votes)
4 Nov 2005 144.8K   4K   45   12
This article explains how to set a proxy using PAC files.

Introduction

This article explains how to set a proxy using PAC files. PAC files are Proxy Automatic Configuration files, which define a proxy for a specific URL. The solution presented in the article uses the WinHttp.dll for obtaining a proxy URL.

Background

Using the code

I’ve created a simple testing application that sends a web request to www.google.com using a proxy obtained from a PAC file.

In order to run the application you need to put the proxy.pac file into your home directory for the default web site. Usually this directory is c:\inetpub\wwwroot.

The main function that returns the proxy for a specific URL is GetProxyForUrlUsingPac that is defined in the Proxy class:

C#
public static string GetProxyForUrlUsingPac ( string DestinationUrl, string PacUri ){

     IntPtr WinHttpSession = Win32Api.WinHttpOpen("User",
                                    Win32Api.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                                    IntPtr.Zero, 
                                    IntPtr.Zero, 
                                    0);

     Win32Api.WINHTTP_AUTOPROXY_OPTIONS  ProxyOptions = 
              new Win32Api.WINHTTP_AUTOPROXY_OPTIONS();
     Win32Api.WINHTTP_PROXY_INFO ProxyInfo = 
                     new Win32Api.WINHTTP_PROXY_INFO(); 
            
     ProxyOptions.dwFlags           = Win32Api.WINHTTP_AUTOPROXY_CONFIG_URL;
     ProxyOptions.dwAutoDetectFlags = (Win32Api.WINHTTP_AUTO_DETECT_TYPE_DHCP |
                                       Win32Api.WINHTTP_AUTO_DETECT_TYPE_DNS_A);
     ProxyOptions.lpszAutoConfigUrl = PacUri;
            
     // Get Proxy 
     bool IsSuccess = Win32Api.WinHttpGetProxyForUrl( WinHttpSession, 
                                                      DestinationUrl,
                                                      ref ProxyOptions,
                                                      ref ProxyInfo );
            
     Win32Api.WinHttpCloseHandle(WinHttpSession);

     if ( IsSuccess ){
         return ProxyInfo.lpszProxy;
     }else {
         Console.WriteLine("Error: {0}", Win32Api.GetLastError() );
         return null;
     }
}

The Win32Api class contains a definition of the Win32 functions:

C#
/// <summary>
/// This function implements the Web Proxy Auto-Discovery (WPAD) protocol
/// for automatically configuring the proxy settings for an HTTP request.
/// The WPAD protocol downloads a Proxy Auto-Configuration (PAC) file,
/// which is a script that identifies the proxy server to use for a given
/// target URL. PAC files are typically deployed by the IT department within
/// a corporate network environment. The URL of the PAC file can either be
/// specified explicitly or WinHttpGetProxyForUrl can be instructed to
/// automatically discover the location of the PAC file on the local network.
/// </summary>
/// <param name="hSession">The WinHTTP session handle
///         returned by the WinHttpOpen function</param>
/// <param name="lpcwszUrl">A pointer
/// to a null-terminated Unicode string that contains the
/// URL of the HTTP request that the application is preparing to send.</param>
/// <param name="pAutoProxyOptions">A pointer
/// to a WINHTTP_AUTOPROXY_OPTIONS structure that
/// specifies the auto-proxy options to use.</param>
/// <param name="pProxyInfo">A pointer
/// to a WINHTTP_PROXY_INFO structure that receives the
/// proxy setting. This structure is then applied to the request handle using the
/// WINHTTP_OPTION_PROXY option.</param>
/// <returns></returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool WinHttpGetProxyForUrl(
            IntPtr hSession,
            string lpcwszUrl,
            ref WINHTTP_AUTOPROXY_OPTIONS pAutoProxyOptions,
            ref WINHTTP_PROXY_INFO pProxyInfo);

/// <summary>
/// The function initializes, for an application, the use of WinHTTP
/// functions and returns a WinHTTP-session handle
/// </summary>
/// <param name="pwszUserAgent">A pointer
/// to a string variable that contains the name of the
/// application or entity calling the WinHTTP functions.</param>
/// <param name="dwAccessType">Type of access required.
///     This can be one of the following values</param>
/// <param name="pwszProxyName"> A pointer
/// to a string variable that contains the name of the
/// proxy server to use when proxy access
/// is specified by setting dwAccessType to
/// WINHTTP_ACCESS_TYPE_NAMED_PROXY. The WinHTTP functions
/// recognize only CERN type proxies for HTTP.
/// If dwAccessType is not set to WINHTTP_ACCESS_TYPE_NAMED_PROXY,
/// this parameter must be set
/// to WINHTTP_NO_PROXY_NAME</param>
/// <param name="pwszProxyBypass">A pointer
/// to a string variable that contains an optional list
/// of host names or IP addresses, or both,
/// that should not be routed through the proxy when
/// dwAccessType is set to WINHTTP_ACCESS_TYPE_NAMED_PROXY.
/// The list can contain wildcard characters.
/// Do not use an empty string, because
/// the WinHttpOpen function uses it as the proxy bypass list.
/// If this parameter specifies the "<local>" macro
/// as the only entry, this function bypasses
/// any host name that does not contain a period.
/// If dwAccessType is not set to WINHTTP_ACCESS_TYPE_NAMED_PROXY,
/// this parameter must be set to WINHTTP_NO_PROXY_BYPASS.</param>
/// <param name="dwFlags">Unsigned long integer value
/// that contains the flags that indicate various options
/// affecting the behavior of this function</param>
/// <returns>Returns a valid session handle
///    if successful, or NULL otherwise</returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern IntPtr WinHttpOpen(
            string pwszUserAgent,
            int dwAccessType,
            IntPtr pwszProxyName,
            IntPtr pwszProxyBypass,
            int dwFlags
            );

/// <summary>
/// The function closes a single HINTERNET handle
/// </summary>
/// <param name="hInternet">Valid HINTERNET handle to be closed.</param>
/// <returns>Returns TRUE if the handle
///    is successfully closed, or FALSE otherwise</returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool WinHttpCloseHandle(IntPtr hInternet);

The main function that uses the GetProxyForUrlUsingPac is:

C#
// Create test request
WebRequest TestRequest = WebRequest.Create ( DestinationUrl );
           
// Optain Proxy address for the URL
string ProxyAddresForUrl = Proxy.GetProxyForUrlUsingPac (DestinationUrl, PacUri);
if ( ProxyAddresForUrl != null ){
   Console.WriteLine ("Found Proxy: {0}", ProxyAddresForUrl );
   TestRequest.Proxy = new WebProxy ( ProxyAddresForUrl ) ;
}else{
   Console.WriteLine ( "Proxy Not Found. Send request directly."  );
}

That's it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCould'n get the string value of the proxy server after running ProxyTest Pin
Member 6358574-Oct-17 10:11
Member 6358574-Oct-17 10:11 
Questionnumeric values for dwFlags in WINHTTP_AUTOPROXY_OPTIONS Pin
piotr_s23-Apr-14 1:52
piotr_s23-Apr-14 1:52 
GeneralThis is great stuff. I have made an addition : Get the configuration file URI (pac) from IE Settings Pin
phazzy11-Feb-10 23:22
phazzy11-Feb-10 23:22 
GeneralThanks Pin
Prasoon Kumar Gupta31-Mar-09 2:12
professionalPrasoon Kumar Gupta31-Mar-09 2:12 
QuestionRe: Thanks Pin
michael.groenewald19-Apr-09 22:58
michael.groenewald19-Apr-09 22:58 
Generalcan't read the host name Pin
x_kanaga24-Jul-08 20:21
x_kanaga24-Jul-08 20:21 
Generalnot able to detect the pac file automatically....... Pin
bharathiraja.periyasamy17-Oct-06 19:52
bharathiraja.periyasamy17-Oct-06 19:52 
GeneralCan't get to local file. Pin
Victor M. Bello A.27-Jul-06 9:36
Victor M. Bello A.27-Jul-06 9:36 
GeneralRe: Can't get to local file. Pin
Chan Hui30-Aug-06 18:47
Chan Hui30-Aug-06 18:47 
GeneralRe: Can't get to local file. Pin
puneet miglani6-Nov-06 23:48
puneet miglani6-Nov-06 23:48 
GeneralRe: Can't get to local file. Pin
thrio2-Oct-07 4:24
thrio2-Oct-07 4:24 
JokeNice Pin
EricLaw15-Jan-06 14:28
EricLaw15-Jan-06 14:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.