0

我目前正在编写一个需要更改 Windows 代理设置的 C# 代理程序。每个在线指南仅更改 LAN 连接的代理设置(即在 NAT 后面)。这是一个问题,因为中国的许多用户(我的目标受众)直接将 PPPoE 连接从他们的调制解调器连接到他们的计算机并使用 PPPoE 软件拨号到 DSL(是的,这很糟糕,所有监听端口都对世界,但事情就是这样)。

我将如何更改 DSL 代理?这令人担忧,因为查看我的用户统计数据,大约 20% 的人没有自动更改代理设置。

4

1 回答 1

6

这是一个执行此操作的实用程序示例类。你像这样使用它:

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

和实用程序类:

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);
}
于 2013-06-10T13:13:31.043 回答