Delete registry folder and sub folder using python [duplicate] - python
I'm trying to delete certain registry keys, via python script.
i have no problems reading and deleting keys from the "HKEY_CURRENT_USER", but trying to do the same from the "HKEY_LOCAL_MACHINE", gives me the dreaded WindowsError: [Error 5] Access is denied.
i'm running the script via the IDLE IDE, with admin privileges.
here's the code:
from _winreg import *
ConnectRegistry(None,HKEY_LOCAL_MACHINE)
OpenKey(HKEY_LOCAL_MACHINE,r'software\wow6432node\App',0,KEY_ALL_ACCESS)
DeleteKey(OpenKey(HKEY_LOCAL_MACHINE,r'software\wow6432node'),'App')
You need to remove all subkeys before you can delete the key.
def deleteSubkey(key0, key1, key2=""):
import _winreg
if key2=="":
currentkey = key1
else:
currentkey = key1+ "\\" +key2
open_key = _winreg.OpenKey(key0, currentkey ,0,_winreg.KEY_ALL_ACCESS)
infokey = _winreg.QueryInfoKey(open_key)
for x in range(0, infokey[0]):
#NOTE:: This code is to delete the key and all subkeys.
# If you just want to walk through them, then
# you should pass x to EnumKey. subkey = _winreg.EnumKey(open_key, x)
# Deleting the subkey will change the SubKey count used by EnumKey.
# We must always pass 0 to EnumKey so we
# always get back the new first SubKey.
subkey = _winreg.EnumKey(open_key, 0)
try:
_winreg.DeleteKey(open_key, subkey)
print "Removed %s\\%s " % ( currentkey, subkey)
except:
deleteSubkey( key0, currentkey, subkey )
# no extra delete here since each call
#to deleteSubkey will try to delete itself when its empty.
_winreg.DeleteKey(open_key,"")
open_key.Close()
print "Removed %s" % (currentkey)
return
Here is an how you run it:
deleteSubkey(_winreg.HKEY_CURRENT_USER, "software\\wow6432node", "App")
deleteSubkey(_winreg.HKEY_CURRENT_USER, "software\\wow6432node\\App")
Just my two cents on the topic, but I recurse to the lowest subkey and delete on unravel:
def delete_sub_key(root, sub):
try:
open_key = winreg.OpenKey(root, sub, 0, winreg.KEY_ALL_ACCESS)
num, _, _ = winreg.QueryInfoKey(open_key)
for i in range(num):
child = winreg.EnumKey(open_key, 0)
delete_sub_key(open_key, child)
try:
winreg.DeleteKey(open_key, '')
except Exception:
# log deletion failure
finally:
winreg.CloseKey(open_key)
except Exception:
# log opening/closure failure
The difference between the other posts is that I do not try to delete if num is >0 because it will fail implicitly (as stated in the docs). So I don't waste time to try if there are subkeys.
[EDIT]
I have created a pip package that handles registry keys.
Install with: pip install windows_tools.registry
Usage:
from windows_tools.registry import delete_sub_key, KEY_WOW64_32KEY, KEY_WOW64_64KEY
keys = ['SOFTWARE\MyInstalledApp', 'SOFTWARE\SomeKey\SomeOtherKey']
for key in keys:
delete_sub_key(key, arch=KEY_WOW64_32KEY | KEY_WOW64_64KEY)
[/EDIT]
Unburying this old question, here's an updated version of ChrisHiebert's recursive function that:
Handles Python 3 (tested with Python 3.7.1)
Handles multiple registry architectures (eg Wow64 for Python 32 on Windows 64)
Is PEP-8 compliant
The following example shows function usage to delete two keys in all registry architectures (standard and redirected WOW6432Node) by using architecture key masks.
Hopefully this will help someone:
import winreg
def delete_sub_key(key0, current_key, arch_key=0):
open_key = winreg.OpenKey(key0, current_key, 0, winreg.KEY_ALL_ACCESS | arch_key)
info_key = winreg.QueryInfoKey(open_key)
for x in range(0, info_key[0]):
# NOTE:: This code is to delete the key and all sub_keys.
# If you just want to walk through them, then
# you should pass x to EnumKey. sub_key = winreg.EnumKey(open_key, x)
# Deleting the sub_key will change the sub_key count used by EnumKey.
# We must always pass 0 to EnumKey so we
# always get back the new first sub_key.
sub_key = winreg.EnumKey(open_key, 0)
try:
winreg.DeleteKey(open_key, sub_key)
print("Removed %s\\%s " % (current_key, sub_key))
except OSError:
delete_sub_key(key0, "\\".join([current_key,sub_key]), arch_key)
# No extra delete here since each call
# to delete_sub_key will try to delete itself when its empty.
winreg.DeleteKey(open_key, "")
open_key.Close()
print("Removed %s" % current_key)
return
# Allows to specify if operating in redirected 32 bit mode or 64 bit, set arch_keys to 0 to disable
arch_keys = [winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY]
# Base key
root = winreg.HKEY_LOCAL_MACHINE
# List of keys to delete
keys = ['SOFTWARE\MyInstalledApp', 'SOFTWARE\SomeKey\SomeOtherKey']
for key in keys:
for arch_key in arch_keys:
try:
delete_sub_key(root, key, arch_key)
except OSError as e:
print(e)
Figured it out!
turns out the registry key wasn't empty and contained multiple subkeys.
i had to enumerate and delete the subkeys first, and only then i was able to delete the main key from HKLM.
(also added "try...except", so it wouldn't break the whole code, it case there were problems).
This is my solution. I like to use with statements in order to not have to close the key manually. First I check for sub keys and delete them before I delete the key itself. EnumKey raises an OSError if no sub key exists. I use this to break out of the loop.
from winreg import *
def delete_key(key: Union[HKEYType, int], sub_key_name: str):
with OpenKey(key, sub_key_name) as sub_key:
while True:
try:
sub_sub_key_name = EnumKey(sub_key, 0)
delete_key(sub_key, sub_sub_key_name)
except OSError:
break
DeleteKey(key, sub_key_name)
Related
Checking for Duplicates twice over in a File - Python
config.yml example, DBtables: CurrentMinuteLoad: CSV_File: trend.csv Table_Name: currentminuteload GUI image, This may not be the cleanest route to take. I'm making a GUI that creates a config.yml file for another python script I'm working with. Using pysimplegui, My button isn't functioning the way I'd expect it to. It currently and accurately checks for the Reference name (example here would be CurrentMinuteLoad) and will kick it back if it exists, but will skip the check for the table (so the ELIF statement gets skipped). Adding the table still works, I'm just not getting the double-check that I want. Also, I have to hit the Okay button twice in the GUI for it to work?? A weird quirk that doesn't quite make sense to me. def add_table(): window2.read() with open ("config.yml","r") as h: if values['new_ref'] in h.read(): sg.popup('Reference name already exists') elif values['new_db'] in h.read(): sg.popup('Table name already exists') else: with open("config.yml", "a+") as f: f.write("\n " + values['new_ref'] +":") f.write("\n CSV_File:" + values['new_csv']) f.write("\n Table_Name:" + values['new_db']) f.close() sg.popup('The reference "' + values['new_ref'] + '" has been included and will add the table "' + values['new_db'] + '" to PG Admin during the next scheduled upload')
When you use h.read(), you should save the value since it will read it like a stream, and subsequent calls for this method will result in an empty string. Try editing the code like this: with open ("config.yml","r") as h: content = h.read() if values['new_ref'] in content: sg.popup('Reference name already exists') elif values['new_db'] in content: sg.popup('Table name already exists') else: # ...
You should update the YAML file using a real YAML parser, that will allow you to check on duplicate values, without using in, which will give you false positives when a new value is a substring of an existing value (or key). In the following I add values twice, and show the resulting YAML. The first time around the check on new_ref and new_db does not find a match although it is a substring of existing values. The second time using the same values there is of course a match on the previously added values. import sys import ruamel.yaml from pathlib import Path def add_table(filename, values, verbose=False): error = False yaml = ruamel.yaml.YAML() data = yaml.load(filename) dbtables = data['DBtables'] if values['new_ref'] in dbtables: print(f'Reference name "{values["new_ref"]}" already exists') # use sg.popup in your code error = True for k, v in dbtables.items(): if values['new_db'] in v.values(): print(f'Table name "{values["new_db"]}" already exists') error = True if error: return dbtables[values['new_ref']] = d = {} for x in ['new_cv', 'new_db']: d[x] = values[x] yaml.dump(data, filename) if verbose: sys.stdout.write(filename.read_text()) values = dict(new_ref='CurrentMinuteL', new_cv='trend_csv', new_db='currentminutel') add_table(Path('config.yaml'), values, verbose=True) print('========') add_table(Path('config.yaml'), values, verbose=True) which gives: DBtables: CurrentMinuteLoad: CSV_File: trend.csv Table_Name: currentminuteload CurrentMinuteL: new_cv: trend_csv new_db: currentminutel ======== Reference name "CurrentMinuteL" already exists Table name "currentminutel" already exists
Python winreg - How to write a linefeed to a REG_SZ value
I need some assistance in writing a line feed to a registry value. The Value is of type REG_SZ. I'm able to do this manually, by adding a "0A" to each break position when modifying the hex value in the Registry, but I'm not sure how to do this programmatically. This is my current code to write the String to Registry, which WORKS, but does not allow for the line feeds: (identifying information redacted, and text shortened. The "#" is the position for a line feed) import os import _winreg from _winreg import * Key = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" Field = [_winreg.REG_SZ, _winreg.REG_BINARY] Sub_Key = ["legalnoticetext", "legalnoticecaption"] value = ["Terms of Use", "By logging in to this PC, users agree to the Terms of Use" "\nThe User agrees to the following:#- The User may not alter, in any way, " "with Settings on this PC without the approval from any Authorised Persons."] parmLen = len(Sub_Key) z = 0 # Loop Counter for list iteration try: Key = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" if not os.path.exists(Key): key = _winreg.CreateKey(HKEY_LOCAL_MACHINE, Key) Registrykey = OpenKey(HKEY_LOCAL_MACHINE, Key, 0, KEY_WRITE) while z < parmLen: _winreg.SetValueEx(Registrykey, Sub_Key[z], 0, Field[z], value[z]) print ("Setting <" + Sub_Key[z] + "> with value: " + value[z]) z += 1 CloseKey(Registrykey) print ("SUCCESSFUL! Procedure: Show Logon Terms of Use") except WindowsError: print ("Error") I've tested the following code to see if I can write directly in Hex, as I have the modified hex value, but it results in the value being interpreted as a string, and then formatting it incorrectly (again) to Hex. import os import _winreg from _winreg import * Key = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" Field = [_winreg.REG_SZ, _winreg.REG_BINARY] Sub_Key = ["legalnoticetext", "legalnoticecaption"] value = ["Terms of Use", "42,00,79,00,20,00,6C,00,6F,00,67,00,67,00,69,00,6E,00,67,00,20,00,69,00," "6E,00,20,00,74,00,6F,00,20,00,74,00,68,00,69,00,73,00,20,00,50,00,43,00," "2C,00,20,00,75,00,73,00,65,00,72,00,73,00,20,00,61,00,67,00,72,00,65,00," "65,00,20,00,74,00,6F,00,20,00,74,00,68,00,65,00,20,00,54,00,65,00,72,00," "6D,00,73,00,20,00,6F,00,66,00,20,00,55,00,73,00,65,00,0A,00,54,00,68,00," "65,00,20,00,55,00,73,00,65,00,72,00,20,00,61,00,67,00,72,00,65,00,65,00," "73,00,20,00,74,00,6F,00,20,00,74,00,68,00,65,00,20,00,66,00,6F,00,6C,00," "6C,00,6F,00,77,00,69,00,6E,00,67,00,3A,00,0A,00,2D,00,20,00,54,00,68,00," "65,00,20,00,55,00,73,00,65,00,72,00,20,00,6D,00,61,00,79,00,20,00,6E,00," "6F,00,74,00,20,00,61,00,6C,00,74,00,65,00,72,00,2C,00,20,00,69,00,6E,00," "20,00,61,00,6E,00,79,00,20,00,77,00,61,00,79,00,2C,00,20,00,77,00,69,00," "74,00,68,00,20,00,53,00,65,00,74,00,74,00,69,00,6E,00,67,00,73,00,20,00," "6F,00,6E,00,20,00,74,00,68,00,69,00,73,00,20,00,50,00,43,00,20,00,77,00," "69,00,74,00,68,00,6F,00,75,00,74,00,20,00,74,00,68,00,65,00,20,00,61,00," "70,00,70,00,72,00,6F,00,76,00,61,00,6C,00,20,00,66,00,72,00,6F,00,6D,00," "20,00,61,00,6E,00,79,00,20,00,41,00,75,00,74,00,68,00,6F,00,72,00,69,00," "73,00,65,00,64,00,20,00,50,00,65,00,72,00,73,00,6F,00,6E,00,73,00,2E,00," "00,00"] parmLen = len(Sub_Key) z = 0 # Loop Counter for list iteration try: Key = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" if not os.path.exists(Key): key = _winreg.CreateKey(HKEY_LOCAL_MACHINE, Key) Registrykey = OpenKey(HKEY_LOCAL_MACHINE, Key, 0, KEY_WRITE) while z < parmLen: _winreg.SetValueEx(Registrykey, Sub_Key[z], 0, Field[z], value[z]) print ("Setting <" + Sub_Key[z] + "> with value: " + value[z]) z += 1 CloseKey(Registrykey) print ("SUCCESSFUL! Procedure: Show Logon Terms of Use") except WindowsError: print ("Error") RTFM'ing doesn't prove to be very helpful with this specific issue, so any guidance would be appreciated!
You have a couple of issues going on. os.path.exists checks for file path existence. Feeding it the key string won't check the registry. It looks like you are using Python 2.7, please consider upgrading to 3. The issue you are running into is that writing a REG_BINARY expects binary data; in Python 3, this means you just need to encode your string. Here is the code in Python 3. import winreg Key_str = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" Field = [winreg.REG_SZ, winreg.REG_BINARY] Sub_Key = ["legalnoticetext", "legalnoticecaption"] value = ["Terms of Use", "By logging in to this PC, users agree to the Terms of Use" "\nThe User agrees to the following:#- The User may not alter, in any way, " "with Settings on this PC without the approval from any Authorised Persons."] try: key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, Key_str) except FileNotFoundError: key = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, Key_str) for sk, f, v in zip(Sub_Key, Field, value): if f == winreg.REG_BINARY: winreg.SetValueEx(key, sk, 0, f, v.encode('latin-1')) else: winreg.SetValueEx(key, sk, 0, f, v) key.Close() In Python 2, your standard strings are byte strings, so there is no need to encode the string to a bytes encoding. Here is the Python 2 code: import _winreg Key_str = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" Field = [_winreg.REG_SZ, _winreg.REG_BINARY] Sub_Key = ["legalnoticetext", "legalnoticecaption"] value = ["Terms of Use", "By logging in to this PC, users agree to the Terms of Use" "\nThe User agrees to the following:#- The User may not alter, in any way, " "with Settings on this PC without the approval from any Authorised Persons."] try: key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, Key_str) except WindowsError: key = _winreg.CreateKey(_winreg.HKEY_LOCAL_MACHINE, Key_str) for sk, f, v in zip(Sub_Key, Field, value): _winreg.SetValueEx(key, sk, 0, f, v) key.Close()
Is there a way to get the full path of the shell:appsfolder on Windows 10?
I'd like to be able to list the files in the shell:appsfolder in a python script but need the full path to do this using os.list. Is there a way to get the full path (or does anyone know it)? Alternatively, is there a different way I can list these files? Can I "cd" to it? The idea behind the script is to automate the shortcut creation of all the Windows Store apps (identified by the fact they have a "long name" property I think) and extract those shortcuts to a folder where the program Launchy can detect them. I don't like having to manually go through the process of creating the shortcut (and renaming it to remove the " - shortcut) every time I download or remove an app so I thought I'd automate it.
Here's a function that hopefully does what you want in terms of creating shortcuts for the Windows Store apps that are listed in the "Applications" virtual folder (i.e. FOLDERID_AppsFolder). To classify Windows Store apps, it looks for an exclamation point in the Application User Model ID since the AUMID should be of the form "PackageFamily!ApplicationID" (see Automate Launching UWP Apps). For reliability it cross-checks each package family with the user's registered package families. import os import ctypes import pywintypes import pythoncom import winerror try: import winreg except ImportError: # Python 2 import _winreg as winreg bytes = lambda x: str(buffer(x)) from ctypes import wintypes from win32com.shell import shell, shellcon from win32com.propsys import propsys, pscon # KNOWNFOLDERID # https://msdn.microsoft.com/en-us/library/dd378457 # win32com defines most of these, except the ones added in Windows 8. FOLDERID_AppsFolder = pywintypes.IID('{1e87508d-89c2-42f0-8a7e-645a0f50ca58}') # win32com is missing SHGetKnownFolderIDList, so use ctypes. _ole32 = ctypes.OleDLL('ole32') _shell32 = ctypes.OleDLL('shell32') _REFKNOWNFOLDERID = ctypes.c_char_p _PPITEMIDLIST = ctypes.POINTER(ctypes.c_void_p) _ole32.CoTaskMemFree.restype = None _ole32.CoTaskMemFree.argtypes = (wintypes.LPVOID,) _shell32.SHGetKnownFolderIDList.argtypes = ( _REFKNOWNFOLDERID, # rfid wintypes.DWORD, # dwFlags wintypes.HANDLE, # hToken _PPITEMIDLIST) # ppidl def get_known_folder_id_list(folder_id, htoken=None): if isinstance(folder_id, pywintypes.IIDType): folder_id = bytes(folder_id) pidl = ctypes.c_void_p() try: _shell32.SHGetKnownFolderIDList(folder_id, 0, htoken, ctypes.byref(pidl)) return shell.AddressAsPIDL(pidl.value) except WindowsError as e: if e.winerror & 0x80070000 == 0x80070000: # It's a WinAPI error, so re-raise it, letting Python # raise a specific exception such as FileNotFoundError. raise ctypes.WinError(e.winerror & 0x0000FFFF) raise finally: if pidl: _ole32.CoTaskMemFree(pidl) def enum_known_folder(folder_id, htoken=None): id_list = get_known_folder_id_list(folder_id, htoken) folder_shell_item = shell.SHCreateShellItem(None, None, id_list) items_enum = folder_shell_item.BindToHandler(None, shell.BHID_EnumItems, shell.IID_IEnumShellItems) for item in items_enum: yield item def list_known_folder(folder_id, htoken=None): result = [] for item in enum_known_folder(folder_id, htoken): result.append(item.GetDisplayName(shellcon.SIGDN_NORMALDISPLAY)) result.sort(key=lambda x: x.upper()) return result def create_shortcut(shell_item, shortcut_path): id_list = shell.SHGetIDListFromObject(shell_item) shortcut = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink) shortcut.SetIDList(id_list) persist = shortcut.QueryInterface(pythoncom.IID_IPersistFile) persist.Save(shortcut_path, 0) def get_package_families(): families = set() subkey = (r'Software\Classes\Local Settings\Software\Microsoft' r'\Windows\CurrentVersion\AppModel\Repository\Families') with winreg.OpenKey(winreg.HKEY_CURRENT_USER, subkey) as hkey: index = 0 while True: try: families.add(winreg.EnumKey(hkey, index)) except OSError as e: if e.winerror != winerror.ERROR_NO_MORE_ITEMS: raise break index += 1 return families def update_app_shortcuts(target_dir): package_families = get_package_families() for item in enum_known_folder(FOLDERID_AppsFolder): try: property_store = item.BindToHandler(None, shell.BHID_PropertyStore, propsys.IID_IPropertyStore) app_user_model_id = property_store.GetValue( pscon.PKEY_AppUserModel_ID).ToString() except pywintypes.error: continue # AUID template: Packagefamily!ApplicationID if '!' not in app_user_model_id: continue package_family, app_id = app_user_model_id.rsplit('!', 1) if package_family not in package_families: continue name = item.GetDisplayName(shellcon.SIGDN_NORMALDISPLAY) shortcut_path = os.path.join(target_dir, '%s.lnk' % name) create_shortcut(item, shortcut_path) print('{}: {}'.format(name, app_user_model_id)) example if __name__ == '__main__': desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0) target_dir = os.path.join(desktop, 'Windows Store Apps') if not os.path.exists(target_dir): os.mkdir(target_dir) update_app_shortcuts(target_dir)
Python string comparison using pymarc marc8_to_unicode no longer working
My code imports a MARC file using MARCReader and compares a string against a list of acceptable answers. If the string from MARC has no match in my list, it gets added to an error list. This has worked for years in Python 2.7.4 installations on Windows 7 with no issue. I recently got a Windows 10 machine and installed Python 2.7.10, and now strings with non-standard characters fail that match. the issue is not Python 2.7.10 alone; I've installed every version from 2.7.4 through 2.7.10 on this new machine, and get the same problem. A new install of Python 2.7.10 on a Windows 7 machine also gets the problem. I've trimmed out functions that aren't relevant, and I've dramatically trimmed the master list. In this example, "Académie des Sciences" is an existing repository, but "Acadm̌ie des Sciences" now appears in our list of new repositories. # -*- coding: utf-8 -*- from aipmarc import get_catdb, get_bibno, parse_date from phfawstemplate import browsepage #, nutchpage, eadpage, titlespage from pymarc import MARCReader, marc8_to_unicode from time import strftime from umlautsort import alafiling import urllib2 import sys import os import string def make_newrepos_list(list, fn): # Create list of unexpected repositories found in the MArcout database dump output = "These new repositories are not yet included in the master list in phfaws.py. Please add the repository code (in place of ""NEWCODE*""), and the URL (in place of ""TEST""), and then add these lines to phfaws.py. Please keep the list alphabetical. \nYou can find repository codes at http://www.loc.gov/marc/organizations/ \n \n" for row in list: output = '%s reposmasterlist.append([u"%s", "%s", "%s"])\n' % (output, row[0], row[1], row[2]) fh = open(fn,'w') fh.write(output.encode("utf-8")) fh.close() def main(marcfile): reader = MARCReader(file(marcfile)) ''' Creating list of preset repository codes. ''' reposmasterlist =[[u"American Institute of Physics", "MdCpAIP", "http://www.aip.org/history/nbl/index.html"]] reposmasterlist.append([u"Académie des Sciences", "FrACADEMIE", "http://www.academie-sciences.fr/fr/Transmettre-les-connaissances/inventaires-des-fonds-d-archives-personnelles.html"]) reposmasterlist.append([u"American Association for the Advancement of Science", "daaas", "http://archives.aaas.org/"]) newreposcounter = 0 newrepos = "" newreposlist = [] findingaidcounter = 0 reposcounter = 0 for record in reader: if record['903']: # Get only records where 903a="PHFAWS" phfawsfull = record.get_fields('903') for field in phfawsfull: phfawsnote = field['a'] if 'PHFAWS' in phfawsnote: if record['852'] is not None: # Get only records where 852/repository is not blank repository = record.get_fields('852') for field in repository: reposname = field['a'] reposname = marc8_to_unicode(reposname) # Convert repository name from MARC file to Unicode reposname = reposname.rstrip('.,') reposcode = None reposurl = None for row in reposmasterlist: # Match field 852 repository against the master list. if row[0] == reposname: # If it's in the master list, use the master list to populate our repository-related fields reposcode = row[1] reposurl = row[2] if record['856'] is not None: # Get only records where 856 is not blank and includes "online finding aid" links = record.get_fields('856') for field in links: linksthree = field['3'] if linksthree is not None and "online finding aid" in linksthree: if reposcode == None: # If this record's repository wasn't in the master list, add to list of new repositories newreposcounter += 1 newrepos = '%s %s \n' % (newrepos, reposname) reposcode = "NEWCODE" + str(newreposcounter) reposurl = "TEST" reposmasterlist.append([reposname, reposcode, reposurl]) newreposlist.append([reposname, reposcode, reposurl]) human_url = field['u'] else: pass else: pass else: pass else: pass else: pass # Output list of new repositories newreposlist.sort(key = lambda rep: rep[0]) if newreposcounter != 0: status = '%d new repositories found. you must add information on these repositories, then run phfaws.py again. Please see the newly updated rewrepos.txt for details.' % (newreposcounter) sys.stderr.write(status) make_newrepos_list(newreposlist, 'newrepos.txt') if __name__ == '__main__': try: mf = sys.argv[1] sys.exit(main(mf)) except IndexError: sys.exit('Usage: %s <marcfile>' % sys.argv[0]) Edit: I've found that simply commenting out the "reposname = marc8_to_unicode(reposname)" line gets me the results I want. I still don't understand why this is, since it was a necessary step before.
Edit: I've found that simply commenting out the "reposname = marc8_to_unicode(reposname)" line gets me the results I want. I still don't understand why this is, since it was a necessary step before. This suggests to me that the encoding of strings in your database changed from MARC8 to Unicode. Have you upgraded your cataloging system recently?
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.
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_64KEY or KEY_WOW64_32KEY to the flags parameter). Using OpenKey() as context manager was introduced in python 2.6.
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)
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
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)
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.
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
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) ...