'Python winreg looping through sub-keys
I'm able to successfully retrieve the 5 sub-keys from my windows 7 machine registry hive "HKEY_LOCAL_MACHINE" with the code below.
from _winreg import *
try:
i = 0
while True:
subkey = EnumKey(HKEY_LOCAL_MACHINE, i)
print subkey
i += 1
except WindowsError:
pass
My question is, how do I then enumerate the keys under those? I want to end up listing all the keys in the SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged folder but I can't figure out how to step my way down there.
In response to the first comment, I ran this code on my machine and while it didn't error out, it didn't produce results.
from _winreg import *
aReg = ConnectRegistry(None,HKEY_LOCAL_MACHINE)
aKey = OpenKey(aReg, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged")
for i in range(1024):
try:
keyname = EnumKey(aKey, i)
asubkey = OpenKey(aKey, keyname)
val = QueryValueEx(asubkey, "Description")
print val
except WindowsError:
break
A regedit or reg query shows 6 values in that folder but I can't get a python script to show me those six.
Solution 1:[1]
Just want to add a perhaps more pythonic solution.
from _winreg import *
from contextlib import suppress
import itertools
def subkeys(path, hkey=HKEY_LOCAL_MACHINE, flags=0):
with suppress(WindowsError), OpenKey(hkey, path, 0, KEY_READ|flags) as k:
for i in itertools.count():
yield EnumKey(k, i)
You can now access the keys as expected
for key in subkeys(r'path\to\your\key'):
print key
For python versions < 3.4 that lack suppress(), I recommend adding it to your project:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
Note: If you have trouble reading some values you might be reading from the wrong registry view. Pass
KEY_WOW64_64KEYorKEY_WOW64_32KEYto theflagsparameter). UsingOpenKey()as context manager was introduced in python 2.6.
Solution 2:[2]
Does something like this work?
import _winreg
def subkeys(key):
i = 0
while True:
try:
subkey = _winreg.EnumKey(key, i)
yield subkey
i+=1
except WindowsError:
break
def traverse_registry_tree(key=_winreg.HKEY_LOCAL_MACHINE, tabs=0):
for k in subkeys(key):
print '\t'*tabs + str(k)
traverse_registry_tree(k, tabs+1)
Solution 3:[3]
I don't have the same registry keys to search but the following code will list all the subkeys in HKEY_LOCAL_MACHINE\Software. I think if you change the value of the keyVal string to your directory it will work.
The try ... except bloc is this way because EnumKey will fail. I didn't do it as a for loop because I dont know how to get the correct length of aKey.
keyVal = r"Software"
aKey = OpenKey(HKEY_LOCAL_MACHINE, keyVal, 0, KEY_ALL_ACCESS)
try:
i = 0
while True:
asubkey = EnumKey(aKey, i)
print(asubkey)
i += 1
except WindowsError:
pass
Solution 4:[4]
This works, and prints out the list of all subkeys (fixed version of @Broseph's answer)
import _winreg
def subkeys(key):
i = 0
while True:
try:
subkey = _winreg.EnumKey(key, i)
yield subkey
i+=1
except WindowsError as e:
break
def traverse_registry_tree(hkey, keypath, tabs=0):
key = _winreg.OpenKey(hkey, keypath, 0, _winreg.KEY_READ)
for subkeyname in subkeys(key):
print '\t'*tabs + subkeyname
subkeypath = "%s\\%s" % (keypath, subkeyname)
traverse_registry_tree(hkey, subkeypath, tabs+1)
keypath = r"SOFTWARE\\Microsoft\\Windows"
traverse_registry_tree(_winreg.HKEY_LOCAL_MACHINE, keypath)
Solution 5:[5]
For iterating through keys of Windows registry, you would need EnumKey() from _winreg module. Given below is the definition for EnumKey() :-
def EnumKey(key, index):
- Enumerates subkeys of an open registry key.
- key is an already open key, or any one of the predefined HKEY_* constants.
- index is an integer that identifies the index of the key to retrieve.
Note that this method, takes index as an argument, and will provide you the key only for the given index. Therefore, in order to get all the keys, you need to increment the index by one and continue until you encounter WindowsError.
Refer to this post for a detailed understanding on the same. The Github link for the code can be found in the post.
Solution 6:[6]
this is just an improvement on @sparrowt's answer. His answer failed when I tried it, but think it was on the right track. This will give tree below keypath. Sorry for changing some variable and method names in rewrite, but just trying to post this quick. In my code, I put hkey as global variable bc I expect to only be working with one hkey at a time.
import winreg
import itertools
hkey = winreg.HKEY_LOCAL_MACHINE
def list_subkeys(path, hkey_set=None):
global hkey
if not hkey_set:
hkey_set = hkey
try:
registry_key = winreg.OpenKey(hkey_set, path, 0, winreg.KEY_READ)
for i in itertools.count():
yield winreg.EnumKey(registry_key, i)
winreg.CloseKey(registry_key)
except Exception as ex:
if str(ex) != '[WinError 259] No more data is available':
print(str(ex))
try:
winreg.CloseKey(registry_key)
except:
pass
return []
def traverse_registry_tree(keypath, levels=None, hkey_set=None):
global hkey
if not levels:
levels = []
if not hkey_set:
hkey_set = hkey
subkeys = list(list_subkeys(keypath, hkey_set))
for subkeyname in subkeys:
subkeypath = "%s\\%s" % (keypath, subkeyname)
levels.append(subkeypath)
levels.extend([r for r in traverse_registry_tree(subkeypath, levels, hkey_set) if r not in levels])
del subkeys
return levels
Solution 7:[7]
I made this code. It prints the whole subtree of a key. But first, I would like to say that the following code does not use the original naming:
[key]
|-[key]
| ?-[value1: data]
|-[value1: data]
?-[value2: data]
I use the following scheme
[folder]
|-[subfolder]
| ?-[key1: value]
|-[key1: value]
?-[key2: value]
import winreg
def padding(cnt):
str = ""
for i in range(cnt):
str += '\t'
return str
def recursive_visit(folder, i):
subfolders_count, subkeys_count, modified = winreg.QueryInfoKey(folder)
for subfolder_index in range(subfolders_count):
try:
subfolder_name = winreg.EnumKey(folder, subfolder_index)
print(padding(i)+subfolder_name+":")
with winreg.OpenKeyEx(folder, subfolder_name) as subfolder:
recursive_visit(subfolder, i+1)
except (WindowsError, KeyError, ValueError):
print("Error reading " + folder)
for subkey_index in range(subkeys_count):
print(padding(i)+str(winreg.EnumValue(folder, subkey_index)))
globals()["cnt"] += 1
cnt = 0 #how many keys we visited
### ENTER INPUT HERE
root = winreg.HKEY_LOCAL_MACHINE
folder = r"SYSTEM\Setup\FirstBoot\Services"
###
with winreg.OpenKey(root, folder) as reg:
keys_count, values_count, modified = winreg.QueryInfoKey(reg)
print("Subfolders: " + str(keys_count) + " Subkeys: " + str(values_count))
recursive_visit(reg, 1)
print("visited " + str(cnt) + " leaf keys")
This gives you the following output:
Subkeys: 72 Subvalues: 1
AdobeARMservice:
('ServiceName', 'AdobeARMservice', 1)
('Path', '"C:\\Program Files (x86)\\Common Files\\Adobe\\ARM\\1.0\\armsvc.exe"', 1)
('Path.Org', '"C:\\Program Files (x86)\\Common Files\\Adobe\\ARM\\1.0\\armsvc.exe"', 1)
('Path.Win32', 'C:\\Program Files (x86)\\Common Files\\Adobe\\ARM\\1.0\\armsvc.exe', 1)
('StartName', 'LocalSystem', 1)
('DisplayName', 'Adobe Acrobat Update Service', 1)
('Type', 16, 4)
('StartType', 2, 4)
('ErrorControl', 0, 4)
('LoadOrderGroup', '', 1)
('TagId', 0, 4)
AdobeUpdateService:
('ServiceName', 'AdobeUpdateService', 1)
...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Nuno André |
| Solution 2 | Broseph |
| Solution 3 | |
| Solution 4 | |
| Solution 5 | Community |
| Solution 6 | thanksforyourhelp |
| Solution 7 | Patrik Staron |
