Microsoft KB Archive/873199

From BetaArchive Wiki

Article ID: 873199

Article Last Modified on 5/18/2007



APPLIES TO

  • Microsoft Visual Studio .NET 2003 Professional Edition
  • Microsoft Visual Studio .NET 2003 Enterprise Architect
  • Microsoft Visual Studio .NET 2003 Enterprise Developer
  • Microsoft Visual Studio .NET 2003 Academic Edition
  • Microsoft Visual Studio .NET 2002 Professional Edition
  • Microsoft Visual Studio .NET 2002 Enterprise Architect
  • Microsoft Visual Studio .NET 2002 Enterprise Developer
  • Microsoft Visual Studio .NET 2002 Academic Edition
  • Microsoft Windows HTTP Services 5.1
  • Microsoft Windows HTTP Services 5.1




SUMMARY

This article discusses how to use autoproxy in managed code. This article includes a code sample that demonstrates the implementation of autoproxy. The code sample in the article retrieves the proxy settings by using the following methods:


  • Create a managed DLL that uses the Windows HTTP Services (WinHTTP) library.
  • Call the WinHttpGetProxyForUrl function in the managed DLL to retrieve the proxy information for the specified URL.
  • Create a sample application that uses the functions that are defined in the managed DLL to obtain the proxy settings for a specified URL.


INTRODUCTION

This step-by-step article describes how to use autoproxy in managed code. The Microsoft .NET Framework does not provide support for autoproxy. You must use the WinHTTP autoproxy functions like the WinHttpGetProxyForUrl function to obtain the proxy settings in managed code. You can use a proxy auto-configuration (PAC) script to automatically configure the proxy settings.

Note The AutoProxy class provides two overloaded constructors. If you use the AutoProxy class in the following way, you resolve the proxy to use to connect to http://www.microsoft.com by using the PAC file that is provided by http://localhost/PAC/proxy.pac:

AutoProxy.Class1 myProxy = new AutoProxy.Class1("http://www.microsoft.com", "http://localhost/PAC/proxy.pac");

If your network implements autoproxy detection that follows the WPAD protocol that is described at the following Microsoft Developer Network (MSDN) Web site, you do not have to specify the location of the PAC file:

In this case, you can use the following constructor:

AutoProxy.Class1 myProxy = new AutoProxy.Class1("http://www.microsoft.com");

back to the top

Use autoproxy in managed code

To implement autoproxy in managed code, follow these steps:

  1. Create a managed DLL that uses autoproxy.
  2. Create a sample application to verify the implementation of autoproxy.

back to the top

Create a managed DLL that uses autoproxy

