繁体   English   中英

使用 C++ 读取注册表和 output 到控制台

[英]Read registry and output to console with C++

作为 C++ 初学者,我需要你的帮助!

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

但是现在我有一个问题,即控制台上的 output 中神秘地显示变音符号。 我怀疑这是因为使用了错误的字符编码。 经过一番研究,我发现了 function "SetConsoleOutputCP(65001)",它应该将控制台的 output 设置为 UTF8。

不幸的是,如果使用 Unicode 兼容函数来读取注册表,则 output 现在会在变音符号上中断。 在第二种情况下,控制台在使用 ANSI 兼容功能时只是隐藏了变音符号。 我在这里做错了什么,如何从注册表和 output 正确读取变音符号到控制台?

另外,我想稍后将元音变音正确写入 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;
}

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

这是一个简单的方法: https://stackoverflow.com/a/12903901/347508

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

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

#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;
}

我用于测试的注册表项

Output:

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ß

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM