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)
...

Categories

Resources