To create a managed DLL that uses the WinHTTP autoproxy functions to retrieve the proxy information, follow these steps:

  1. Start Microsoft Visual Studio .NET.
  2. On the File menu, point to New, and then click Project. The New Project dialog box appears.
  3. Click Visual C++ Projects under Project Types, and then click Managed C++ Class Library under Templates.

    If you are using Visual Studio .NET 2003, click Class Library (.NET) under Templates.
  4. In the Name box, type Autoproxy, and then click OK.
  5. In Solution Explorer, right-click Autoproxy.h, and then click Open.
  6. Replace the existing code in the Autoproxy.h file with the following code:

    // AutoProxy.h
    #define UNICODE
    #include <windows.h>
    #include <wchar.h>
    #include "path of the header file\winhttp.h"
    #include <stdio.h>
    #pragma comment (lib, "winhttp.lib")
    
    #pragma once
    
    using namespace System;
    using namespace System::Runtime::InteropServices;
    
    namespace AutoProxy
    {
       public __gc class Class1
       {
          private:
              TCHAR* szUrl;
              TCHAR* szAutoProxyLocation;
          public:
              Class1 (String* szUrlParam)
              {
                  TCHAR szMessage[1024];
                  szUrl = (TCHAR *)(void*)Marshal::StringToCoTaskMemUni(szUrlParam);
                  swprintf (szMessage, L"Initializing class for URL %s with autorpxy\n",
                                    szUrl);
                  OutputDebugString (szMessage);
                  szAutoProxyLocation = NULL;
                  CoInitialize(NULL);
              };
              Class1 (String* szUrlParam, String* proxyUrl)
              {
                  TCHAR szMessage[1024];
                  szUrl = (TCHAR *)(void*)Marshal::StringToCoTaskMemUni(szUrlParam);
                  szAutoProxyLocation = (TCHAR*)(void*)Marshal::StringToCoTaskMemUni(proxyUrl);
                  swprintf (szMessage, L"Initilizing class for url %s with proxy location %s\n", 
                                    szUrl, szAutoProxyLocation);
                  OutputDebugString (szMessage);
                  CoInitialize(NULL);
              };
    
              ~Class1 ()
              {
                  OutputDebugString (L"Class1 destruct\n");
                  CoUninitialize ();
              };
    
              String* GetProxyForUrl()throw (TCHAR*)
              {
                  TCHAR szError [1024];
                  HINTERNET hHttpSession = NULL;
                  WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions;
                  WINHTTP_PROXY_INFO ProxyInfo;
                  DWORD cbProxyInfoSize = sizeof(ProxyInfo);
                  TCHAR* szProxy;
                  ZeroMemory( &AutoProxyOptions, sizeof(AutoProxyOptions) );
                  ZeroMemory( &ProxyInfo, sizeof(ProxyInfo) );
                  hHttpSession = WinHttpOpen( L"WinHTTP AutoProxy Sample/1.0",
                                              WINHTTP_ACCESS_TYPE_NO_PROXY,
                                              WINHTTP_NO_PROXY_NAME,
                                              WINHTTP_NO_PROXY_BYPASS,0 
                                            );
                  // Exit if the WinHttpOpen function fails.
                 if( !hHttpSession )
                 {
                      // Clean the WINHTTP_PROXY_INFO structure.
                      if( ProxyInfo.lpszProxy != NULL )
                           GlobalFree(ProxyInfo.lpszProxy);
                      if( ProxyInfo.lpszProxyBypass != NULL )
                           GlobalFree( ProxyInfo.lpszProxyBypass );
                 }
                 // Set up the autoproxy call.
                 if (szAutoProxyLocation)
                 {
                     // The proxy auto-configuration URL is already known.  
                     // Therefore, auto-detection is not required.
                    AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
                 
                    // Set the proxy auto configuration URL.
                    AutoProxyOptions. lpszAutoConfigUrl = szAutoProxyLocation;
                 }
                 else
                 {
                     // Use auto-detection because you do not know a PAC URL.
                     AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
                     // Use both Dynamic Host Configuration Protocol (DHCP) 
                     // and Domain Name System (DNS) based auto-detection.
                     AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP 
    
                     |WINHTTP_AUTO_DETECT_TYPE_DNS_A;
                 }
                // If obtaining the PAC script requires NTLM/Negotiate
                // authentication, automatically supply the domain credentials
                // of the client. 
                AutoProxyOptions.fAutoLogonIfChallenged = TRUE;
                // Call the WinHttpGetProxyForUrl function with our target URL.
                if( WinHttpGetProxyForUrl( hHttpSession,szUrl,&AutoProxyOptions,&ProxyInfo))        
    
                {
                     switch (ProxyInfo.dwAccessType)
                     {
                          case WINHTTP_ACCESS_TYPE_DEFAULT_PROXY:
                             OutputDebugString (L"WINHTTP_ACCESS_TYPE_DEFAULT_PROXY\n");
                             break;
                          case WINHTTP_ACCESS_TYPE_NO_PROXY:
                             OutputDebugString (L"WINHTTP_ACCESS_TYPE_NO_PROXY\n");
                             break;
                          case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
                             OutputDebugString (L"WINHTTP_ACCESS_TYPE_NAMED_PROXY\n");
                             break;
                     }
                     if (ProxyInfo.lpszProxy)
                     {
                         szProxy = new TCHAR [lstrlen (ProxyInfo.lpszProxy)];
                         lstrcpy (szProxy, ProxyInfo.lpszProxy);
                     }
                     // Clean the WINHTTP_PROXY_INFO structure.
                     if (ProxyInfo.lpszProxy != NULL) 
                         GlobalFree(ProxyInfo.lpszProxy); 
                     if (ProxyInfo.lpszProxyBypass != NULL)                                      
    
                         GlobalFree(ProxyInfo.lpszProxyBypass); 
                 }
                 else
                 {
                     DWORD dwErr = GetLastError();
                     switch (dwErr)
                     {
                         case ERROR_WINHTTP_AUTODETECTION_FAILED:
                             swprintf(szError, L"ERROR_WINHTTP_AUTODETECTION_FAILED\n");
                             break;
                         case ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT:
                             swprintf(szError,L"ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT\n");
                             break;
                         case ERROR_WINHTTP_INCORRECT_HANDLE_TYPE:
                             swprintf(szError,L"ERROR_WINHTTP_INCORRECT_HANDLE_TYPE\n");
                             break;
                         case ERROR_WINHTTP_INVALID_URL:
                             swprintf(szError,L"ERROR_WINHTTP_INVALID_URL\n");
                             break;
                         case ERROR_WINHTTP_LOGIN_FAILURE:
                             swprintf(szError,L"ERROR_WINHTTP_LOGIN_FAILURE\n");
                             break;
                         case ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT:
                             swprintf(szError,L"ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT\n");
                             break;
                         case ERROR_WINHTTP_UNRECOGNIZED_SCHEME:
                             swprintf(szError,L"ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n");
                             break;
                         default:
                             swprintf (szError, L"Error %d\n", dwErr);
                    }
                    throw (new Exception(szError));
    
                 }
                // Close the WinHTTP handles.
                if( hHttpSession != NULL )
                      WinHttpCloseHandle( hHttpSession );   
                // Return the proxy settings.
                Marshal::FreeHGlobal(szUrl);
                return new String (szProxy);
    
            }
       };
    }

    Note In this code, path of the header file is a placeholder for the path of the winhttp.h file on your computer.

    The Winhttp.h file and the Winhttp.lib file are included with Microsoft Platform Software Development Kit (SDK). To download Platform SDK, visit the following Microsoft Web site:

  7. In Solution Explorer, right-click Autoproxy, and then click Properties. The Autoproxy Property Pages dialog box appears.
  8. In the left pane, click Linker under Configuration Properties, and then click Input.
  9. In the Additional Dependencies box in the right pane, type "path of winhttp library\winhttp.lib"

    Note path of winhttp library is a placeholder for the Winhttp.lib file on your computer.
  10. In the Additional Dependencies box, type msvcrt.lib.
  11. In the Force Symbol References box, type __DllMainCRTStartup@12, and then click OK.
  12. On the Build menu, click Build Solution to build the project.

