Changing proxy settings programmatically in Windows for DSL connections

≡放荡痞女 提交于 2019-12-11 18:59:55

问题


I'm currently writing a C# proxy program that needs to change Windows proxy settings. Every single guide online only changes the proxy settings for a LAN connection (i.e. behind a NAT). This is a problem, since many users in China (my target audience) directly hook up PPPoE connections from their modem into their computer and use PPPoE software to dial up to DSL (yes, this is sucky security, with all listening ports visible to the world, but that's the way things are).

How would I change the DSL proxy? This is worrying, as looking at my user stats ~20% of people are not getting the proxy settings changed automatically.


回答1:


Here is a utility sample class that does it. You use it like this:

static void Main(string[] args)
{
    // read direct proxy server (return null if there isn't) of the connection named "MyConn"
    string server = ProxyUtilities.GetDirectProxyServer("MyConn");

    // set a direct proxy server (set to null to disable) to the connection named "MyConn"
    ProxyUtilities.SetDirectProxyServer("MyConn", "myproxy:8080");
}

And the utility class:

public static class ProxyUtilities
{
    public static string GetDirectProxyServer(string connectionName)
    {
        List<INTERNET_PER_CONN_OPTION> options = new List<INTERNET_PER_CONN_OPTION>();
        INTERNET_PER_CONN_OPTION option = new INTERNET_PER_CONN_OPTION();
        option.dwOption = INTERNET_PER_CONN_PROXY_SERVER;
        options.Add(option);

        option = new INTERNET_PER_CONN_OPTION();
        option.dwOption = INTERNET_PER_CONN_FLAGS;
        options.Add(option);

        using (var list = INTERNET_PER_CONN_OPTION_LIST.From(connectionName, options))
        {
            int size = list.dwSize;
            if (!InternetQueryOption(IntPtr.Zero, INTERNET_OPTION_PER_CONNECTION_OPTION, list, ref size))
                throw new Win32Exception(Marshal.GetLastWin32Error());

            List<INTERNET_PER_CONN_OPTION> outOptions = list.Options;
            string proxyServer = null;
            if ((outOptions[1].Value.dwValue & PROXY_TYPE_PROXY) != 0)
            {
                proxyServer = Marshal.PtrToStringUni(outOptions[0].Value.pszValue);
            }
            Marshal.FreeHGlobal(outOptions[0].Value.pszValue);
            return proxyServer;
        }
    }

    public static void SetDirectProxyServer(string connectionName, string proxyServer)
    {
        List<INTERNET_PER_CONN_OPTION> options = new List<INTERNET_PER_CONN_OPTION>();
        INTERNET_PER_CONN_OPTION option = new INTERNET_PER_CONN_OPTION();
        option.dwOption = INTERNET_PER_CONN_PROXY_SERVER;
        option.Value.pszValue = proxyServer == null ? IntPtr.Zero : Marshal.StringToHGlobalUni(proxyServer);
        options.Add(option);

        option = new INTERNET_PER_CONN_OPTION();
        option.dwOption = INTERNET_PER_CONN_FLAGS;
        option.Value.dwValue = proxyServer == null ? PROXY_TYPE_DIRECT : PROXY_TYPE_PROXY;
        options.Add(option);

        try
        {
            using (var list = INTERNET_PER_CONN_OPTION_LIST.From(connectionName, options))
            {
                int size = list.dwSize;
                if (!InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PER_CONNECTION_OPTION, list, size))
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
        finally
        {
            Marshal.FreeHGlobal(option.Value.pszValue);
        }
    }

    private const int INTERNET_OPTION_PER_CONNECTION_OPTION = 75;
    private const int INTERNET_PER_CONN_FLAGS = 1;
    private const int INTERNET_PER_CONN_PROXY_SERVER = 2;
    private const int PROXY_TYPE_DIRECT = 0x00000001;
    private const int PROXY_TYPE_PROXY = 0x00000002;

    [StructLayout(LayoutKind.Explicit)]
    private struct INTERNET_PER_CONN_OPTION_Value
    {
        [FieldOffset(0)]
        public int dwValue;
        [FieldOffset(0)]
        public IntPtr pszValue;
        [FieldOffset(0)]
        public System.Runtime.InteropServices.ComTypes.FILETIME ftValue;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct INTERNET_PER_CONN_OPTION
    {
        public int dwOption;
        public INTERNET_PER_CONN_OPTION_Value Value;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private class INTERNET_PER_CONN_OPTION_LIST : IDisposable
    {
        public int dwSize;
        public string pszConnection;
        public int dwOptionCount;
        public int dwOptionError;
        public IntPtr pOptions;

        public static INTERNET_PER_CONN_OPTION_LIST From(string name, IEnumerable<INTERNET_PER_CONN_OPTION> options)
        {
            INTERNET_PER_CONN_OPTION_LIST list = new INTERNET_PER_CONN_OPTION_LIST();
            list.pszConnection = name;
            list.pOptions = Marshal.AllocCoTaskMem(options.Sum(o => Marshal.SizeOf(o)));
            IntPtr current = list.pOptions;
            foreach (var option in options)
            {
                Marshal.StructureToPtr(option, current, false);
                current += Marshal.SizeOf(option);
            }
            list.dwSize = Marshal.SizeOf(list);
            list.dwOptionCount = options.Count();
            return list;
        }

        public List<INTERNET_PER_CONN_OPTION> Options
        {
            get
            {
                List<INTERNET_PER_CONN_OPTION> options = new List<INTERNET_PER_CONN_OPTION>();
                if (pOptions != IntPtr.Zero)
                {
                    IntPtr current = pOptions;
                    for (int i = 0; i < dwOptionCount; i++)
                    {
                        INTERNET_PER_CONN_OPTION option = (INTERNET_PER_CONN_OPTION)Marshal.PtrToStructure(current, typeof(INTERNET_PER_CONN_OPTION));
                        current += Marshal.SizeOf(option);
                        options.Add(option);
                    }
                }
                return options;
            }
        }

        public void Dispose()
        {
            if (pOptions != null)
            {
                Marshal.FreeCoTaskMem(pOptions);
                pOptions = IntPtr.Zero;
            }
        }
    }

    [DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private extern static bool InternetQueryOption(IntPtr hInternet, int dwOption, INTERNET_PER_CONN_OPTION_LIST list, ref int lpdwBufferLength);

    [DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool InternetSetOption(IntPtr hInternet, int dwOption, INTERNET_PER_CONN_OPTION_LIST list, int lpdwBufferLength);
}


来源:https://stackoverflow.com/questions/16896318/changing-proxy-settings-programmatically-in-windows-for-dsl-connections

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!