You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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;

原因分析

  1. 宽字符输出不匹配:szUserName和szPassword是WCHAR(UTF-16宽字符)类型数组,std::cout默认处理char窄字符,直接输出宽字符数组名会被解析为指针地址,因此打印出十六进制值。
  2. 函数参数传递错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 17:33:09