RegSetValueEx - 错误的路径,64位,以管理员身份运行

时间:2015-03-31 20:35:45

标签: c++ visual-studio-2013 registry

我有一些与注册表相关的功能相关的问题。 我使用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);
    }
}

好的,这就是代码,出了什么问题? 另外我想问一下如何做,所以我不必以管理员的身份运行它来创建注册表,因为如果我不以管理员的身份运行它,它就不会创建注册表。 64位版本的操作系统如何?我在32位编译,所以有什么我必须做的,所以它适用于64位机器吗?

感谢。 =)

1 个答案:

答案 0 :(得分:2)

您的代码存在一些问题。

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

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

第三,您没有正确使用RegQueryValueEx()RegSetValueEx()。具体做法是:

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

  2. 对于RegSetValueEx()
  3. REG_SZ值必须包含空终止符,但path.size()不计算空终止符,因此您需要使用size()+1代替

  4. 第四,您正在泄露HKEY返回给您的RegOpenKeyEx(),因为只有在RegCloseKey()成功时才拨打RegQueryValueEx()

    所有这些都说,尝试更像这样的事情:

    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!";