我正在尝试写一个Windows应用程序,让我回到给定的关键所有的子项和值。 我已经编写了代码,只要在给定的键中提供了子键就可以工作,但是不能正确地枚举这些值。 它成功地枚举了没有值的子键,并以带标签树的排列方式返回结果。 但是,在枚举值时,程序会为每个存在的值(每次都是相同的随机值)给出一个随机值,然后用debugging错误崩溃。
它的预期产出基本上是:
(1) KEY (1) SUBKEY (1) SUBKEYWITHINSUBKEY Code: value1data Code: value2data Code: value3data (2) SUBKEY (1) SUBKEYWITHINSUBKEY (3) SUBKEY
…等等。
我得到的输出是这样的:
(1) KEY (1) SUBKEY (1) SUBKEYWITHINSUBKEY Code: someValue Code: someValue Code: someValue
(…然后崩溃)
随后出现以下错误:
“debugging错误!”运行时检查失败#2 – variables“valNameLen”周围的堆栈已损坏。
这个代码目前有点麻烦(我是一个Windows API的新手),但是如果任何人能够告诉我我做错了什么,或者批评我的代码风格,那么他们觉得合适,那会很好。
谢谢!
-R
/* Windows Registry Subkey Enumeration Example Based on example found at code-blue.org */ #include <windows.h> #include <stdio.h> void EnumerateValues(HKEY hKey, DWORD numValues) { DWORD dwIndex = 0; LPSTR valueName = new CHAR[64]; DWORD valNameLen; DWORD dataType; DWORD data; DWORD dataSize; for (int i = 0; i < numValues; i++) { RegEnumValue(hKey, dwIndex, valueName, &valNameLen, NULL, &dataType, (BYTE*)&data, &dataSize); dwIndex++; printf("Code: 0x%08X\n", data); } } void EnumerateSubKeys(HKEY RootKey, char* subKey, unsigned int tabs = 0) { HKEY hKey; DWORD cSubKeys; //Used to store the number of Subkeys DWORD maxSubkeyLen; //Longest Subkey name length DWORD cValues; //Used to store the number of Subkeys DWORD maxValueLen; //Longest Subkey name length DWORD retCode; //Return values of calls RegOpenKeyEx(RootKey, subKey, 0, KEY_ALL_ACCESS, &hKey); RegQueryInfoKey(hKey, // key handle NULL, // buffer for class name NULL, // size of class string NULL, // reserved &cSubKeys, // number of subkeys &maxSubkeyLen, // longest subkey length NULL, // longest class string &cValues, // number of values for this key &maxValueLen, // longest value name NULL, // longest value data NULL, // security descriptor NULL); // last write time if(cSubKeys>0) { char currentSubkey[MAX_PATH]; for(int i=0;i < cSubKeys;i++){ DWORD currentSubLen=MAX_PATH; retCode=RegEnumKeyEx(hKey, // Handle to an open/predefined key i, // Index of the subkey to retrieve. currentSubkey, // buffer to receives the name of the subkey ¤tSubLen, // size of that buffer NULL, // Reserved NULL, // buffer for class string NULL, // size of that buffer NULL); // last write time if(retCode==ERROR_SUCCESS) { for (int i = 0; i < tabs; i++) printf("\t"); printf("(%d) %s\n", i+1, currentSubkey); char* subKeyPath = new char[currentSubLen + strlen(subKey)]; sprintf(subKeyPath, "%s\\%s", subKey, currentSubkey); EnumerateSubKeys(RootKey, subKeyPath, (tabs + 1)); } } } else { EnumerateValues(hKey, cValues); } RegCloseKey(hKey); } int main() { EnumerateSubKeys(HKEY_CURRENT_USER,"SOFTWARE\\MyKeyToSearchIn"); return 0; }
以这种方式枚举键是矫枉过正的。 这只会浪费系统资源,内存,调用堆栈,并对注册表子系统施加压力。 除非需要,否则不要做。
你将有“搜索注册表”在您的应用程序? 如果是的话,只有当用户要求时才列举。 或者,如果您正在开发“注册表查看器/编辑器”,则只在需要时才展开和打开子密钥。
如果您绝对需要检索并存储所有键/值,则可以使用多个线程来枚举键。 线程的数量最初将是HKEY-主键,然后你可以有更多的线程,这取决于你在枚举键时执行的子键的数量和运行时启发式。
递归对于子键的“递归枚举”可能是也可能不是好的方法 – 你必须将递归实现的参数个数保持最小 – 把参数放在一个struct
或者放在类中。 你也可以使用相同的std::stack
。
看起来,您正在调用RegEnumValue()而不将lpcchValueName参数设置为适当的值。 该参数是[in]参数以及[out]参数。 尝试这个:
for (int i = 0; i < numValues; i++) { DWORD valNameLen = 64; //added this line to match valueName buffer size RegEnumValue(hKey, dwIndex, valueName, &valNameLen, NULL, &dataType, (BYTE*)&data, &dataSize);
RegEnumValue()的文档: http : //msdn.microsoft.com/en-us/library/ms724865 (v=vs.85) .aspx