E
Epetruk
Hi,
I wrote this class to try to set the proxy settings in Internet Explorer
programmatically. The class uses the API functions in wininet.dll; however,
there's a horrible crash when I call InternetSetOption the first time. Can
anyone tell me what I'm doing wrong?
Epetruk
public class IESettingsApp
{
public enum IESettingOptions
{
INTERNET_PER_CONN_FLAGS = 1,
INTERNET_PER_CONN_PROXY_SERVER = 2,
INTERNET_PER_CONN_PROXY_BYPASS = 3,
INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5,
INTERNET_OPTION_REFRESH = 37,
INTERNET_OPTION_PER_CONNECTION_OPTION = 75,
INTERNET_OPTION_SETTINGS_CHANGED = 39,
PROXY_TYPE_PROXY = 2,
PROXY_TYPE_DIRECT = 1,
};
[StructLayout(LayoutKind.Sequential)]
struct FILETIME
{
public UInt32 dwLowDate;
public UInt32 dwHighDate;
};
//special way of handling unions - 2nd, 3rd and 4th fields begin at
same loc
[StructLayout(LayoutKind.Explicit, Size = 12)]
struct INTERNET_PER_CONN_OPTION
{
[FieldOffset(0)]
public UInt32 dwOption;
[FieldOffset(4)]
public UInt32 dwValue;
[FieldOffset(4)]
public IntPtr pszValue;
[FieldOffset(4)]
public FILETIME ftValue;
};
[StructLayout(LayoutKind.Sequential)]
struct INTERNET_PER_CONN_OPTION_LIST
{
public UInt32 dwSize;
public String pszConnection;
public UInt32 dwOptionCount;
public UInt32 dwOptionError;
public IntPtr pOptions;
};
[DllImport("wininet.dll", SetLastError = true, CharSet =
CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private extern static bool InternetSetOption(IntPtr hInternet,
UInt32 dwOption, INTERNET_PER_CONN_OPTION_LIST lpBuffer, UInt32
dwBufferLength);
public static void SetIEProxySettings(String strProxyServer, String
strProxyBypassAddresses)
{
const int numIpcos = 3;
//create the INTERNET_PER_CONN_OPTION_LIST, and set its size
INTERNET_PER_CONN_OPTION_LIST ipcoList = new
INTERNET_PER_CONN_OPTION_LIST();
UInt32 ipcoListSize = (UInt32)Marshal.SizeOf(ipcoList);
ipcoList.dwSize = ipcoListSize;
ipcoList.pszConnection = null;
ipcoList.dwOptionCount = numIpcos;
INTERNET_PER_CONN_OPTION[] ipcoArr = new
INTERNET_PER_CONN_OPTION[numIpcos];
int ipcoSize = Marshal.SizeOf(ipcoArr[0]);
//use proxy server
ipcoArr[0].dwOption =
(UInt32)(IESettingOptions.INTERNET_PER_CONN_FLAGS);
ipcoArr[0].dwValue =
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_SERVER;
//use *this* proxy server
ipcoArr[1].dwOption =
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_SERVER;
ipcoArr[1].pszValue =
Marshal.StringToHGlobalAnsi(strProxyServer);
bypass these addresses for the proxy
ipcoArr[2].dwOption =
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_BYPASS;
ipcoArr[2].pszValue =
Marshal.StringToHGlobalAnsi(strProxyBypassAddresses);
//now create a buffer that will hold all the
INTERNET_PER_CONN_OPTIONS we've created
byte[] ipcoBuf = new byte[ipcoSize * numIpcos];
for (int i = 0; i < numIpcos; i++)
{
//copy the dwOption first
BitConverter.GetBytes(ipcoArr.dwOption).CopyTo(ipcoBuf, i
* ipcoSize);
//copy the next field in the union, depending on whether
it's a DWORD or a string
switch (ipcoArr.dwOption)
{
case (UInt32)IESettingOptions.INTERNET_PER_CONN_FLAGS:
BitConverter.GetBytes(ipcoArr.dwValue).CopyTo(ipcoBuf,
i * ipcoSize + sizeof(UInt32));
break;
case
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_SERVER:
case
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_BYPASS:
BitConverter.GetBytes(ipcoArr.pszValue.ToInt32()).CopyTo(ipcoBuf,
i * ipcoSize + sizeof(UInt32));
break;
}
}
//copy the buffer to the IntPtr that represents the
INTERNET_PER_CONN_OPTION_LIST
IntPtr pOptions = Marshal.AllocCoTaskMem(numIpcos * ipcoSize);
Marshal.Copy(ipcoBuf, 0, pOptions, numIpcos * ipcoSize);
ipcoList.pOptions = pOptions;
//turn the INTERNET_PER_CONN_OPTION structure into an IntPtr
IntPtr ipcoListPtr =
Marshal.AllocCoTaskMem((Int32)ipcoListSize);
Marshal.StructureToPtr(ipcoList, ipcoListPtr, false);
//call the function to set the settings
bool bRet = InternetSetOption(IntPtr.Zero,
(UInt32)IESettingOptions.INTERNET_OPTION_PER_CONNECTION_OPTION, ipcoList,
ipcoListSize);
if (!bRet)
{
int err = Marshal.GetLastWin32Error();
System.ComponentModel.Win32Exception we = new
System.ComponentModel.Win32Exception(err);
Console.WriteLine("The following error occurred: {0}",
we.Message);
Console.Read();
}
//notify of the change and refresh
InternetSetOption(IntPtr.Zero,
(UInt32)IESettingOptions.INTERNET_OPTION_SETTINGS_CHANGED, ipcoList, 0);
InternetSetOption(IntPtr.Zero,
(UInt32)IESettingOptions.INTERNET_OPTION_REFRESH, ipcoList, 0);
//and deallocate allocated memory
Marshal.FreeCoTaskMem(ipcoList.pOptions);
Marshal.FreeCoTaskMem(ipcoListPtr);
Marshal.FreeHGlobal(ipcoArr[1].pszValue);
Marshal.FreeHGlobal(ipcoArr[2].pszValue);
}
}
I wrote this class to try to set the proxy settings in Internet Explorer
programmatically. The class uses the API functions in wininet.dll; however,
there's a horrible crash when I call InternetSetOption the first time. Can
anyone tell me what I'm doing wrong?
Epetruk
public class IESettingsApp
{
public enum IESettingOptions
{
INTERNET_PER_CONN_FLAGS = 1,
INTERNET_PER_CONN_PROXY_SERVER = 2,
INTERNET_PER_CONN_PROXY_BYPASS = 3,
INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5,
INTERNET_OPTION_REFRESH = 37,
INTERNET_OPTION_PER_CONNECTION_OPTION = 75,
INTERNET_OPTION_SETTINGS_CHANGED = 39,
PROXY_TYPE_PROXY = 2,
PROXY_TYPE_DIRECT = 1,
};
[StructLayout(LayoutKind.Sequential)]
struct FILETIME
{
public UInt32 dwLowDate;
public UInt32 dwHighDate;
};
//special way of handling unions - 2nd, 3rd and 4th fields begin at
same loc
[StructLayout(LayoutKind.Explicit, Size = 12)]
struct INTERNET_PER_CONN_OPTION
{
[FieldOffset(0)]
public UInt32 dwOption;
[FieldOffset(4)]
public UInt32 dwValue;
[FieldOffset(4)]
public IntPtr pszValue;
[FieldOffset(4)]
public FILETIME ftValue;
};
[StructLayout(LayoutKind.Sequential)]
struct INTERNET_PER_CONN_OPTION_LIST
{
public UInt32 dwSize;
public String pszConnection;
public UInt32 dwOptionCount;
public UInt32 dwOptionError;
public IntPtr pOptions;
};
[DllImport("wininet.dll", SetLastError = true, CharSet =
CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private extern static bool InternetSetOption(IntPtr hInternet,
UInt32 dwOption, INTERNET_PER_CONN_OPTION_LIST lpBuffer, UInt32
dwBufferLength);
public static void SetIEProxySettings(String strProxyServer, String
strProxyBypassAddresses)
{
const int numIpcos = 3;
//create the INTERNET_PER_CONN_OPTION_LIST, and set its size
INTERNET_PER_CONN_OPTION_LIST ipcoList = new
INTERNET_PER_CONN_OPTION_LIST();
UInt32 ipcoListSize = (UInt32)Marshal.SizeOf(ipcoList);
ipcoList.dwSize = ipcoListSize;
ipcoList.pszConnection = null;
ipcoList.dwOptionCount = numIpcos;
INTERNET_PER_CONN_OPTION[] ipcoArr = new
INTERNET_PER_CONN_OPTION[numIpcos];
int ipcoSize = Marshal.SizeOf(ipcoArr[0]);
//use proxy server
ipcoArr[0].dwOption =
(UInt32)(IESettingOptions.INTERNET_PER_CONN_FLAGS);
ipcoArr[0].dwValue =
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_SERVER;
//use *this* proxy server
ipcoArr[1].dwOption =
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_SERVER;
ipcoArr[1].pszValue =
Marshal.StringToHGlobalAnsi(strProxyServer);
bypass these addresses for the proxy
ipcoArr[2].dwOption =
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_BYPASS;
ipcoArr[2].pszValue =
Marshal.StringToHGlobalAnsi(strProxyBypassAddresses);
//now create a buffer that will hold all the
INTERNET_PER_CONN_OPTIONS we've created
byte[] ipcoBuf = new byte[ipcoSize * numIpcos];
for (int i = 0; i < numIpcos; i++)
{
//copy the dwOption first
BitConverter.GetBytes(ipcoArr.dwOption).CopyTo(ipcoBuf, i
* ipcoSize);
//copy the next field in the union, depending on whether
it's a DWORD or a string
switch (ipcoArr.dwOption)
{
case (UInt32)IESettingOptions.INTERNET_PER_CONN_FLAGS:
BitConverter.GetBytes(ipcoArr.dwValue).CopyTo(ipcoBuf,
i * ipcoSize + sizeof(UInt32));
break;
case
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_SERVER:
case
(UInt32)IESettingOptions.INTERNET_PER_CONN_PROXY_BYPASS:
BitConverter.GetBytes(ipcoArr.pszValue.ToInt32()).CopyTo(ipcoBuf,
i * ipcoSize + sizeof(UInt32));
break;
}
}
//copy the buffer to the IntPtr that represents the
INTERNET_PER_CONN_OPTION_LIST
IntPtr pOptions = Marshal.AllocCoTaskMem(numIpcos * ipcoSize);
Marshal.Copy(ipcoBuf, 0, pOptions, numIpcos * ipcoSize);
ipcoList.pOptions = pOptions;
//turn the INTERNET_PER_CONN_OPTION structure into an IntPtr
IntPtr ipcoListPtr =
Marshal.AllocCoTaskMem((Int32)ipcoListSize);
Marshal.StructureToPtr(ipcoList, ipcoListPtr, false);
//call the function to set the settings
bool bRet = InternetSetOption(IntPtr.Zero,
(UInt32)IESettingOptions.INTERNET_OPTION_PER_CONNECTION_OPTION, ipcoList,
ipcoListSize);
if (!bRet)
{
int err = Marshal.GetLastWin32Error();
System.ComponentModel.Win32Exception we = new
System.ComponentModel.Win32Exception(err);
Console.WriteLine("The following error occurred: {0}",
we.Message);
Console.Read();
}
//notify of the change and refresh
InternetSetOption(IntPtr.Zero,
(UInt32)IESettingOptions.INTERNET_OPTION_SETTINGS_CHANGED, ipcoList, 0);
InternetSetOption(IntPtr.Zero,
(UInt32)IESettingOptions.INTERNET_OPTION_REFRESH, ipcoList, 0);
//and deallocate allocated memory
Marshal.FreeCoTaskMem(ipcoList.pOptions);
Marshal.FreeCoTaskMem(ipcoListPtr);
Marshal.FreeHGlobal(ipcoArr[1].pszValue);
Marshal.FreeHGlobal(ipcoArr[2].pszValue);
}
}