Search code examples
pythonwindowsregistry

Python winreg is updating SOMETHING, but not the Windows registry


I am using winreg to read, write, and change the Windows registry. My program flips a lot of different settings to fix things that annoy me about the windows defaults. When I run it, it seems to work. The changes even persist between Flask runs, even after restarting Windows Explorer, and the computer.

But every time I check the registry, the changes aren’t there. I already verified that everything is 64bit. I am running VScode as admin (and running flask through the terminal there). Just in case, I ran it in an admin terminal outside of vscode too.

No matter what I try, it tells me it’s changing the registry when it actually isn’t. It’s completely punking me. I've tried reopening Windows Explorer, closing and reopening the Registry, and restarting the system. None made a difference.

For the settings where I created a value and set it's "data" attribute, that persists between sessions and I can test for it in my code as if it's storing it SOMEWHERE.

This is the code:

NOTE: if you're at all worried about the registry changes below, back up your registry before running this

import winreg

def hive_name(hive):
    if hive == winreg.HKEY_CURRENT_USER:
        return "HKEY_CURRENT_USER"
    elif hive == winreg.HKEY_LOCAL_MACHINE:
        return "HKEY_LOCAL_MACHINE"
    elif hive == winreg.HKEY_CLASSES_ROOT:
        return "HKEY_CLASSES_ROOT"
    elif hive == winreg.HKEY_USERS:
        return "HKEY_USERS"
    elif hive == winreg.HKEY_PERFORMANCE_DATA:
        return "HKEY_PERFORMANCE_DATA"
    elif hive == winreg.HKEY_CURRENT_CONFIG:
        return "HKEY_CURRENT_CONFIG"
    else:
        return "UNKNOWN_HIVE"

def open_or_create_key(hive, path):
    try:
        # Open the registry key for reading and writing in 64-bit view
        key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ | winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY)
        print(f"Key opened: {hive_name(hive)}\\{path}")
    except FileNotFoundError:
        # Handle if the key doesn't exist
        print(f"Creating key: {hive_name(hive)}\\{path}")
        key = winreg.CreateKeyEx(hive, path, 0, winreg.KEY_READ | winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY)
    except PermissionError:
        # Handle if there are permission issues
        print(f"Permission denied while accessing the key: {hive_name(hive)}\\{path}")
        key = None
    except Exception as e:
        # Handle any other exceptions
        print(f"An error occurred: {e}")
        key = None
    return key

def get_value(key,which):
    try:
        value, _ = winreg.QueryValueEx(key, which)
        print(f"Current value: {value}")
    except FileNotFoundError:
        print("Current value: <not set>")
    except Exception as e:
        print(f"An error occurred while querying the value: {e}")

def set_value(key,which,what):
    try:
        winreg.SetValueEx(key, which, 0, winreg.REG_DWORD, what)
        print (which, "was set to", what)
    except FileNotFoundError:
        print (which, "could not be set to", what)

def close_key(key):
    if key:
        winreg.CloseKey(key)
        print("Key closed.")

# Test the open_or_create_key function
if __name__ == "__main__":

    print("# This key does exist on my system and has tons of values")
    print("# Expected Output: Key opened: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced")
    key = open_or_create_key(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced")
    print("# Value name DisallowShaking is NOT in my registry.")
    print("# Expected Output: Current value: <not set> ")
    # Prevents the windows "feature" of minimizing everything if you "shake" a window while dragging. Does nothing if the value isn't actually set.
    get_value(key,"DisallowShaking")
    print("# Value name HideFileExt IS in my registry.")
    print("# Expected Output: HideFileExt set to X (where X is the value set in the code) - needs to be checked in the registry to see if it changed between runs")
    # enables or disables hiding of file extensions. 0 to not hide it.
    set_value(key,"HideFileExt",1)
    close_key(key)

    # This restores the Windows 10 right-click context menu to your system in Windows 11 if the key is present. It has no effect when left
    print("# Neither {86ca1aa0-34aa-4e8b-a509-50c905bae2a2} nor InprocServer32 exist in my registry.")
    print("# Expected Output: Creating Key: Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32")
    key = open_or_create_key(winreg.HKEY_CURRENT_USER, r"Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32")
    close_key(key)

    # Setting this key and vlue restores the Windows 10 Windows Explorer ribbon. 
    print("# The Blocked key does not exist in my registry.")
    print("# Expected Output: Creating Key: SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked")
    key = open_or_create_key(winreg.HKEY_CURRENT_USER, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked")
    print("# If the key were created, then I can test for value {e2bf9676-5f8f-435c-97eb-11607a5bedf7} which should not exist yet.")
    print("# Expected Output: An error occurred while querying the value:  ")
    get_value(key,"{e2bf9676-5f8f-435c-97eb-11607a5bedf7}")
    set_value(key,"{e2bf9676-5f8f-435c-97eb-11607a5bedf7}", 1)
    close_key(key)

When I run the above (in VsCode terminal with VsCode run as admin), I get the following output:

# This key does exist on my system and has tons of values
# Expected Output: Key opened: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
Key opened: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
# Value name DisallowShaking is NOT in my registry.
# Expected Output: Current value: <not set>
Current value: 1
# Value name HideFileExt IS in my registry.
# Expected Output: HideFileExt set to X (where X is the value set in the code) - needs to be checked in the registry to see if it changed between runs
HideFileExt was set to 1
Key closed.
# Neither {86ca1aa0-34aa-4e8b-a509-50c905bae2a2} nor InprocServer32 exist in my registry.
# Expected Output: Creating Key: Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32
Key opened: HKEY_CURRENT_USER\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32
Key closed.
# The Blocked key does not exist in my registry.
# Expected Output: Creating Key: SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked
Key opened: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked
# If the key were created, then I can test for value {e2bf9676-5f8f-435c-97eb-11607a5bedf7} which should not exist yet.
# Expected Output: An error occurred while querying the value:
Current value: <not set>
Key closed.

Despite that, the state of my registry after running the above is as follows:

  • DisallowShaking was NOT created

  • HideFileExt was NOT set to 1 enter image description here

  • key Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32 is NOT created enter image description here

  • key SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked is NOT created

  • value {e2bf9676-5f8f-435c-97eb-11607a5bedf7} is clearly does not exist, but outputs as if it were. enter image description here

And somehow, the state is preserved. I added a "set_value" to the last value ({e2bf9676-5f8f-435c-97eb-11607a5bedf7}) on a subsequent run and the value I set persisted between runs of the program. The key and value both still don't exist in my registry.

The common responses are the 64 vs 32 bit issue which isn't in play (the system, python, and the Regedit are all 64 bit). I've checked the "VirtualStore" - I checked the ENTIRE registry for any text containing one of the values I set and it's not there (except when I run the code... then it thinks it is).


Solution

  • As per my comment, I assume it was most likely an issue with the older version of python/winreg, as always restarting/reinstalling seem to solve these types of cryptic problems.

    Although there were changes between 3.10 and 3.12 to how winreg manages registry key handles, that should not have anything to do with it.

    I still could not reproduce the problem with python 3.10.11 or 3.12.11, perhaps it's just a buggy/corrupt python install?