【问题标题】:RegGetValue() returns wrong informationRegGetValue() 返回错误信息
【发布时间】:2015-09-08 06:41:51
【问题描述】:

我正在编写一个 VC++ 程序,它应该从注册表中返回 Java 版本以及 Java Home。代码的目的是显示单个系统中安装的所有 JRE 版本,并显示最高版本。我的系统中安装了 JRE 1.5、1.6、1.7 和 1.8。我在显示有关版本的信息方面没有问题。但是当从注册表中显示 JavaHome 时,该路径仅适用于 Java 版本 1.5、1.6 和 1.7。对于 1.8 版,它显示 JRE 7 的路径。我尝试使用 INSTALLDIR 从安装的每个 JRE 中存在的 MSI 目录显示路径。然后,JRE 8 也有问题。最初我认为这是用于显示所有 JRE 版本的循环中的错误。所以我卸载了 JRE 1.8 并检查现在是否 JRE 1.7 显示了 JRE 1.6 的路径。但是没有。 JRE 1.7 显示了正确的路径。只有当涉及到 JRE 1.8 时,它才会显示 1.7 而不是 1.8 的路径。请帮帮我。我附上下面的代码。是的,检查了 JRE 1.8 注册表中存在的路径。它确实有自己的独立路径。不是 JRE 1.7 的路径。此外,当我尝试显示 Java 1.8 路径的长度时,它显示正确的长度 36(因为它应该是 JAVA 1.8 的路径长度),即使输出显示版本 1.8 的路径为 1.7。字符串比较有问题吗?请帮我解决这个问题。

#include "StdAfx.h"
#include "targetver.h"
#include "windows.h"
#include"stdio.h"
#include "sstream"
#include"string.h"
#include"tchar.h"
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
#define BUFFER 8192
char value[BUFFER];
TCHAR** versions = new TCHAR*[];
DWORD BufferSize = BUFFER;
char str1[20];
char *javapath;
void QueryKey(HKEY hKey) 
{ 
TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
DWORD    cbName;                   // size of name string 
TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
DWORD    cchClassName = MAX_PATH;  // size of class string 
DWORD    cSubKeys=0;               // number of subkeys 
DWORD    cbMaxSubKey;              // longest subkey size 
DWORD    cchMaxClass;              // longest class string 
DWORD    cValues;              // number of values for key 
DWORD    cchMaxValue;          // longest value name 
DWORD    cbMaxValueData;       // longest value data 
DWORD    cbSecurityDescriptor; // size of security descriptor 
FILETIME ftLastWriteTime;      // last write time
DWORD i, retCode;
// Get the class name and the value count. 
retCode = RegQueryInfoKey(
hKey,                    // key handle 
achClass,                // buffer for class name 
&cchClassName,           // size of class string 
NULL,                    // reserved 
&cSubKeys,               // number of subkeys 
&cbMaxSubKey,            // longest subkey size 
&cchMaxClass,            // longest class string 
&cValues,                // number of values for this key 
&cchMaxValue,            // longest value name 
&cbMaxValueData,         // longest value data 
&cbSecurityDescriptor,   // security descriptor 
&ftLastWriteTime);       // last write time 

// Enumerate the subkeys, until RegEnumKeyEx fails.
TCHAR** versions = new TCHAR*[];
for(int i = 0; i < cSubKeys; i++)
versions[i] = new TCHAR[MAX_KEY_LENGTH];
if (cSubKeys)
{
for (i=0; i<cSubKeys; i++) 
    { 
        cbName = MAX_KEY_LENGTH;
        retCode = RegEnumKeyEx(hKey, i,
                                achKey, 
                                &cbName, 
                                NULL, 
                                NULL, 
                                NULL, 
                                &ftLastWriteTime); 
            if (retCode == ERROR_SUCCESS) 
            {
                if(strlen(achKey)==8)
                {
                    printf( "\nJava Version:");
                    _tprintf(TEXT("%s"),achKey);    
                    printf( "\nJava Home:");
                    strcpy(str1,"SOFTWARE\\\\JavaSoft\\\\Java Runtime Environment\\\\");
                    strcat(str1,achKey);
                    strcat(str1,"\\\\");
                    RegGetValue(HKEY_LOCAL_MACHINE,str1, "JavaHome", RRF_RT_ANY, NULL, (PVOID)&value, &BufferSize);
                    printf("%s",value);
                    printf("\n");
                    strcpy(versions[i],achKey);

            }
            else
                continue;
        }
    }
}
            TCHAR* big=0;
        for(i=0;i<cSubKeys;i++)
        {

            if(strlen(versions[i])==8)
            {
                _tprintf(TEXT(" versions are %s:\n"),versions[i]);
                if(versions[i]>big)
                    big=versions[i];
            }
                else
                    continue;
        }
            _tprintf(" \nLatest version in the system is %s\n",big);
}
int _tmain(int argc, _TCHAR* argv[])
{
  HKEY hKey;
LONG dwRegOPenKey = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\JavaSoft\\Java Runtime Environment\\"), 0, KEY_READ, &hKey);
if(dwRegOPenKey == ERROR_SUCCESS)
{
    printf("RegOpenKeyEx succeeded, error code %d\n", GetLastError());
    QueryKey(hKey);

} 
else
{
    printf("RegOpenKeyEx failed, error code %d\n", dwRegOPenKey);
}
    RegCloseKey(hKey);
    return 0;
}

【问题讨论】:

  • 您没有检查RegGetValue 的返回值。由于缓冲区不足而失败,因为您在最后一个参数中传递了错误的缓冲区大小。单步执行您的代码以查看发生了什么。
  • 您分配了多少个 TCHAR 指针。您的变量 version 会影响全局变量。 javapath 从未被分配。为什么BufferSize 是全球性的?您可以通过传递对结构的引用来避免全局变量吗?谁控制versions中指针的生命周期?
  • 如果是 Bufferoverflow 的问题,那为什么即使我安装了 java 1.5 或 1.6 或 1.7 的其他更新,它们都显示正确的路径?不管安装了多少版本,只有到1.8版本时,才会显示上一个版本在系统中安装的路径。 @RaymondChen
  • @user877329 TCHAR 指针 Versions[] 的数量取决于 cSubKeys 返回的值。它的大小取决于 MAX_KEY_LENGTH。对不起javapath。我为别的东西宣布了它。忘记删除了。关于 BufferSize,我只是为了方便而将其设为全局。而且我还没有编写代码来删除使用后的版本 [] 指针。稍后再做。
  • 因为 Java 1.8 的路径是最长的。请注意,您在使用后不会重置BufferSize。这意味着每次使用它时,都说缓冲区大小是上一个版本的长度。如果新版本比旧版本长,调用会失败。

标签: visual-c++


【解决方案1】:

您没有检查RegGetValue 的返回值,它会告诉您ERROR_INSUFFICIENT_BUFFER。一些调试会发现BufferSize 变量越来越小。这是因为您没有在每次调用 RegGetValue 之前将 BufferSize 变量重置为 sizeof(value),因此每次调用都会重用上一次调用留下的值,即检索到的值的大小。 Java 1.5 的调用成功,因为它是第一次调用。它适用于 Java 1.6 和 1.7,因为这些值恰好与 Java 1.5 的值长度相同。最后,它在 Java 1.8 中失败了,因为该值比其他值长。

TL;DR:在调用 RegGetValue 之前设置 BufferSize = sizeof(value);

【讨论】:

    猜你喜欢
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    相关资源
    最近更新 更多