windows 为 RegSetValueEx() 将 std::string 转换为 const BYTE*

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/849491/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:27:09  来源:igfitidea点击:

convert std::string to const BYTE* for RegSetValueEx()

c++windowswinapistlregistry

提问by Emile Vrijdags

I have a function that gets a std::string. That function calls

我有一个获取 std::string 的函数。该函数调用

RegSetValueEx

正则集值

the 5th parameter is the value of the registry value and expects a variable of type const BYTE*. So I have to convert the std::string to const BYTE* and also give the length of the resulting array as the 6th parameter.

第 5 个参数是注册表值的值,需要一个类型为 const BYTE* 的变量。所以我必须将 std::string 转换为 const BYTE* 并将结果数组的长度作为第 6 个参数。

I have found a way to do it, but it feels ugly and I don't really understand what is going on. Here is a slimmed down version of that function:

我找到了一种方法来做到这一点,但感觉很难看,我真的不明白发生了什么。这是该功能的精简版:

void function(const std::string& newValue)
{
    HKEY keyHandle;
    if(RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("some key"),0,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
    {
        std::wstring wNewValue;
        wNewValue.assign(newValue.begin(),newValue.end());

        if (RegSetValueEx(keyHandle, TEXT("some value"), NULL, REG_SZ, (const BYTE*)(LPCTSTR)(wNewValue.c_str()), wNewValue.size()*2)==ERROR_SUCCESS)
        {
            //do something
        }
        RegCloseKey(keyHandle);
    }
}

As you can see, i first make a wide string (UNICODE is defined), then use a double cast, and for the length i have to do *2, else it will only set half of the input string.

如您所见,我首先创建一个宽字符串(定义了 UNICODE),然后使用双重转换,对于长度我必须做 *2,否则它只会设置输入字符串的一半。

Is this form of cast the normal/best way to do it?

这种形式的演员是正常/最好的方式吗?

Why the * 2, what would be a better way?

为什么是* 2,什么是更好的方法?

回答by Idan K

void function(const std::string& newValue)
{
    HKEY keyHandle;
    if(RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("some key"),0,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
    {

        if (RegSetValueExA(keyHandle, "some value", NULL, REG_SZ, (const BYTE*)newValue.c_str(), newValue.size() + 1)==ERROR_SUCCESS)
        {
                //do something
        }
        RegCloseKey(keyHandle);
    }
}

I removed the part where you convert your string to a wstring, instead you'll be using the ANSI version of RegSetValueEx explicitly.

我删除了将字符串转换为 wstring 的部分,取而代之的是,您将明确使用 ANSI 版本的 RegSetValueEx。

quote from RegSetValueEx remarks in MSDN:

引用 MSDN 中 RegSetValueEx 的评论:

If dwType is the REG_SZ, REG_MULTI_SZ, or REG_EXPAND_SZ type and the ANSI version of this function is used (either by explicitly calling RegSetValueExA or by not defining UNICODE before including the Windows.h file), the data pointed to by the lpData parameter must be an ANSI character string. The string is converted to Unicode before it is stored in the registry.

如果 dwType 是 REG_SZ、REG_MULTI_SZ 或 REG_EXPAND_SZ 类型并且使用了该函数的 ANSI 版本(通过显式调用 RegSetValueExA 或在包含 Windows.h 文件之前不定义 UNICODE),则 lpData 参数指向的数据必须是一个 ANSI 字符串。在将字符串存储在注册表中之前,该字符串将转换为 Unicode。

Also note that the cbData parameter should include the size of the null termination aswell.

另请注意, cbData 参数还应包括空终止的大小。

回答by Dario

The * 2 is because RegSetValueExwants to know the number of bytes to write und each char (wchar_t) in a wstring is two bytes wide. So the resulting byte-array has twice the size!

* 2 是因为RegSetValueEx想知道要写入的字节数,并且 wstring 中的每个字符 (wchar_t) 是两个字节宽。所以生成的字节数组的大小是原来的两倍!

回答by Oded S

Shouldn't it be wNewValue.size()*2+2? The +2 for the null character? MSDN says: The size of the information pointed to by the lpData parameter, in bytes. If the data is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ, cbData must include the size of the terminating null character or characters.

不应该wNewValue.size()*2+2吗?空字符的+2?MSDN 说: lpData 参数指向的信息的大小,以字节为单位。如果数据的类型为 REG_SZ、REG_EXPAND_SZ 或 REG_MULTI_SZ,则 cbData 必须包括一个或多个终止空字符的大小。

回答by david

You could also copy the unicode string into a byte array:

您还可以将 unicode 字符串复制到字节数组中:

LPWSTR pData = L"SampleGrabber";
int dwSize = wcslen(pData)*sizeof(TCHAR);
BYTE slump[256];
memset((void*) slump, 0, 256*sizeof(BYTE));
memcpy((void*) slump, (const void *) pData, dwSize*sizeof(BYTE));

globit = RegSetValueEx(hKey, NULL, 0, REG_SZ, (const BYTE*) slump, dwSize);

If you had the misfortune to be writing code for a WINCE 5.0 device and it lacked part of the regedit API.

如果您不幸为 WINCE 5.0 设备编写代码并且缺少 regedit API 的一部分。