使用C+读取注册表并输出到控制台+; 作为C++初学者,我需要你的帮助!

使用C+读取注册表并输出到控制台+; 作为C++初学者,我需要你的帮助!,c++,visual-studio,character-encoding,registry,C++,Visual Studio,Character Encoding,Registry,我目前正在开发一个程序,该程序应该能够读取注册表项及其值,并将其写入向量数组进行进一步处理 但是现在我有一个问题,UMLAUT在控制台上的输出中被神秘地显示。我怀疑这是因为使用了错误的字符编码。经过一些研究,我发现了函数“SetConsoleOutputCP(65001)”,它应该将控制台的输出设置为UTF8 不幸的是,如果使用Unicode兼容函数读取注册表,那么umlauts上的输出现在会中断。在第二种情况下,当使用ANSI兼容函数时,控制台只是隐藏UMLAUT。我在这里做错了什么?如何从注

我目前正在开发一个程序,该程序应该能够读取注册表项及其值,并将其写入向量数组进行进一步处理

但是现在我有一个问题,UMLAUT在控制台上的输出中被神秘地显示。我怀疑这是因为使用了错误的字符编码。经过一些研究,我发现了函数“SetConsoleOutputCP(65001)”,它应该将控制台的输出设置为UTF8

不幸的是,如果使用Unicode兼容函数读取注册表,那么umlauts上的输出现在会中断。在第二种情况下,当使用ANSI兼容函数时,控制台只是隐藏UMLAUT。我在这里做错了什么?如何从注册表正确读取umlauts并将其输出到控制台

另外,我想稍后将umlauts正确写入CSV文件。我也要注意这里有什么特别的吗

你可以在下面找到我的代码和一些注释。 谢谢大家的帮助

#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
    
/**
 * @brief Function to read an registry key to a vector of strings. Registry function will be called as unicode compatible version e.g. RegQueryValueExW (W at the end). This function is overloaded and exists with a different parameter list as well.
 * 
 * @param rootKey Standard hkey for the root key value
 * @param subKey Specific path for a subkey value
 * @param value The value name whose value is to be read
 * @return std::vector<std::wstring> 
 */
std::vector<std::wstring> regMultiSzToVector(HKEY rootKey, LPCWSTR subKey, LPCWSTR value) {
    HKEY hkey;
    DWORD type, size;
    std::vector<std::wstring> target;

    // Open registry key and write it to hkey variable
    if (RegOpenKeyEx(rootKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hkey) != ERROR_SUCCESS)
        exit(1);
    
    // Get type and necessary memory size
    if (RegQueryValueExW(hkey, value, NULL, &type, NULL, &size) != ERROR_SUCCESS)
        exit(1);

    if (type == REG_MULTI_SZ) {
        std::vector<wchar_t> temp(size / sizeof(wchar_t));

        if (RegQueryValueExW(hkey, value, NULL, NULL, reinterpret_cast<LPBYTE>(&temp[0]), &size) != ERROR_SUCCESS)
            exit(1);

        // Writing value from registry key to string array
        size_t index = 0;
        size_t len = wcslen(&temp[0]);
        while (len > 0) {
            target.push_back(&temp[index]);
            index += len + 1;
            len = wcslen(&temp[index]);
        }
    }
    // Closing registry key (see API)
    RegCloseKey(hkey);
    return target;
}

/**
 * @brief Function to read an registry key to a vector of strings. Registry function will be called as ansi compatible version e.g. RegQueryValueExA (A at the end). This function is overloaded and exists with a different parameter list as well.
 * 
 * @param rootKey Standard hkey for the root key value
 * @param subKey Specific path for a subkey value
 * @param value The value name whose value is to be read
 * @return std::vector<std::string> 
 */
