简体   繁体   English

在Windows中以编程方式更改DSL连接的代理设置

[英]Changing proxy settings programmatically in Windows for DSL connections

I'm currently writing a C# proxy program that needs to change Windows proxy settings. 我目前正在编写一个需要更改Windows代理设置的C#代理程序。 Every single guide online only changes the proxy settings for a LAN connection (ie behind a NAT). 每个在线的指南仅更改LAN连接的代理设置(即,位于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). 这是一个问题,因为中国的许多用户(我的目标受众)直接将PPPoE连接从其调制解调器连接到计算机上,并使用PPPoE软件拨号到DSL(是的,这很糟糕,所有侦听端口对世界,但事实就是这样)。

How would I change the DSL proxy? 我将如何更改DSL代理? This is worrying, as looking at my user stats ~20% of people are not getting the proxy settings changed automatically. 这令人担忧,因为查看我的用户统计信息时,大约20%的人没有自动更改代理设置。

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM