2012-02-16 34 views
4

これは私の最初の質問です。私はこのサイトから大きな助けを得ました。C#でWininetを使用してプロキシのユーザー名とパスワードを設定する

私は.NET 2010のC#でアプリケーションを作成しています。HTTP要求に対してシステム全体のプロキシサーバーを設定しようとしています。 Proxy Serverは、「基本」認証を有効にしたSquidベースのプロキシです。 私はIEのプロキシを設定することができました。

プロキシがIEに設定された後、IEはプロキシのユーザー名とパスワードを要求します。この機能を自動化しようとしています。最近1週間は動作できず、インターネットを検索していました。まだ成功していない。

以下は、IEプロキシの設定に使用しているコードです。

public static bool SetProxy(string strProxy, string username, string password, string exceptions) 
    { 

     InternetPerConnOptionList list = new InternetPerConnOptionList(); 

     int optionCount = string.IsNullOrEmpty(strProxy) ? 1 : (string.IsNullOrEmpty(exceptions) ? 2 : 3); 
     InternetConnectionOption[] options = new InternetConnectionOption[optionCount]; 
     // USE a proxy server ... 
     options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; 
     options[0].m_Value.m_Int = (int)((optionCount < 2) ? PerConnFlags.PROXY_TYPE_DIRECT : (PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY)); 
     // use THIS proxy server 
     if (optionCount > 1) 
     { 
      options[1].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_SERVER; 
      options[1].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(strProxy); 
      // except for these addresses ... 
      if (optionCount > 2) 
      { 
       options[2].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS; 
       options[2].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(exceptions); 
      } 
     } 

     // default stuff 
     list.dwSize = Marshal.SizeOf(list); 
     list.szConnection = IntPtr.Zero; 
     list.dwOptionCount = options.Length; 
     list.dwOptionError = 0; 


     int optSize = Marshal.SizeOf(typeof(InternetConnectionOption)); 
     // make a pointer out of all that ... 
     IntPtr optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length); 
     // copy the array over into that spot in memory ... 
     for (int i = 0; i < options.Length; ++i) 
     { 
      IntPtr opt = new IntPtr(optionsPtr.ToInt32() + (i * optSize)); 
      Marshal.StructureToPtr(options[i], opt, false); 
     } 

     list.options = optionsPtr; 

     // and then make a pointer out of the whole list 
     IntPtr ipcoListPtr = Marshal.AllocCoTaskMem((Int32)list.dwSize); 
     Marshal.StructureToPtr(list, ipcoListPtr, false); 

     // and finally, call the API method! 
     int returnvalue = NativeMethods.InternetSetOption(IntPtr.Zero, 
      InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, 
      ipcoListPtr, list.dwSize) ? -1 : 0; 
     if (returnvalue == 0) 
     { // get the error codes, they might be helpful 
      returnvalue = Marshal.GetLastWin32Error(); 
     } 
     // FREE the data ASAP 
     Marshal.FreeCoTaskMem(optionsPtr); 
     Marshal.FreeCoTaskMem(ipcoListPtr); 
     if (returnvalue > 0) 
     { // throw the error codes, they might be helpful 
      throw new Win32Exception(Marshal.GetLastWin32Error()); 
     } 

     return (returnvalue < 0); 
    } 
} 

#region WinInet structures 
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
public struct InternetPerConnOptionList 
{ 
    public int dwSize;    // size of the INTERNET_PER_CONN_OPTION_LIST struct 
    public IntPtr szConnection;   // connection name to set/query options 
    public int dwOptionCount;  // number of options to set/query 
    public int dwOptionError;   // on error, which option failed 
    //[MarshalAs(UnmanagedType.)] 
    public IntPtr options; 
}; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
public struct InternetConnectionOption 
{ 
    static readonly int Size; 
    public PerConnOption m_Option; 
    public InternetConnectionOptionValue m_Value; 
    static InternetConnectionOption() 
    { 
     InternetConnectionOption.Size = Marshal.SizeOf(typeof(InternetConnectionOption)); 
    } 

