使用CredWriteW在Windows存储凭据显示为中文的问题求助
排查思路与修复方案:CredWriteW添加凭据显示中文乱码
首先,你遇到的问题核心是宽字符API与ANSI字符串的编码不匹配,这是Windows编程里很容易踩的经典坑之一。
排查步骤
- 确认API字符版本匹配:Windows API分A(ANSI)和W(宽字符/UTF-16)两个版本,
CredWriteW要求所有字符串参数(TargetName、UserName等)必须是宽字符类型。你用(LPWSTR)"testaccount"这种强制转换,本质是把单字节的ASCII序列直接当作双字节的UTF-16解析,必然出现乱码(也就是你看到的中文)。 - 检查结构体成员类型:查看
CREDENTIALW的定义,TargetName、UserName都是LPWSTR类型,你传入的char*和它类型完全不匹配,这是问题的根源。 - 对比手动添加场景:手动在凭据管理器添加时,系统会正确处理输入的字符串编码(默认是宽字符),所以不会出现乱码,这也侧面验证了是代码里的编码转换逻辑出错。
修复方案
你可以选择以下两种方案之一解决问题:
方案1:改用ANSI版本的API
直接使用CredWriteA和CREDENTIALA结构体,适配你当前的char*字符串:
#include <iostream> #include "windows.h" #include "wincred.h" #pragma hdrstop using namespace std; int main() { const char* password = "testpass"; CREDENTIALA creds = { 0 }; // 改用ANSI版本结构体 creds.Type = CRED_TYPE_GENERIC; creds.TargetName = "testaccount"; // 直接使用char*,无需强制转换 creds.CredentialBlobSize = strlen(password) + 1; creds.CredentialBlob = (LPBYTE)password; creds.Persist = CRED_PERSIST_LOCAL_MACHINE; creds.UserName = "testuser"; // 同样使用char* BOOL result = CredWriteA(&creds, 0); // 调用ANSI版本API if (result != TRUE) { cout << "Some error occurred, error code: " << GetLastError() << endl; } else { cout << "Stored the password successfully" << endl; } return 0; }
方案2:正确使用宽字符版本的API
将所有字符串改为宽字符类型(用L""前缀,或者通过MultiByteToWideChar转换ANSI字符串),严格匹配CredWriteW的要求:
#include <iostream> #include "windows.h" #include "wincred.h" #pragma hdrstop using namespace std; int main() { const wchar_t* password = L"testpass"; // 使用宽字符密码 CREDENTIALW creds = { 0 }; creds.Type = CRED_TYPE_GENERIC; creds.TargetName = L"testaccount"; // 直接用宽字符字符串 creds.CredentialBlobSize = wcslen(password) * sizeof(wchar_t) + sizeof(wchar_t); // 正确计算宽字符字节长度 creds.CredentialBlob = (LPBYTE)password; creds.Persist = CRED_PERSIST_LOCAL_MACHINE; creds.UserName = L"testuser"; // 宽字符用户名 BOOL result = CredWriteW(&creds, 0); if (result != TRUE) { cout << "Some error occurred, error code: " << GetLastError() << endl; } else { cout << "Stored the password successfully" << endl; } return 0; }
额外建议:添加GetLastError()的输出,当CredWrite调用失败时可以获取具体错误码,帮助快速定位其他潜在问题。
内容的提问来源于stack exchange,提问作者harshc
相关产品推荐
相关产品推荐

