-
-
Notifications
You must be signed in to change notification settings - Fork 173
/
registry.py
112 lines (91 loc) · 3.66 KB
/
registry.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from __future__ import annotations
import winreg as reg
from typing import Any
from enum import Enum, Flag
from collections.abc import Generator
class RegistryError(Exception):
pass
class ValueNotFound(RegistryError):
pass
class Access(Flag):
KEY_READ = reg.KEY_READ
KEY_WRITE = reg.KEY_WRITE
KEY_NOTIFY = reg.KEY_NOTIFY
KEY_EXECUTE = reg.KEY_EXECUTE
KEY_SET_VALUE = reg.KEY_SET_VALUE
KEY_ALL_ACCESS = reg.KEY_ALL_ACCESS
KEY_CREATE_LINK = reg.KEY_CREATE_LINK
KEY_QUERY_VALUE = reg.KEY_QUERY_VALUE
KEY_CREATE_SUB_KEY = reg.KEY_CREATE_SUB_KEY
KEY_ENUMERATE_SUB_KEYS = reg.KEY_ENUMERATE_SUB_KEYS
class MainKey(Enum):
HKU = reg.HKEY_USERS
HKCR = reg.HKEY_CLASSES_ROOT
HKCU = reg.HKEY_CURRENT_USER
HKLM = reg.HKEY_LOCAL_MACHINE
HKEY_USERS = reg.HKEY_USERS
HKEY_CLASSES_ROOT = reg.HKEY_CLASSES_ROOT
HKEY_CURRENT_USER = reg.HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE = reg.HKEY_LOCAL_MACHINE
HKEY_CURRENT_CONFIG = reg.HKEY_CURRENT_CONFIG
HKEY_PERFORMANCE_DATA = reg.HKEY_PERFORMANCE_DATA
class ValueType(Enum):
REG_SZ = reg.REG_SZ
REG_NONE = reg.REG_NONE
REG_LINK = reg.REG_LINK
REG_DWORD = reg.REG_DWORD
REG_QWORD = reg.REG_QWORD
REG_BINARY = reg.REG_BINARY
REG_MULTI_SZ = reg.REG_MULTI_SZ
REG_EXPAND_SZ = reg.REG_EXPAND_SZ
REG_RESOURCE_LIST = reg.REG_RESOURCE_LIST
REG_DWORD_BIG_ENDIAN = reg.REG_DWORD_BIG_ENDIAN
REG_DWORD_LITTLE_ENDIAN = reg.REG_DWORD_LITTLE_ENDIAN
REG_QWORD_LITTLE_ENDIAN = reg.REG_QWORD_LITTLE_ENDIAN
REG_FULL_RESOURCE_DESCRIPTOR = reg.REG_FULL_RESOURCE_DESCRIPTOR
REG_RESOURCE_REQUIREMENTS_LIST = reg.REG_RESOURCE_REQUIREMENTS_LIST
class RegistryKey:
def __init__(self, path: str, *, read_only: bool = False):
main_key, _, path = path.replace('/', '\\').partition('\\')
self.main_key = MainKey[main_key]
self.path = path
access_flags = Access.KEY_QUERY_VALUE
if not read_only:
access_flags |= Access.KEY_SET_VALUE
self._handle = reg.OpenKey(self.main_key.value, path, access=access_flags.value)
def __enter__(self) -> RegistryKey:
return self
def __exit__(self, exc_type, exc, tb):
self._handle.Close()
def get(self, name: str) -> tuple[ValueType, Any]:
try:
value, value_type = reg.QueryValueEx(self._handle, name)
except FileNotFoundError:
# TODO: consider returning None for missing values
raise ValueNotFound(name)
return (ValueType(value_type), value)
def set(self, name: str, value_type: ValueType, value: Any) -> bool:
reg.SetValueEx(self._handle, name, 0, value_type.value, value)
return True # TODO: return False if the set operation fails
def delete(self, name: str, *, silent: bool = False) -> bool:
try:
reg.DeleteValue(self._handle, name)
except FileNotFoundError:
if not silent:
raise ValueNotFound(name)
return False
return True
def values(self) -> Generator[tuple[str, ValueType, Any], None, None]:
len_keys, len_values, last_modified = reg.QueryInfoKey(self._handle)
for i in range(len_values):
try:
name, value, value_type = reg.EnumValue(self._handle, i)
yield name, ValueType(value_type), value
except OSError:
return
if __name__ == "__main__":
with RegistryKey("HKCU/Software/Microsoft/Windows/CurrentVersion/Run") as key:
# key.get("test")
# key.set("test", ValueType.REG_SZ, "test\\path")
for name, value_type, value in key.values():
print(name, value_type, value)