    // Nested Types 
    [StructLayout(LayoutKind.Explicit)] 
    public struct InternetConnectionOptionValue 
    { 
     // Fields 
     [FieldOffset(0)] 
     public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime; 
     [FieldOffset(0)] 
     public int m_Int; 
     [FieldOffset(0)] 
     public IntPtr m_StringPtr; 
    } 
} 
#endregion 

#region WinInet enums 
// 
// options manifests for Internet{Query|Set}Option 
// 
public enum InternetOption : uint 
{ 
    INTERNET_OPTION_PER_CONNECTION_OPTION = 75 
} 

// 
// Options used in INTERNET_PER_CONN_OPTON struct 
// 
public enum PerConnOption 
{ 
    INTERNET_PER_CONN_FLAGS = 1, // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags 
    INTERNET_PER_CONN_PROXY_SERVER = 2, // Sets or retrieves a string containing the proxy servers. 
    INTERNET_PER_CONN_PROXY_BYPASS = 3, // Sets or retrieves a string containing the URLs that do not use the proxy server. 
    INTERNET_PER_CONN_AUTOCONFIG_URL = 4//, // Sets or retrieves a string containing the URL to the automatic configuration script. 
} 

// 
// PER_CONN_FLAGS 
// 
[Flags] 
public enum PerConnFlags 
{ 
    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 
} 
#endregion 

internal static class NativeMethods 
{ 
    [DllImport("WinInet.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    public static extern bool InternetSetOption(IntPtr hInternet, InternetOption dwOption, IntPtr lpBuffer, int dwBufferLength); 
} 

この機能を有効にするための助けがあれば幸いです。

よろしく、 ムダシールミルザ。

+0

32ビットへのポインタをキャストしているので、プロキシ設定コードは64ビットマシンでは機能しません。 – EricLaw

答えて

0

WebProxyクラスを見て、あなたが望むことができるかどうかを確認してください。以下の方法で

使用それは(私は例外が区切られていることを前提とするつもりです「;」):あなたが設定

SetProxy("http://proxy:8080", "user", "password", "http://site1;http://site2"); 
+0

こんにちは、このクラスも試しましたが、成功しませんでした。 –

+0

私はそれを例で更新しました。それはあなたのために機能しますか? –

+0

こんにちは@TrevorPilleyは 'ProxyEnable'チェックボックスを変更する方法はありません。 – Scorpion

1

public static void SetProxy(string proxyAddress, string userName, string password, string exceptions) 
{ 
    var credential = new NetworkCredential(userName, password); 

    string[] bypassList = null; 

    if (!string.IsNullOrEmpty(exceptions)) 
    { 
     bypassList = exceptions.Split(';'); 
    } 

    WebRequest.DefaultWebProxy = new WebProxy(proxyAddress, true, bypassList, credential); 
} 

は、メソッドを呼び出すためにWinINET用のプロキシですが、すべてのクライアントが恩恵を受ける "グローバル"プロキシのユーザー名とパスワードを保存する方法はありません。このユーザー名/パスワードは、プロセスごとにのみキャッシュできます。このプロセスでは、InternetSetOption APIを使用してユーザー名とパスワードを提供できます。これにより、WinINETのパスワードのみが設定され、.NETや他のHTTPスタックのパスワードは設定されません。

0

「Windowsセキュリティ」ウィンドウの認証と刺激を処理しながら、私はWebBrowserコントロールで同様の問題を抱えました。まず、WinINETでプロキシアドレスを設定し、資格情報でnavigateメソッドを呼び出します。これは、1つのプロセスあたりのプロキシ資格情報を格納するのに役立ちます:

WebBrowser.Navigate("http://user:[email protected]/"); 

のWinInet方法は、プロキシアドレス完璧な設定、(@EricLawが言ったように)しかし、あなたのコードは、あなたの「グローバルプロキシ」という考えには適していませんINTERNET_OPTION_PER_CONNECTION_OPTIONを使用しています。 INTERNET_OPTION_PROXYdocumentaion

さらに解決策がないfour different approachesがあります。しかし、彼らは非常に便利です。

関連する問題