Recipe16.10.Use the Current Internet Connection Settings


Recipe 16.10. Use the Current Internet Connection Settings

Problem

Your program wants to use the current Internet connection settings without forcing the user to add them to your application manually.

Solution

Read the current Internet connectivity settings with the InternetSettingsReader class provided for you in Example 16-13. InternetSettingsReader calls some methods of the WinINet API via P/Invoke to retrieve current Internet connection information. The majority of the work is done in setting up the structures that WinINet uses and then marshaling the structure pointers correctly to retrieve the values.

Example 16-13. InternetSettingsReader class

 public class InternetSettingsReader {     #region WinInet structures     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]     public struct InternetPerConnOptionList     {         public int dwSize; // size of the INTERNET_PER_CONN_OPTION_LIST struct         public IntPtr szConnection;    // Connection name to set/query options         public int dwOptionCount;    // Number of options to set/query         public int dwOptionError;        // On error, which option failed         public IntPtr options;     };     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]     public struct InternetConnectionOption     {         static readonly int Size;         public PerConnOption m_Option;         public InternetConnectionOptionValue m_Value;         static InternetConnectionOption()         {             InternetConnectionOption.Size =               Marshal.SizeOf(typeof(InternetConnectionOption));         }         // Nested Types         [StructLayout(LayoutKind.Explicit)]         public struct InternetConnectionOptionValue         {             // Fields             [FieldOffset(0)]             public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime;             [FieldOffset(0)]             public int m_Int;             [FieldOffset(0)]             public IntPtr m_StringPtr;         }     }     #endregion     #region WinInet enums     // Options used in INTERNET_PER_CONN_OPTON struct     //     public enum PerConnOption     {     // Sets or retrieves the connection type. The Value member will contain one     // or more of the values from PerConnFlags             INTERNET_PER_CONN_FLAGS = 1,     // Sets or retrieves a string containing the proxy servers         INTERNET_PER_CONN_PROXY_SERVER = 2,     // Sets or retrieves a string containing the URLs that do not use the     // proxy server             INTERNET_PER_CONN_PROXY_BYPASS = 3,     // Sets or retrieves a string containing the URL to the automatic     // configuration script         INTERNET_PER_CONN_AUTOCONFIG_URL = 4,     }     //     // PER_CONN_FLAGS     //     [Flags]     public enum PerConnFlags     {         PROXY_TYPE_DIRECT = 0x00000001, // Direct to net         PROXY_TYPE_PROXY = 0x00000002, // Via named proxy         PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // Autoproxy URL         PROXY_TYPE_AUTO_DETECT = 0x00000008 // Use autoproxy detection     }     #region P/Invoke defs     [DllImport("WinInet.dll", EntryPoint = "InternetQueryOption",          SetLastError = true)]     public static extern bool InternetQueryOption(         IntPtr hInternet,         int dwOption,         ref InternetPerConnOptionList optionsList,         ref int bufferLength         );     #endregion     #region Private Members     string _proxyAddr = "";     int _proxyPort = -1;     bool _bypassLocal = false;     string _autoConfigAddr = "";     string[] _proxyExceptions = null;     PerConnFlags _flags;     #endregion     #region CTOR     public InternetSettingsReader()     {     }     #endregion 

Each of the properties of InternetSettingsReader shown in Example 16-14 call into the GetInternetConnectionOption method, which returns an InternetConnectionOption. The InternetConnectionOption structure holds all of the pertinent data for the value being returned, and that value is then retrieved based on what type of value was asked for by the specific properties.

Example 16-14. InternetSettingsReader properties

 #region Properties public string ProxyAddr {     get     {         InternetConnectionOption ico =             GetInternetConnectionOption(                 PerConnOption.INTERNET_PER_CONN_PROXY_SERVER);         // Parse out the addr and port         string proxyInfo = Marshal.PtrToStringUni(                                 ico.m_Value.m_StringPtr);         ParseProxyInfo(proxyInfo);         return _proxyAddr;     } } public int ProxyPort {     get     {         InternetConnectionOption ico =             GetInternetConnectionOption(                 PerConnOption.INTERNET_PER_CONN_PROXY_SERVER);         // Parse out the addr and port         string proxyInfo = Marshal.PtrToStringUni(                                 ico.m_Value.m_StringPtr);         ParseProxyInfo(proxyInfo);         return _proxyPort;     } } public bool BypassLocalAddresses {     get     {         InternetConnectionOption ico =             GetInternetConnectionOption(                 PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS);         // Bypass is listed as <local> in the exceptions list         string exceptions =             Marshal.PtrToStringUni(ico.m_Value.m_StringPtr);         if (exceptions.IndexOf("<local>") != -1)             _bypassLocal = true;         else             _bypassLocal = false;          return _bypassLocal;     } } public string AutoConfigurationAddr {     get     {         InternetConnectionOption ico =             GetInternetConnectionOption(                 PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL);         // Get these straight         _autoConfigAddr =             Marshal.PtrToStringUni(ico.m_Value.m_StringPtr);         if (_autoConfigAddr == null)             _autoConfigAddr = "";         return _autoConfigAddr;     } } public string[] ProxyExceptions {     get     {         InternetConnectionOption ico =             GetInternetConnectionOption(                 PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS);         // Exceptions are separated by semicolon         string exceptions =             Marshal.PtrToStringUni(ico.m_Value.m_StringPtr);         if (!string.IsNullOrEmpty(exceptions))         {             _proxyExceptions = exceptions.Split(';');         }         return _proxyExceptions;     } } public PerConnFlags ConnectionType {     get     {         InternetConnectionOption ico =              GetInternetConnectionOption(                 PerConnOption.INTERNET_PER_CONN_FLAGS);         _flags = (PerConnFlags)ico.m_Value.m_Int;         return _flags;     } } #endregion private void ParseProxyInfo(string proxyInfo) {     if(!string.IsNullOrEmpty(proxyInfo))     {         string [] parts = proxyInfo.Split(':');         if (parts.Length == 2)         {             _proxyAddr = parts[0];             try             {                 _proxyPort = Convert.ToInt32(parts[1]);             }             catch (FormatException)             {                 // No port                 _proxyPort = -1;             }         }         else         {             _proxyAddr = parts[0];             _proxyPort = -1;         }     } } 

The GetInternetConnectionOption method shown in Example 16-15 does the heavy lifting as far as communicating with WinINet. First an InternetPerConnOptionList is created as well as an InternetConnectionOption structure to hold the returned value. The InternetConnectionOption structure is then pinned so that the garbage collector does not move the structure in memory and the PerConnOption value is assigned to determine what Internet option to retrieve. The InternetPerConnOptionList is initialized to hold the option values and then the WinINet function IntrenetQueryOption is called. The InternetConnectionOption is filled using the Marshal.PtrToStructure method and returned with the value.

Example 16-15. GetInternetConnectionOption method

 private InternetConnectionOption GetInternetConnectionOption(PerConnOption pco) {      // Allocate the list and option      InternetPerConnOptionList perConnOptList = new InternetPerConnOptionList();      InternetConnectionOption ico = new InternetConnectionOption();      // Pin the option structure      GCHandle gch = GCHandle.Alloc(ico, GCHandleType.Pinned);      // Initialize the option for the data we want      ico.m_Option = pco;      //Initialize the option list for the default connection or LAN      int listSize = Marshal.SizeOf(perConnOptList);      perConnOptList.dwSize = listSize;      perConnOptList.szConnection = IntPtr.Zero;      perConnOptList.dwOptionCount = 1;      perConnOptList.dwOptionError = 0;      // Figure out sizes and offsets      int icoSize = Marshal.SizeOf(ico);      int optionTotalSize = icoSize;      // Alloc enough memory for the option      perConnOptList.options =          Marshal.AllocCoTaskMem(icoSize);     long icoOffset = (long)perConnOptList.options + (long)icoSize;     // Make pointer from the structure     IntPtr optionListPtr = perConnOptList.options;     Marshal.StructureToPtr(ico, optionListPtr, false);     // Make the query     if (InternetQueryOption(         IntPtr.Zero,         75, //(int)InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,         ref perConnOptList,         ref listSize) == true)     {         // Retrieve the value.         ico = (InternetConnectionOption)Marshal.PtrToStructure(perConnOptList.options,                                         typeof(InternetConnectionOption));     }     // Free the COM memory     Marshal.FreeCoTaskMem(perConnOptList.options);     // Unpin the structs     gch.Free();     return ico; } 

Using the InternetSettingsReader is demonstrated in the GetInternetSettings method shown in Example 16-16. The proxy information is retrieved and displayed to the console here, but could easily be stored in another program for use as proxy information when connecting. See Recipe 14.7 for details on setting up the proxy information for a WebRequest.

Example 16-16. Using the InternetSettingsReader

 public static void GetInternetSettings() {     InternetSettingsReader isr = new InternetSettingsReader();     Console.WriteLine("Current Proxy Address: {0}",isr.ProxyAddr);     Console.WriteLine("Current Proxy Port: {0}",isr.ProxyPort);     Console.WriteLine("Current ByPass Local Address setting: {0}",                              isr.BypassLocalAddresses);     Console.WriteLine("Exception addresses for proxy (bypass):");     if(isr.ProxyExceptions != null)     {         foreach(string addr in isr.ProxyExceptions)         {             Console.WriteLine("\t{0}",addr);         }     }     Console.WriteLine("Proxy connection type: {0}",isr.ConnectionType.ToString()); } 

Output for the Solution:

 Current Proxy Address: CORPORATEPROXY Current Proxy Port: 8080 Current ByPass Local Address setting: True Exception addresses for proxy (bypass):     corporate.com     <local> Proxy connection type: PROXY_TYPE_DIRECT, PROXY_TYPE_PROXY 

Discussion

The WinInet Windows Internet (WinInet) API is the unmanaged API for interacting with the FTP, HTTP, and Gopher protocols. This API can be used fill in where managed code leaves off, such as with the Internet configuration settings shown in the Solution. It can also be used for downloading files, working with cookies, and participating in Gopher sessions. You need to understand that WinInet is meant to be a client-side API and is not suited for server-side or service applications; issues could arise in your application from improper usage.

There is a huge amount of information available to the C# programmer directly through the FCLFramework class FCLibrary, but at times you still need to roll up your sleeves and talk to the Win32 API. Even in situations in which restricted privileges are the norm, it is not always out of bounds to create a small assembly that needs enhanced access to do P/Invoke. It can have its access locked down so as not to become a risk to the system.

See Also

See the "InternetQueryOption Function [WinInet]" topic in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net