std::vector<std::string> regMultiSzToVector(HKEY rootKey, LPCSTR subKey, LPCSTR value) {
    HKEY hkey;
    DWORD type, size;
    std::vector<std::string> target;

    // Open registry key and write it to hkey variable
    if (RegOpenKeyExA(rootKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hkey) != ERROR_SUCCESS)
        exit(1);

    // Get type and necessary memory size
    if (RegQueryValueExA(hkey, value, NULL, &type, NULL, &size) != ERROR_SUCCESS)
        exit(1);

    if (type == REG_MULTI_SZ) {
        std::vector<char> temp(size);

        if (RegQueryValueExA(hkey, value, NULL, NULL, reinterpret_cast<LPBYTE>(&temp[0]), &size) != ERROR_SUCCESS)
            exit(1);
        
        // Writing value from registry key to string array
        size_t index = 0;
        size_t len = strlen(&temp[0]);
        while (len > 0) {
            target.push_back(&temp[index]);
            index += len + 1;
            len = strlen(&temp[index]);
        }
    }
    // Closing registry key (see API)
    RegCloseKey(hkey);
    return target;
}

int main(int argc, char const* argv[]) {
    
    // Saving function return values to vectors
    std::vector<std::wstring> result1 = regMultiSzToVector(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\007", L"Counter");
    std::vector<std::string> result2 = regMultiSzToVector(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\007", "Counter");
    
    // Printing String values from first and second vector
    printf("Vector 1: \n");
    for (auto &e : result1) {
        std::wcout << e << std::endl;
    }

    printf("\n\n\n Vector 2: \n");
    for (auto &e : result2) {
        std::cout << e << std::endl;
    }
    
    return 0;
}
#包括
#包括
#包括
#包括
/**
*@brief函数将注册表项读取到字符串向量。注册表函数将被称为unicode兼容版本,例如RegQueryValueExW(末尾为W)。此函数已重载,并且存在一个不同的参数列表。
* 
*@param rootKey根键值的标准hkey
*@param子键子键值的特定路径
*@param value要读取其值的值名称
*@return std::vector
*/
向量regMultiSzToVector(HKEY根键、LPCWSTR子键、LPCWSTR值){
HKEY HKEY;
DWORD类型、大小;
std::载体靶;
//打开注册表项并将其写入hkey变量
if(RegOpenKeyEx(rootKey,subKey,0,KEY|u READ | KEY_WOW64_64KEY,&hkey)!=ERROR_SUCCESS)
出口(1);
//获取类型和必要的内存大小
if(RegQueryValueExW(hkey,value,NULL,&type,NULL,&size)!=ERROR\u SUCCESS)
出口(1);
if(type==REG\u MULTI\u SZ){
标准:向量温度(大小/尺寸(wchar__t));
if(RegQueryValueExW(hkey,value,NULL,NULL,reinterpret\u cast(&temp[0]),&size)!=错误\u成功)
出口(1);
//将值从注册表项写入字符串数组
尺寸指数=0;
尺寸长度=wcslen(&temp[0]);
而(len>0){
目标。推回(&temp[索引]);
指数+=len+1;
len=wcslen(&temp[index]);
}
}
//正在关闭注册表项(请参阅API)
雷克洛斯基(香港中学),;
回报目标;
}
/**
*@brief函数将注册表项读取到字符串向量。注册表函数将被称为ansi兼容版本,例如RegQueryValueExA(末尾为A)。此函数已重载,并且存在一个不同的参数列表。
* 
*@param rootKey根键值的标准hkey
*@param子键子键值的特定路径
*@param value要读取其值的值名称
*@return std::vector
*/
std::vector regMultiSzToVector(HKEY rootKey、LPCSTR子key、LPCSTR值){
HKEY HKEY;
DWORD类型、大小;
std::载体靶;
//打开注册表项并将其写入hkey变量
if(RegOpenKeyExA(rootKey,subKey,0,KEY|u READ | KEY_WOW64_64KEY,&hkey)!=ERROR_SUCCESS)
出口(1);
//获取类型和必要的内存大小
if(RegQueryValueExA(hkey,value,NULL,&type,NULL,&size)!=ERROR\u SUCCESS)
出口(1);
if(type==REG\u MULTI\u SZ){
标准:向量温度(大小);
if(RegQueryValueExA(hkey,value,NULL,NULL,reinterpret\u cast(&temp[0]),&size)!=错误\u成功)
出口(1);
//将值从注册表项写入字符串数组
尺寸指数=0;
尺寸长度=strlen(&temp[0]);
而(len>0){
目标。推回(&temp[索引]);
指数+=len+1;
len=strlen(&temp[索引]);
}
}
//正在关闭注册表项(请参阅API)
雷克洛斯基(香港中学),;
回报目标;
}
int main(int argc,char const*argv[]{
//将函数返回值保存到向量
std::vector result1=regMultiSzToVector(HKEY_LOCAL_MACHINE,L“SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\007”,L“Counter”);
std::vector result2=regMultiSzToVector(HKEY_LOCAL_MACHINE,“软件\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\007”,“计数器”);
//从第一个和第二个向量打印字符串值
printf(“向量1:\n”);
对于(自动和e:result1){

如果要使用CP65001(UTF-8),则还需要将UTF-16编码的
wstring
转换为UTF-8编码的字符串

下面是一个简单的方法:

我只对您的代码做了一些小的修改:

  • 更改RegOpenKeyEx->RegOpenKeyExW
  • 删除代码的非unicode部分
  • 将结果打印为原始wstring和utf-8编码的字符串以演示差异

你能不能把它简化成一个“请”。“…应该将控制台的输出设置为UTF8…”但是注册表通常是UTF-16或传统应用MBCS
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
#include <codecvt>

#pragma comment(lib, "user32")
#pragma comment(lib, "Advapi32")

// utf-8 conversion from https://stackoverflow.com/a/12903901/347508
// convert UTF-8 string to wstring
std::wstring utf8_to_wstring (const std::string& str)
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
    return myconv.from_bytes(str);
}

// convert wstring to UTF-8 string
std::string wstring_to_utf8 (const std::wstring& str)
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
    return myconv.to_bytes(str);
}

/**
 * @brief Function to read an registry key to a vector of strings. Registry function will be called as unicode compatible version e.g. RegQueryValueExW (W at the end). This function is overloaded and exists with a different parameter list as well.
 * 
 * @param rootKey Standard hkey for the root key value
 * @param subKey Specific path for a subkey value
 * @param value The value name whose value is to be read
 * @return std::vector<std::wstring> 
 */
std::vector<std::wstring> regMultiSzToVector(HKEY rootKey, LPCWSTR subKey, LPCWSTR value) {
    HKEY hkey;
    DWORD type, size;
    std::vector<std::wstring> target;

    // Open registry key and write it to hkey variable
    if (RegOpenKeyExW(rootKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hkey) != ERROR_SUCCESS)
        exit(1);
    
    // Get type and necessary memory size
    if (RegQueryValueExW(hkey, value, NULL, &type, NULL, &size) != ERROR_SUCCESS)
        exit(1);

    if (type == REG_MULTI_SZ) {
        std::vector<wchar_t> temp(size / sizeof(wchar_t));

        if (RegQueryValueExW(hkey, value, NULL, NULL, reinterpret_cast<LPBYTE>(&temp[0]), &size) != ERROR_SUCCESS)
            exit(1);

        // Writing value from registry key to string array
        size_t index = 0;
        size_t len = wcslen(&temp[0]);
        while (len > 0) {
            target.push_back(&temp[index]);
            index += len + 1;
            len = wcslen(&temp[index]);
        }
    }
    // Closing registry key (see API)
    RegCloseKey(hkey);
    return target;
}


int main(int argc, char const* argv[]) {
    
    // Saving function return values to vectors
    std::vector<std::wstring> res = regMultiSzToVector(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", L"hansi");
    
    // Printing String values from first and second vector
    printf("Result: \n");
    for (auto &e : res) {
        std::wcout << "* utf-16=" << e << std::endl;
        std::cout  << "  utf-8 =" << wstring_to_utf8(e) << std::endl;
    }

    
    return 0;
}
C:\Users\Hansi>chcp 850
Active code page: 850

C:\Users\Hansi>cl /EHsc reg_test.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29910 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

reg_test.cpp
Microsoft (R) Incremental Linker Version 14.28.29910.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:reg_test.exe
reg_test.obj

C:\Users\Hansi>reg_test.exe
Result:
* utf-16=Íl
  utf-8 =Öl
* utf-16=H÷ren
  utf-8 =H├Âren
* utf-16=T³re
  utf-8 =T├╝re
* utf-16=Da▀
  utf-8 =Daß

C:\Users\Hansi>chcp 65001
Active code page: 65001

C:\Users\Hansi>reg_test.exe
Result:
* utf-16=l
  utf-8 =Öl
* utf-16=Hren
  utf-8 =Hören
* utf-16=T  utf-8 =Türe
  utf-8 =Daß