使用CredUICmdLinePromptForCredentials时输出十六进制值的问题
CredUICmdLinePromptForCredentials输出用户名/密码为十六进制值的问题修复
问题描述
调用CredUICmdLinePromptForCredentials函数获取用户名和密码后,直接输出对应变量时显示的是十六进制地址值,而非实际输入的字符串。仅通过访问数组首元素并转换为char类型,才能显示单个字符。
原代码
#include <windows.h> #include <wincred.h> #include <iostream> #pragma comment(lib,"Credui.lib") int main() { DWORD dwErr; WCHAR szUserName[CREDUI_MAX_USERNAME_LENGTH] = {NULL}; WCHAR szPassword[CREDUI_MAX_PASSWORD_LENGTH] = {NULL}; BOOL fSave; DWORD dwAuthError=1223; dwErr = CredUICmdLinePromptForCredentials( L".", NULL, dwAuthError, (PWSTR)&szUserName, CREDUI_MAX_USERNAME_LENGTH + 1, (PWSTR)&szPassword, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, CREDUI_FLAGS_DO_NOT_PERSIST|CREDUI_FLAGS_EXCLUDE_CERTIFICATES ); if (dwErr == ERROR_SUCCESS) { std::cout << "User Name: " << szUserName << std::endl; std::cout << "Password : " << szPassword << std::endl; } else if (dwErr == ERROR_CANCELLED) { std::cout << "User cancelled the operation." << std::endl; } else { std::cout << "Error occurred: " << dwErr << std::endl; } return 0; }
运行结果
User Name: 000000C5402FED80 Password : 000000C5402FF1B0
测试代码片段
将ERROR_SUCCESS分支修改为以下代码时,可正常显示输入字符串的首字符:
std::cout << "User Name: " << char(szUserName[0]) << std::endl; std::cout << "Password : " << char(szPassword[0]) << std::endl;
原因分析
- 宽字符输出不匹配:
szUserName和szPassword是WCHAR(UTF-16宽字符)类型数组,std::cout默认处理char窄字符,直接输出宽字符数组名会被解析为指针地址,因此打印出十六进制值。 - 函数参数传递错误:
CredUICmdLinePromptForCredentials要求传入PWSTR(即WCHAR*)类型的缓冲区指针,但代码中错误地使用(PWSTR)&szUserName——数组名本身会退化为指向首元素的指针,取地址后变成WCHAR**类型,导致函数写入内存的位置错误,属于未定义行为。
解决方案
1. 修正函数参数
将调用函数时的(PWSTR)&szUserName改为szUserName,(PWSTR)&szPassword改为szPassword,数组名自动转换为符合要求的PWSTR指针。
2. 正确输出宽字符
有两种可靠方式:
- 方式一:使用std::wcout输出
std::wcout专门用于处理宽字符输出,搭配宽字符字符串字面量(前缀L)即可正常显示:std::wcout << L"User Name: " << szUserName << std::endl; std::wcout << L"Password : " << szPassword << std::endl; - 方式二:转换为窄字符输出
如果输入仅包含ASCII字符,可通过WideCharToMultiByte函数将宽字符转换为窄字符后使用std::cout输出,示例代码如下:char userName[CREDUI_MAX_USERNAME_LENGTH] = {0}; WideCharToMultiByte(CP_ACP, 0, szUserName, -1, userName, sizeof(userName), NULL, NULL); char password[CREDUI_MAX_PASSWORD_LENGTH] = {0}; WideCharToMultiByte(CP_ACP, 0, szPassword, -1, password, sizeof(password), NULL, NULL); std::cout << "User Name: " << userName << std::endl; std::cout << "Password : " << password << std::endl;
修正后完整代码
#include <windows.h> #include <wincred.h> #include <iostream> #pragma comment(lib,"Credui.lib") int main() { DWORD dwErr; WCHAR szUserName[CREDUI_MAX_USERNAME_LENGTH] = {0}; WCHAR szPassword[CREDUI_MAX_PASSWORD_LENGTH] = {0}; BOOL fSave; DWORD dwAuthError = 1223; dwErr = CredUICmdLinePromptForCredentials( L".", NULL, dwAuthError, szUserName, CREDUI_MAX_USERNAME_LENGTH + 1, szPassword, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES ); if (dwErr == ERROR_SUCCESS) { std::wcout << L"User Name: " << szUserName << std::endl; std::wcout << L"Password : " << szPassword << std::endl; } else if (dwErr == ERROR_CANCELLED) { std::cout << "User cancelled the operation." << std::endl; } else { std::cout << "Error occurred: " << dwErr << std::endl; } return 0; }
内容的提问来源于stack exchange,提问作者winapiadmin
相关产品推荐
相关产品推荐

