|
常数和结构声明
对于许多 Win32 API 调用,您都需要一组支持常数(在本文中,我选择将其表示为枚举),并且还可能需要一个或两个结构声明。凭据 API 也遵循上述一般性规则,并且需要多种常数和一个结构。在我的 .NET 类中,我添加了一个枚举来表示 CredUIPromptForCredentials 的标志参数,添加了另外一个枚举来表示全部三个凭据 API 调用可能产生的返回代码集,并添加了一个 CREDUI_INFO 结构声明。
Public Enum CREDUI_FLAGS INCORRECT_PASSWORD = &H1 DO_NOT_PERSIST = &H2 REQUEST_ADMINISTRATOR = &H4 EXCLUDE_CERTIFICATES = &H8 REQUIRE_CERTIFICATE = &H10 SHOW_SAVE_CHECK_BOX = &H40 ALWAYS_SHOW_UI = &H80 REQUIRE_SMARTCARD = &H100 PASSWORD_ONLY_OK = &H200 VALIDATE_USERNAME = &H400 COMPLETE_USERNAME = &H800 PERSIST = &H1000 SERVER_CREDENTIAL = &H4000 EXPECT_CONFIRMATION = &H20000 GENERIC_CREDENTIALS = &H40000 USERNAME_TARGET_CREDENTIALS = &H80000 KEEP_USERNAME = &H100000 End Enum Public Enum CredUIReturnCodes As Integer NO_ERROR = 0 ERROR_CANCELLED = 1223 ERROR_NO_SUCH_LOGON_SESSION = 1312 ERROR_NOT_FOUND = 1168 ERROR_INVALID_ACCOUNT_NAME = 1315 ERROR_INSUFFICIENT_BUFFER = 122 ERROR_INVALID_PARAMETER = 87 ERROR_INVALID_FLAGS = 1004 End Enum Public Structure CREDUI_INFO Public cbSize As Integer Public hwndParent As IntPtr Public pszMessageText As String Public pszCaptionText As String Public hbmBanner As IntPtr End Structure
为 API 调用创建包装函数
此步骤不是必需的。您可以简单地将 API 声明为 Public(而不是像我的代码一样,使其声明为 Private),并从应用程序中直接调用它们。不过,我发现调用 API 经常需要完成一些工作,因而我喜欢通过包装 API 调用来向代码的最终用户隐藏这些调用细节。
Private Const MAX_USER_NAME As Integer = 100 Private Const MAX_PASSWORD As Integer = 100 Private Const MAX_DOMAIN As Integer = 100 Public Shared Function PromptForCredentials( _ ByRef creditUI As CREDUI_INFO, _ ByVal targetName As String, _ ByVal netError As Integer, _ ByRef userName As String, _ ByRef password As String, _ ByRef save As Boolean, _ ByVal flags As CREDUI_FLAGS) _ As CredUIReturnCodes Dim saveCredentials As Integer Dim user As New StringBuilder(MAX_USER_NAME) Dim pwd As New StringBuilder(MAX_PASSWORD) saveCredentials = Convert.ToInt32(save) creditUI.cbSize = Marshal.SizeOf(creditUI) Dim result As CredUIReturnCodes result = CredUIPromptForCredentials( _ creditUI, targetName, _ IntPtr.Zero, netError, _ user, MAX_USER_NAME, _ pwd, MAX_PASSWORD, _ saveCredentials, flags) save = Convert.ToBoolean(saveCredentials) userName = user.ToString password = pwd.ToString Return result End Function Public Shared Function ParseUserName(ByVal userName As String, _ ByRef userPart As String, _ ByRef domainPart As String) _ As CredUIReturnCodes Dim user As New StringBuilder(MAX_USER_NAME) Dim domain As New StringBuilder(MAX_DOMAIN) Dim result As CredUIReturnCodes result = CredUIParseUserName(userName, _ user, MAX_USER_NAME, _ domain, MAX_DOMAIN) userPart = user.ToString() domainPart = domain.ToString() Return result End Function Public Shared Function ConfirmCredentials(ByVal target As String, _ ByVal confirm As Boolean) As CredUIReturnCodes Return CredUIConfirmCredentials(target, confirm) End Function 注:为了便于使用,我已经使我的所有函数都成为 Shared/Static 函数。因为它们没有将任何信息存储为类级别属性或变量,所以实在没有任何理由强制开发人员在调用这些函数之前创建类实例。
在声明并包装这些 API 之后,我建议将代码放入它自己的程序集中,方法是在 Microsoft?Visual Studio?.NET 中创建一个 Class Library 项目(就像我在本文随附的示例中所做的那样)并且将代码编译为它的唯一类。通过根据这些代码创建程序集,以后可以从需要这些代码的任何项目中进行引用。但是,如果您愿意,也可直接将该类包含到您的项目中。
|