PInovke引用如下:
class NativeMethod { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct CREDUI_INFO { public int cbSize; public IntPtr hwndParent; public string pszMessageText; public string pszCaptionText; public IntPtr hbmBanner; } public enum PromptForWindowsCredentialsFlags { /// /// The caller is requesting that the credential provider return the user name and password in plain text. /// This value cannot be combined with SECURE_PROMPT. /// CREDUIWIN_GENERIC = 0x1, /// /// The Save check box is displayed in the dialog box. /// CREDUIWIN_CHECKBOX = 0x2, /// /// Only credential providers that support the authentication package specified by the authPackage parameter should be enumerated. /// This value cannot be combined with CREDUIWIN_IN_CRED_ONLY. /// CREDUIWIN_AUTHPACKAGE_ONLY = 0x10, /// /// Only the credentials specified by the InAuthBuffer parameter for the authentication package specified by the authPackage parameter should be enumerated. /// If this flag is set, and the InAuthBuffer parameter is NULL, the function fails. /// This value cannot be combined with CREDUIWIN_AUTHPACKAGE_ONLY. /// CREDUIWIN_IN_CRED_ONLY = 0x20, /// /// Credential providers should enumerate only administrators. This value is intended for User Account Control (UAC) purposes only. We recommend that external callers not set this flag. /// CREDUIWIN_ENUMERATE_ADMINS = 0x100, /// /// Only the incoming credentials for the authentication package specified by the authPackage parameter should be enumerated. /// CREDUIWIN_ENUMERATE_CURRENT_USER = 0x200, /// /// The credential dialog box should be displayed on the secure desktop. This value cannot be combined with CREDUIWIN_GENERIC. /// Windows Vista: This value is not supported until Windows Vista with SP1. /// CREDUIWIN_SECURE_PROMPT = 0x1000, /// /// The credential provider should align the credential BLOB pointed to by the refOutAuthBuffer parameter to a 32-bit boundary, even if the provider is running on a 64-bit system. /// CREDUIWIN_PACK_32_WOW = 0x10000000, } [DllImport("credui.dll", CharSet = CharSet.Unicode)] public 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, PromptForWindowsCredentialsFlags flags); [DllImport("credui.dll", CharSet = CharSet.Unicode)] public 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); }
执行语句如下:
bool save = false; int errorcode = 0; uint dialogReturn = 0; uint authPackage = 0; IntPtr outCredBuffer; uint outCredSize; NativeMethod.CREDUI_INFO credui = new NativeMethod.CREDUI_INFO(); credui.cbSize = Marshal.SizeOf(credui); credui.pszCaptionText = "Connect to your application"; credui.pszMessageText = "Enter your credentials!"; credui.hwndParent = this.Handle; //Show the dialog dialogReturn = NativeMethod.CredUIPromptForWindowsCredentials(ref credui, errorcode, ref authPackage, (IntPtr)0, 0, out outCredBuffer, out outCredSize, ref save, 0); StringBuilder userName = new StringBuilder(100); StringBuilder password = new StringBuilder(100); StringBuilder domain = new StringBuilder(100); int maxUserName = 100; int maxDomain = 100; int maxPassword = 100; if (dialogReturn == 0) { if (NativeMethod.CredUnPackAuthenticationBuffer(1, outCredBuffer, outCredSize, userName, ref maxUserName, domain, ref maxDomain, password, ref maxPassword) == true) { string str = userName.ToString(); string[] strSplit = str.Split('//'); this.tbUserName.Text = strSplit[0]; this.tbPassword.Text = password.ToString(); this.tbDomain.Text = strSplit[1]; } }
当然还能增加些执行完才能退出的功能:
/// /// demonstrate process id after creating process /// private void afterProcessStart(ref System.Diagnostics.Process proc) { rac_ProcessStarted(proc.Id); try { proc.EnableRaisingEvents = true; proc.Exited += new EventHandler(m_process_Exited); } catch (Exception e) { rac_ProcessAccessFailed(e.Message); } } /// /// Demonstrate exit process id after exiting process /// private void m_process_Exited(object sender, EventArgs e) { rac_ProcessEnded(((System.Diagnostics.Process)sender).Id); } /// /// Demonstrate end process id after ending process /// private void rac_ProcessEnded(int process) { MessageBox.Show(this, "Process " + process.ToString() + " ended.", "Process Ended", MessageBoxButtons.OK, MessageBoxIcon.Information); } /// /// Demonstrate start process id when catching the error exception /// private void rac_ProcessFailed(string error) { MessageBox.Show(this, error, "Process Failed to Start", MessageBoxButtons.OK, MessageBoxIcon.Error); } /// /// Demonstrate start process id when the process starts successfully /// private void rac_ProcessStarted(int process) { MessageBox.Show(this, "Process " + process.ToString() + " started successfully.", "Process Started", MessageBoxButtons.OK, MessageBoxIcon.Information); } /// /// Demonstrate access failed process id when the process accessed denied /// private void rac_ProcessAccessFailed(string error) { MessageBox.Show(this, error, "Process Access Denied", MessageBoxButtons.OK, MessageBoxIcon.Information); }
有退出的一些错误事件的capture,当然以上功能也能用CreateProcessWithLogonW完成,我觉得后者更容易些。。。Credential Provide是很有意思的东西,包括了一些com如何在windows开启时候新建provide.有兴趣的朋友可以去微软的相关网站去看,有详细源代码和文档。
http://msdn.microsoft.com/en-us/magazine/cc163489.aspx