RegSetValueEx - 路径错误,64 位,运行 作为管理员

RegSetValueEx - wrong path, 64bit, running as admin

我有一些关于注册表相关功能的问题。 我使用 RegSetValueEx 函数来创建注册表数据,但不幸的是我肯定做错了,但我不确定错误在哪里。我想在 HKEY_LOCAL_MACHINE - SOFTWARE\Microsoft\Windows\CurrentVersion\Run 中创建一个注册表,但它仅在 HKEY_LOCAL_MACHINE 键中创建数据,仅此而已。

TCHAR name[UNLEN + 1];
DWORD size = UNLEN + 1;
GetUserName((TCHAR*)name, &size);
string namep = name;
string path = "C:\Users\" + namep + "\AppData\Roaming\MyProgram\MyProgram.exe";
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Run", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
    cout << "OPENED!";
    if (RegQueryValueEx(HKEY_LOCAL_MACHINE, "MyRegistry", 0, NULL, NULL, NULL) == ERROR_FILE_NOT_FOUND)
    {
        cout << "NOT FOUND!"; // If registry not found, then create it?
        if (RegSetValueEx(HKEY_LOCAL_MACHINE, "MyRegistry", 0, REG_SZ, (const BYTE*)path.c_str(), path.size()) == ERROR_SUCCESS)
            cout << "REGISTRY WRITTEN";
        RegCloseKey(hKey);
    }
}

好的,这就是代码,有什么问题吗? 另外我想问一下怎么做,所以我不必 运行 它作为管理员来创建注册表,因为如果我不 运行 它作为管理员,它不会' t 创建注册表。 OS 的 64 位版本如何?我在 32 位上编译,所以我必须做些什么才能在 64 位机器上运行吗?

谢谢。 =)

您的代码有几个问题。

首先,不要硬编码文件路径,尤其是包含系统文件夹的路径。在这种情况下,您应该使用 SHGetFolderPath(CSIDL_APPDATA)SHGetKnownFolderPath(FOLDERID_RoamingAppData) 来发现当前用户的 AppData\Roaming 文件夹的位置。或者,如果 MyProgram.exe 是当前 运行ning 的应用程序,您可以改用 GetModuleFileName(0)

其次,非管理员用户没有 HKEY_LOCAL_MACHINE 的写入权限,只有 HKEY_CURRENT_USER。如果您需要写入 HKEY_LOCAL_MACHINE,您的应用需要 运行 提升管理员权限。

第三,你没有正确使用RegQueryValueEx()RegSetValueEx()。具体来说:

  1. 您在第一个参数中传递了错误的 HKEY。你需要把RegOpenKeyEx()返回给你的HKEY传给你

  2. 对于RegSetValueEx(),一个REG_SZ值必须包含空终止符,但是path.size()不包括空终止符,所以你需要使用size()+1 代替。

第四,您泄露了 RegOpenKeyEx() 返回给您的 HKEY,因为只有 RegQueryValueEx() 成功时您才调用 RegCloseKey()

综上所述,试试这样的东西:

if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\Microsoft\Windows\CurrentVersion\Run"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
    cout << "OPENED! ";

    LONG lRet = RegQueryValueEx(hKey, TEXT("MyRegistry"), 0, NULL, NULL, NULL);
    if (lRet == ERROR_FILE_NOT_FOUND)
    {
        cout << "NOT FOUND! ";

        // assuming you want to store the calling process's
        // filename, otherwise adjust this as needed ...
        TCHAR filename[MAX_PATH + 1];
        DWORD len = GetModuleFileName(NULL, filename, MAX_PATH);
        filename[len] = 0;

        if (RegSetValueEx(hKey, TEXT("MyRegistry"), 0, REG_SZ, (const BYTE*)filename, (len+1) * sizeof(TCHAR)) == ERROR_SUCCESS)
            cout << "WRITTEN!";
        else
            cout << "NOT WRITTEN!";
    }
    else if (lRet == 0)
    {
        cout << "FOUND!";
    }
    else
        cout << "NOT QUERIED!";

    RegCloseKey(hKey);
}
else
    cout << "NOT OPENED!";

如果您只想确保注册表包含最新的文件名,您可以省略 RegQueryValueEx() 并让 RegSetValueEx() 覆盖现有值(如果存在):

if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\Microsoft\Windows\CurrentVersion\Run"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
    cout << "OPENED! ";

    // assuming you want to store the calling process's
    // filename, otherwise adjust this as needed ...
    TCHAR filename[MAX_PATH + 1];
    DWORD len = GetModuleFileName(NULL, filename, MAX_PATH);
    filename[len] = 0;

    if (RegSetValueEx(hKey, TEXT("MyRegistry"), 0, REG_SZ, (const BYTE*)filename, (len+1) * sizeof(TCHAR)) == ERROR_SUCCESS)
        cout << "WRITTEN!";
    else
        cout << "NOT WRITTEN!";

    RegCloseKey(hKey);
}
else
    cout << "NOT OPENED!";