back to the top

Create a sample application to verify the implementation of autoproxy

To create a sample application that uses the managed DLL that you created by using Visual Studio .NET and then displays the proxy settings, follow these steps:

  1. Start Visual Studio .NET.
  2. On the File menu, point to New, and then click Project. The New Project dialog box appears.
  3. Click Visual C# Projects under Project Types, click Console Application under Templates, and then click OK. By default, a file that is named Class1.cs is created.
  4. Add a reference to the Autoproxy.dll file that you created. To do this, follow these steps:
    1. In Solution Explorer, right-click References, and then click Add Reference. The Add Reference dialog box appears.
    2. On the .NET tab, click Browse.
    3. Locate the Autoproxy.dll file on your computer, and then click Open.
    4. In the Add Reference dialog box, click OK.
  5. Add the following code at the beginning of the namespace declaration in the Class1.cs file:

    using AutoProxy;
  6. Add the following code to the Main method of the Class1.cs file:

    AutoProxy.Class1 myProxy = new AutoProxy.Class1("http://www.microsoft.com", "http://localhost/PAC/proxy.pac"); 
    try
    {
        Console.WriteLine ("\n\nProxy settings for the URL are:\n {0}\n", myProxy.GetProxyForUrl() );
        Console.Read();
    }
    catch (Exception myError)
    {
        Console.WriteLine (myError.Message);
        Console.Read();
    }

    Note In this code, http://localhost/PAC/proxy.pac is the URL path of the autoproxy configuration file. If you do not have autoproxy configured on the computer, you can follow these steps to configure autoproxy for testing purposes:

    1. Start Notepad.
    2. Paste the following code in Notepad:

      function FindProxyForURL(url, host) 
      { 
        return "PROXY 192.168.1.1:8080"; 
      }

      Note In this code, 192.168.1.1 is the IP address of your proxy server and 8080 is the port through which you can access proxy server.

    3. Save the file as Proxy.pac.
    4. Create a virtual directory for the Proxy.pac file that you created in step 6c.

      For additional information about creating a virtual directory, click the following article number to view the article in the Microsoft Knowledge Base:

      172138 How to create a virtual directory in Internet Information Services (IIS)

      Note The content folder path must be the path of the folder where you saved the Proxy.pac file.
  7. On the Build menu, click Build Solution to build the application.
  8. On the Debug menu, click Start to run the application. You can see the proxy settings in the output.

Note After you get a proxy URL for a specific request URL, you can use the HttpWebRequest.Proxy property to set this property for your request. Additionally, you can use the GlobalProxySelection.Select method to select this proxy for all the requests that are made by your application.

back to the top

REFERENCES

For more information, visit the following MSDN Web site:

back to the top

Keywords: kbhowto kbhowtomaster kbhttp kbdll kbproxydev kbmanaged KB873199