您的位置:首页 > 其它

通过credential provide获得权限启动程序

2011-06-01 10:54 225 查看
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
        {
            /// <summary>
            /// 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.
            /// </summary>
            CREDUIWIN_GENERIC = 0x1,
            /// <summary>
            /// The Save check box is displayed in the dialog box.
            /// </summary>
            CREDUIWIN_CHECKBOX = 0x2,
            /// <summary>
            /// 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.
            /// </summary>
            CREDUIWIN_AUTHPACKAGE_ONLY = 0x10,
            /// <summary>
            /// 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.
            /// </summary>
            CREDUIWIN_IN_CRED_ONLY = 0x20,
            /// <summary>
            /// 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.
            /// </summary>
            CREDUIWIN_ENUMERATE_ADMINS = 0x100,
            /// <summary>
            /// Only the incoming credentials for the authentication package specified by the authPackage parameter should be enumerated.
            /// </summary>
            CREDUIWIN_ENUMERATE_CURRENT_USER = 0x200,
            /// <summary>
            /// 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.
            /// </summary>
            CREDUIWIN_SECURE_PROMPT = 0x1000,
            /// <summary>
            /// 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.
            /// </summary>
            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];
                    }
                }




当然还能增加些执行完才能退出的功能:

/// <summary>
        /// demonstrate process id after creating process 
        /// </summary>
        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);
            }
        }

        /// <summary>
        /// Demonstrate exit process id after exiting process
        /// </summary>
        private void m_process_Exited(object sender, EventArgs e)
        {
            rac_ProcessEnded(((System.Diagnostics.Process)sender).Id);
        }

        /// <summary>
        /// Demonstrate end process id after ending process
        /// </summary>
        private void rac_ProcessEnded(int process)
        {
            MessageBox.Show(this, "Process " + process.ToString() + " ended.", "Process Ended", 
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>
        /// Demonstrate start process id when catching the error exception
        /// </summary>
        private void rac_ProcessFailed(string error)
        {
            MessageBox.Show(this, error, "Process Failed to Start", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        /// <summary>
        /// Demonstrate start process id when the process starts successfully 
        /// </summary>
        private void rac_ProcessStarted(int process)
        {
            MessageBox.Show(this, "Process " + process.ToString() + " started successfully.",
                "Process Started", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>
        /// Demonstrate access failed process id when the process accessed denied
        /// </summary>
        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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: