【问题标题】:Show Authentication dialog in C# for windows Vista/7在 C# 中为 windows Vista/7 显示身份验证对话框
【发布时间】:2010-11-09 14:39:50
【问题描述】:

我想从用户那里获取网络登录凭据。

我正在使用带有 C# 的 .NET 3.5。 到目前为止,我使用了CredUIPromptForCredentials 电话 (关于如何使用它的非常有用的链接可以找到here

我的问题是CredUIPromptForCredentials API 调用显示的是旧的 Windows 2000/XP 凭据对话框,而不是新的 Vista/7 对话框。

我在 msdn 上看到我应该使用 CredUIPromptForWindowsCredentials 函数。

有人可以发布一个如何在 C# 中使用它的示例吗? 我还需要能够获取输入的凭据。

【问题讨论】:

    标签: c# pinvoke


    【解决方案1】:

    我设法实施了一个适合我的解决方案。

    这里是源代码:

        [DllImport("ole32.dll")]
        public static extern void CoTaskMemFree(IntPtr ptr);
    
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        private struct CREDUI_INFO
        {
            public int cbSize;
            public IntPtr hwndParent;
            public string pszMessageText;
            public string pszCaptionText;
            public IntPtr hbmBanner;
        }  
    
    
        [DllImport("credui.dll", CharSet = CharSet.Auto)]
        private static extern bool CredUnPackAuthenticationBuffer(int dwFlags,
                                                                   IntPtr pAuthBuffer,
                                                                   uint cbAuthBuffer,
                                                                   StringBuilder pszUserName,
                                                                   ref int pcchMaxUserName,
                                                                   StringBuilder pszDomainName,
                                                                   ref int pcchMaxDomainame,
                                                                   StringBuilder pszPassword,
                                                                   ref int pcchMaxPassword);
    
        [DllImport("credui.dll", CharSet = CharSet.Auto)]
        private static extern int CredUIPromptForWindowsCredentials(ref CREDUI_INFO notUsedHere,
                                                                     int authError,
                                                                     ref uint authPackage,
                                                                     IntPtr InAuthBuffer,
                                                                     uint InAuthBufferSize,
                                                                     out IntPtr refOutAuthBuffer,
                                                                     out uint refOutAuthBufferSize,
                                                                     ref bool fSave,
                                                                     int flags);
    
    
    
        public static void GetCredentialsVistaAndUp(string serverName, out NetworkCredential networkCredential)
        {
            CREDUI_INFO credui = new CREDUI_INFO();
            credui.pszCaptionText = "Please enter the credentails for " + serverName;
            credui.pszMessageText = "DisplayedMessage";
            credui.cbSize = Marshal.SizeOf(credui);
            uint authPackage = 0;
            IntPtr outCredBuffer = new IntPtr();
            uint outCredSize;
            bool save = false;
            int result = CredUIPromptForWindowsCredentials(ref credui,
                                                           0,
                                                           ref authPackage,
                                                           IntPtr.Zero,
                                                           0,
                                                           out outCredBuffer,
                                                           out outCredSize,
                                                           ref save,
                                                           1 /* Generic */);
    
            var usernameBuf = new StringBuilder(100);
            var passwordBuf  = new StringBuilder(100);
            var domainBuf = new StringBuilder(100);
    
            int maxUserName = 100;
            int maxDomain = 100;
            int maxPassword = 100;
            if (result == 0)
            {
                if (CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredSize, usernameBuf, ref maxUserName,
                                                   domainBuf, ref maxDomain, passwordBuf, ref maxPassword))
                {
                    //TODO: ms documentation says we should call this but i can't get it to work
                    //SecureZeroMem(outCredBuffer, outCredSize);
    
                    //clear the memory allocated by CredUIPromptForWindowsCredentials 
                    CoTaskMemFree(outCredBuffer);
                    networkCredential = new NetworkCredential()
                                            {
                                                UserName = usernameBuf.ToString(),
                                                Password = passwordBuf.ToString(),
                                                Domain = domainBuf.ToString()
                                            };
                    return;
                }
            }
    
            networkCredential = null;
        }
    

    我仍然需要弄清楚细节,例如如何记住最后输入的凭据等...

    但主要部分有效。

    【讨论】:

    • 我看到你调用了你的函数GetCredentialsVistaAndUp,这是否也适用于 xp 或者你没有测试过吗?
    • @ChrisjanLodewyks - 它不适用于 XP。 XP 不支持此对话框。它只能在 Vista 及更高版本上使用,就像方法名称所暗示的那样。
    • 我不断得到一个神秘的返回码 0x1F / 十进制 31。结果我必须为所有内容设置 CharSet = CharSet.Unicode,然后效果很好。
    • 您有没有想过如何获取最后输入的凭据?
    【解决方案2】:

    这里有一些代码可以继续extracted from bytes.com post:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct _CREDUI_INFO
    {
      public int cbSize;
      public IntPtr hwndParent;
      public string pszMessageText;
      public string pszCaptionText;
      public IntPtr hbmBanner;
    }
    class Program
    {
      [DllImport("credui.dll", CharSet=CharSet.Unicode)]
      internal static extern uint CredUIPromptForWindowsCredentials(ref
        _CREDUI_INFO notUsedHere,
        int authError,
        ref uint authPackage,
        IntPtr InAuthBuffer,
        uint InAuthBufferSize,
        out IntPtr refOutAuthBuffer,
        out uint refOutAuthBufferSize,
        ref bool fSave,
        int flags);
    
      const int CREDUIWIN_AUTHPACKAGE_ONLY = 0x10;
    
      static void Main()
      {
        _CREDUI_INFO credui = new _CREDUI_INFO();
        credui.cbSize = Marshal.SizeOf(credui);
        credui.pszCaptionText = "Testje";
        credui.pszMessageText = "Message";
        uint authPackage = 0;
        IntPtr outCredBuffer;
        uint outCredSize;
        bool save = false;
    
        uint ret = CredUIPromptForWindowsCredentials(ref credui,
          0,
          ref authPackage,
          IntPtr.Zero,
          0,
          out outCredBuffer,
          out outCredSize,
          ref save,
          CREDUIWIN_AUTHPACKAGE_ONLY);
    
        if(ret != 0)
        {
          // failed to load function...
          // ...
        }
        else
        {
          // extract credentials from the buffer returned, using more
          //   credui.dll API's .
          // ...
        }
      }
    }
    

    【讨论】:

    • 我看到了这篇文章。问题是我需要提取在对话框中输入的凭据。我认为它需要使用 CredUnPackAuthenticationBuffer api 调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    相关资源
    最近更新 更多