C++ C++;读取注册表

C++ C++;读取注册表,c++,windows,registry,npapi,registrykey,C++,Windows,Registry,Npapi,Registrykey,我尝试在我的NPAPI插件中读取注册表: bool ScriptablePluginObject::Invoke(NPObject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) { ScriptablePluginObject *thisObj = (ScriptablePluginObject*) obj; char* name

我尝试在我的NPAPI插件中读取注册表:

bool ScriptablePluginObject::Invoke(NPObject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) {
    ScriptablePluginObject *thisObj = (ScriptablePluginObject*) obj;
    char* name                      = npnfuncs->utf8fromidentifier(methodName);
    LPCWSTR game_path               = getRegKey(L"SOFTWARE\\World of RPG", L"Path");

    MessageBox(NULL, game_path, L"Debugging", MB_TOPMOST);

    /* ... */
}

LPCWSTR ScriptablePluginObject::getRegKey(LPCWSTR location, LPCWSTR name) {
    HKEY hKey;
    LPBYTE folder   = new BYTE[MAX_PATH];
    DWORD dwSize    = sizeof(folder);
    long registry   = RegOpenKeyEx(HKEY_LOCAL_MACHINE, location, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
    long entry      = RegQueryValueEx(hKey, name, NULL, REG_NONE, folder, &dwSize);

    if(registry != ERROR_SUCCESS) {
        return L"Error1";
    }

    if(entry != ERROR_SUCCESS) {
        return L"Error2";
    }

    RegCloseKey(hKey);
    folder[dwSize / sizeof(folder[0])] = '\0';
    return (LPCWSTR) folder;
}
但它会在每次调用时返回
Error2
。我尝试了很多改变:

  • 更改路径(使用开始和/或结束
    \\
  • 改变参数
我想获取
HKEY\U LOCAL\U MACHINE\SOFTWARE\World of RPG\Path的路径

有人能帮我吗?我做错了什么?

getRegKey()
中,您的
文件夹变量是指针,因此
sizeof(folder)
是4(如果编译为32位)或8(如果编译为64位)。因此,
RegQueryValueEx()
失败,出现
错误\u更多\u数据
错误代码

您还为阵列使用了错误的数据类型。您需要使用
WCHAR
而不是
BYTE

更改此项:

LPBYTE folder   = new BYTE[MAX_PATH];
DWORD dwSize    = sizeof(folder);
为此:

LPWSTR folder   = new WCHAR[MAX_PATH];
DWORD dwSize    = sizeof(WCHAR) * MAX_PATH;
话虽如此,您正在泄漏文件夹所指向的内存,因为您从未删除它。

getRegKey()
中,您的
文件夹变量是指针,因此
sizeof(folder)
是4(如果编译为32位)或8(如果编译为64位)。因此,
RegQueryValueEx()
失败,出现
错误\u更多\u数据
错误代码

您还为阵列使用了错误的数据类型。您需要使用
WCHAR
而不是
BYTE

更改此项:

LPBYTE folder   = new BYTE[MAX_PATH];
DWORD dwSize    = sizeof(folder);
为此:

LPWSTR folder   = new WCHAR[MAX_PATH];
DWORD dwSize    = sizeof(WCHAR) * MAX_PATH;

话虽如此,您正在泄漏
文件夹所指向的内存,因为您从未
删除[]
它。

以下是我在上面的评论中提到的示例:

#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

LSTATUS ReadRegistry ( LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, DWORD *pBufferSize );

int _tmain(int argc, _TCHAR* argv[])
{
    const int BUFFER_SIZE = 1024;

    WCHAR sBuffer[BUFFER_SIZE]; // 2048 bytes
    DWORD nBufferSize = BUFFER_SIZE * sizeof ( WCHAR );

    ZeroMemory ( sBuffer, nBufferSize );
    LSTATUS nResult = ReadRegistry ( L"SOFTWARE\\7-Zip", L"Path64",
        sBuffer, &nBufferSize );

    // check nResult for ERROR_SUCCESS to know if the call succeeded or not

    return 0;
}

LSTATUS ReadRegistry ( LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, LPDWORD pBufferSize )
{
    HKEY hKey;
    LSTATUS nResult = ::RegOpenKeyEx ( HKEY_LOCAL_MACHINE, sPath,
        0, KEY_READ | KEY_WOW64_64KEY, &hKey );

    if ( nResult == ERROR_SUCCESS )
    {
        nResult = ::RegQueryValueEx ( hKey, sKey, NULL, NULL,
            (LPBYTE) pBuffer, pBufferSize );

        RegCloseKey ( hKey );
    }

    return ( nResult );
}
#包括
#包括
#包括
#包括
LSTATUS ReadRegistry(LPCWSTR sPath、LPCWSTR sKey、LPWSTR pBuffer、DWORD*pBufferSize);
int _tmain(int argc,_TCHAR*argv[]
{
const int BUFFER_SIZE=1024;
WCHAR sBuffer[BUFFER_SIZE];//2048字节
DWORD nBufferSize=缓冲区大小*sizeof(WCHAR);
零内存(sBuffer,nBufferSize);
LSTATUS nResult=ReadRegistry(L“软件\\7-Zip”,L“路径64”,
sBuffer和nbuffer尺寸);
//检查nResult是否出错\u SUCCESS以了解呼叫是否成功
返回0;
}
LSTATUS ReadRegistry(LPCWSTR sPath、LPCWSTR sKey、LPWSTR pBuffer、LPDWORD pBufferSize)
{
HKEY HKEY;
LSTATUS nResult=::RegOpenKeyEx(HKEY_LOCAL_机器,sPath,
0,键|读|键| WOW64 |键和hKey);
如果(nResult==错误\u成功)
{
nResult=::RegQueryValueEx(hKey、sKey、NULL、NULL、,
(LPBYTE)pBuffer,pBufferSize);
雷克洛斯基(香港中学),;
}
返回(nResult);
}
请注意,
ReadRegistry
函数是如何不分配内存的——它需要一个缓冲区并用数据填充它。如果总是让调用者分配内存,那么处理内存就容易多了。如果被调用者分配内存,调用者可能不知道如何分配内存,也可能不知道如何释放内存。(当然,您总是可以假设使用
new
delete
,但如果只有一方一致地这样做,事情就会简单一些。如果调用者分配内存,它就会知道如何释放内存。被调用者只需要将数据放在分配的空间中

另外,请注意在继续下一次调用之前如何检查API函数的返回值-这很重要,因为这会告诉您是否获得了有用的注册表句柄,以及是否需要关闭它


(此示例实际上是C,不是C++,但仍然适用)。

#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

LSTATUS ReadRegistry ( LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, DWORD *pBufferSize );

int _tmain(int argc, _TCHAR* argv[])
{
    const int BUFFER_SIZE = 1024;

    WCHAR sBuffer[BUFFER_SIZE]; // 2048 bytes
    DWORD nBufferSize = BUFFER_SIZE * sizeof ( WCHAR );

    ZeroMemory ( sBuffer, nBufferSize );
    LSTATUS nResult = ReadRegistry ( L"SOFTWARE\\7-Zip", L"Path64",
        sBuffer, &nBufferSize );

    // check nResult for ERROR_SUCCESS to know if the call succeeded or not

    return 0;
}

LSTATUS ReadRegistry ( LPCWSTR sPath, LPCWSTR sKey, LPWSTR pBuffer, LPDWORD pBufferSize )
{
    HKEY hKey;
    LSTATUS nResult = ::RegOpenKeyEx ( HKEY_LOCAL_MACHINE, sPath,
        0, KEY_READ | KEY_WOW64_64KEY, &hKey );

    if ( nResult == ERROR_SUCCESS )
    {
        nResult = ::RegQueryValueEx ( hKey, sKey, NULL, NULL,
            (LPBYTE) pBuffer, pBufferSize );

        RegCloseKey ( hKey );
    }

    return ( nResult );
}
#包括
#包括
#包括
#包括
LSTATUS ReadRegistry(LPCWSTR sPath、LPCWSTR sKey、LPWSTR pBuffer、DWORD*pBufferSize);
int _tmain(int argc,_TCHAR*argv[]
{
const int BUFFER_SIZE=1024;
WCHAR sBuffer[BUFFER_SIZE];//2048字节
DWORD nBufferSize=缓冲区大小*sizeof(WCHAR);
零内存(sBuffer,nBufferSize);
LSTATUS nResult=ReadRegistry(L“软件\\7-Zip”,L“路径64”,
sBuffer和nbuffer尺寸);
//检查nResult是否出错\u SUCCESS以了解呼叫是否成功
返回0;
}
LSTATUS ReadRegistry(LPCWSTR sPath、LPCWSTR sKey、LPWSTR pBuffer、LPDWORD pBufferSize)
{
HKEY HKEY;
LSTATUS nResult=::RegOpenKeyEx(HKEY_LOCAL_机器,sPath,
0,键|读|键| WOW64 |键和hKey);
如果(nResult==错误\u成功)
{
nResult=::RegQueryValueEx(hKey、sKey、NULL、NULL、,
(LPBYTE)pBuffer,pBufferSize);
雷克洛斯基(香港中学),;
}
返回(nResult);
}
请注意,
ReadRegistry
函数如何不分配内存-它需要一个缓冲区并用数据填充它。如果总是让调用者分配内存,那么处理内存就容易多了。如果被调用者分配内存,调用者可能不知道内存是如何分配的,也可能不知道如何释放内存。(当然,您总是可以假设使用
new
delete
,但如果只有一方一致地这样做,事情就会简单一些。如果调用者分配内存,它就会知道如何释放内存。被调用者只需要将数据放在分配的空间中

另外,请注意在继续下一次调用之前如何检查API函数的返回值-这很重要,因为这会告诉您是否获得了有用的注册表句柄,以及是否需要关闭它


(这个示例实际上是C,不是C++,但它仍然适用)。

尝试检查实际值以查看其失败的原因。如果不检查返回值,则无法查看其未返回的原因
ERROR\u SUCCESS
。它返回其他值,这些值有意义,但只有当您实际查看它以查看其包含的内容时,意义才重要。您当前编写的代码显示“如果它不返回成功,请给我一些ErrorX的无意义文本。”相反,保存返回值,并检查保存的值与<代码> ErrRoOxEngult。我在C++上是新的。我已经尝试将long值转换为LPCWSTR。