【问题标题】:how to authenticate to proxy with wininet.dll?如何使用 wininet.dll 对代理进行身份验证?
【发布时间】:2018-02-15 14:14:20
【问题描述】:

我有此代码用于将进程连接到代理,但它返回 false: 如果我不在 SetConnectionProxy() 中输入用户名和密码并且只发送两个选项 PROXY flags 和 PROXY name,则该代码有效。当我添加 INTERNET_PER_CONN_OPTION 设置用户名和设置密码时,它返回 false。 我对wininet一无所知。

请帮帮我。谢谢。

{

    private static string progressName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; //extrae el nombre de la aplicación

    [DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr InternetOpen(
        string lpszAgent, int dwAccessType, string lpszProxyName,
        string lpszProxyBypass, int dwFlags);

    [DllImport("wininet.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool InternetCloseHandle(IntPtr hInternet);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    private struct INTERNET_PER_CONN_OPTION_LIST
    {
        public int Size;

        // The connection to be set. NULL means LAN.
        public System.IntPtr Connection;

        public int OptionCount;
        public int OptionError;

        // List of INTERNET_PER_CONN_OPTIONs.
        public System.IntPtr pOptions;
    }
    private enum INTERNET_OPTION
    {
        // Sets or retrieves an INTERNET_PER_CONN_OPTION_LIST structure that specifies
        // a list of options for a particular connection.
        INTERNET_OPTION_PER_CONNECTION_OPTION = 75,

        // Notify the system that the registry settings have been changed so that
        // it verifies the settings on the next call to InternetConnect.
        INTERNET_OPTION_SETTINGS_CHANGED = 39,

        // Causes the proxy data to be reread from the registry for a handle.
        INTERNET_OPTION_REFRESH = 37

    }

    private enum INTERNET_PER_CONN_OptionEnum
    {
        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_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6,
        INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7,
        INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8,
        INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9,
        INTERNET_PER_CONN_FLAGS_UI = 10,
        INTERNET_OPTION_PROXY_USERNAME = 43,
        INTERNET_OPTION_PROXY_PASSWORD = 44
}
    private const int INTERNET_OPEN_TYPE_DIRECT = 1;  // direct to net
    private const int INTERNET_OPEN_TYPE_PRECONFIG = 0; // read registry
                                                        /// <summary>
                                                        /// Constants used in INTERNET_PER_CONN_OPTON struct.
                                                        /// </summary>
    private enum INTERNET_OPTION_PER_CONN_FLAGS
    {
        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
    }

    /// <summary>
    /// Used in INTERNET_PER_CONN_OPTION.
    /// When create a instance of OptionUnion, only one filed will be used.
    /// The StructLayout and FieldOffset attributes could help to decrease the struct size.
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    private struct INTERNET_PER_CONN_OPTION_OptionUnion
    {
        // A value in INTERNET_OPTION_PER_CONN_FLAGS.
        [FieldOffset(0)]
        public int dwValue;
        [FieldOffset(0)]
        public System.IntPtr pszValue;
        [FieldOffset(0)]
        public System.Runtime.InteropServices.ComTypes.FILETIME ftValue;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct INTERNET_PER_CONN_OPTION
    {
        // A value in INTERNET_PER_CONN_OptionEnum.
        public int dwOption;
        public INTERNET_PER_CONN_OPTION_OptionUnion Value;
    }
    /// <summary>
    /// Sets an Internet option.
    /// </summary>
    [DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    private static extern bool InternetSetOption(
        IntPtr hInternet,
        INTERNET_OPTION dwOption,
        IntPtr lpBuffer,
        int lpdwBufferLength);

    /// <summary>
    /// Queries an Internet option on the specified handle. The Handle will be always 0.
    /// </summary>
    [DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true,
        EntryPoint = "InternetQueryOption")]
    private extern static bool InternetQueryOptionList(
        IntPtr Handle,
        INTERNET_OPTION OptionFlag,
        ref INTERNET_PER_CONN_OPTION_LIST OptionList,
        ref int size);

    /// <summary>
    /// Set the proxy server for LAN connection.
    /// </summary>
    public static bool SetConnectionProxy(string proxyServer, string username, string password)
    {

        IntPtr hInternet = InternetOpen(progressName, INTERNET_OPEN_TYPE_DIRECT, null, null, 0);

        // Create 4 options.
        int opciones = 4;

        INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[opciones];

        // Set PROXY flags.
        Options[0] = new INTERNET_PER_CONN_OPTION();
        Options[0].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS;
        Options[0].Value.dwValue = (int)INTERNET_OPTION_PER_CONN_FLAGS.PROXY_TYPE_PROXY;

        // Set proxy name.
        Options[1] = new INTERNET_PER_CONN_OPTION();
        Options[1].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER;
        Options[1].Value.pszValue = Marshal.StringToHGlobalAnsi(proxyServer);

        //Set username.
        Options[2] = new INTERNET_PER_CONN_OPTION();
        Options[2].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_OPTION_PROXY_USERNAME;
        Options[2].Value.pszValue = Marshal.StringToCoTaskMemAuto(username);

        // Set password.
        Options[3] = new INTERNET_PER_CONN_OPTION();
        Options[3].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_OPTION_PROXY_PASSWORD;
        Options[3].Value.pszValue = Marshal.StringToCoTaskMemAuto(password);

        // Allocate a block of memory of the options.
        System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0]) + Marshal.SizeOf(Options[1]) + Marshal.SizeOf(Options[2]) + Marshal.SizeOf(Options[3]));

        System.IntPtr current = buffer;

        // Marshal data from a managed object to an unmanaged block of memory.
        for (int i = 0; i < Options.Length; i++)
        {
            Marshal.StructureToPtr(Options[i], current, false);
            current = (System.IntPtr)((int)current + Marshal.SizeOf(Options[i]));
        }

        // Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
        INTERNET_PER_CONN_OPTION_LIST option_list = new INTERNET_PER_CONN_OPTION_LIST();

        // Point to the allocated memory.
        option_list.pOptions = buffer;

        // Return the unmanaged size of an object in bytes.
        option_list.Size = Marshal.SizeOf(option_list);

        // IntPtr.Zero means LAN connection.
        option_list.Connection = IntPtr.Zero;

        option_list.OptionCount = Options.Length;
        option_list.OptionError = 0;
        int size = Marshal.SizeOf(option_list);

        // Allocate memory for the INTERNET_PER_CONN_OPTION_LIST instance.
        IntPtr intptrStruct = Marshal.AllocCoTaskMem(size);

        // Marshal data from a managed object to an unmanaged block of memory.
        Marshal.StructureToPtr(option_list, intptrStruct, true);

        // Set internet settings.
        bool bReturn = InternetSetOption(hInternet, INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION, intptrStruct, size);

        // Free the allocated memory.
        Marshal.FreeCoTaskMem(buffer);
        Marshal.FreeCoTaskMem(intptrStruct);
        InternetCloseHandle(hInternet); //

        // Throw an exception if this operation failed.
        if (!bReturn)
        {
            throw new ApplicationException(" Set Internet Option Failed!");
        }

        return bReturn;
    }       

}

【问题讨论】:

    标签: c# proxy wininet


    【解决方案1】:

    经过很长时间我找到了答案,它比看起来简单得多。很简单,只需将 SetConnectionProxy() 的原始函数(不带用户名或密码)放入其中,然后在第一个导航中,将代理的用户名和密码插入 url:http://user:password@url 中,然后我是这样做的:

    先连接代理:

    public static bool SetConnectionProxy(string proxyServer)
    
       {
    
            IntPtr hInternet = InternetOpen(miniYo, INTERNET_OPEN_TYPE_DIRECT, null, null, 0);
            INTERNET_PER_CONN_OPTION[] Options = new INTERNET_PER_CONN_OPTION[2];
    
            // Set PROXY flags.
            Options[0] = new INTERNET_PER_CONN_OPTION();
            Options[0].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS;
            Options[0].Value.dwValue = (int)INTERNET_OPTION_PER_CONN_FLAGS.PROXY_TYPE_PROXY;
    
            // Set proxy name.
            Options[1] = new INTERNET_PER_CONN_OPTION();
            Options[1].dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER;
            Options[1].Value.pszValue = Marshal.StringToHGlobalAnsi(proxyServer);
    
            // Allocate a block of memory of the options.
            System.IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(Options[0]) + Marshal.SizeOf(Options[1]));
            System.IntPtr current = buffer;
    
            // Marshal data from a managed object to an unmanaged block of memory.
            for (int i = 0; i < Options.Length; i++)
            {
                Marshal.StructureToPtr(Options[i], current, false);
                current = (System.IntPtr)((int)current + Marshal.SizeOf(Options[i]));
            }
    
            // Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
            INTERNET_PER_CONN_OPTION_LIST option_list = new INTERNET_PER_CONN_OPTION_LIST();
    
            // Point to the allocated memory.
            option_list.pOptions = buffer;
    
            // Return the unmanaged size of an object in bytes.
            option_list.Size = Marshal.SizeOf(option_list);
    
            // IntPtr.Zero means LAN connection.
            option_list.Connection = IntPtr.Zero;
    
            option_list.OptionCount = Options.Length;
            option_list.OptionError = 0;
            int size = Marshal.SizeOf(option_list);
    
            // Allocate memory for the INTERNET_PER_CONN_OPTION_LIST instance.
            IntPtr intptrStruct = Marshal.AllocCoTaskMem(size);
    
            // Marshal data from a managed object to an unmanaged block of memory.
            Marshal.StructureToPtr(option_list, intptrStruct, true);
    
            // Set internet settings.
            bool bReturn = InternetSetOption(hInternet, INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION, intptrStruct, size);
    
            // Free the allocated memory.
            Marshal.FreeCoTaskMem(buffer);
            Marshal.FreeCoTaskMem(intptrStruct);
            InternetCloseHandle(hInternet); //¿Esto lo cierra?
    
            // Throw an exception if this operation failed.
            if (!bReturn)
            {
                throw new ApplicationException(" Set Internet Option Failed!");
            }
    
            return bReturn;
        }
    

    }

    第一次使用用户名和密码导航,之后:

    UriBuilder uriSite = new UriBuilder(string);
                uriSite.UserName = usuario;
                uriSite.Password = contraseña;
                webBrowser.Navigate(uriSite.Uri);
    

    我很遗憾地说我没有感受到社区的帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-30
      • 2017-11-24
      • 2019-01-31
      • 1970-01-01
      • 2015-09-15
      • 1970-01-01
      相关资源
      最近更新 更多