python操作注册表

1 Windows注册表

很多程序将配置保存在注册表中方便读取。

注册表是一个树状结构,每一个节点可以有子节点,并且每个节点可以有自己的值。这些值就是程序保存在注册表中的配置信息,值有名词、类型和数值三个属性。

1.1 值类型

其中类型表示保存值的类型,常见的类型有:

类型 说明
REG_BINARY 二进制数据
REG_DWORD 32位数字
REG_DWORD_LITTLE_ENDIAN 小端格式的 32位数字,等价于 REG_DWORD
REG_DWORD_BIG_ENDIAN 大端格式的 32位数字
REG_QWORD 64位数字
REG_QWORD_LITTLE_ENDIAN 小端格式的 64位数字,等价于 REG_QWORD
REG_SZ C语言字符串(以 \0 结尾)
REG_EXPAND_SZ C语言字符串(以 \0 结尾),可以在字符串中使用环境变量,比如 %temp%
REG_MULTI_SZ C语言字符串序列(注意不是数组),以两个 \0 结尾
REG_LINK Unicode 编码的符号链接
REG_NONE 未定义的类型

所有的字符串类型中都可以使用系统默认参数,系统默认参数以 % 开头,他们的作用分别是:

%1  表示程序操作的文件
%2  表示系统默认的打印机
%3  表示资料扇区
%4  表示操作的Port端口
"%v"  程序操作的路径

1.2 目录结构

HKEY_LOCAL_MACHINE 主键是此计算机上的所有用户共享的注册表键值,而 HKEY_CURRENT_USER 是当前用户使用的注册表键值。而我们在注册表的 HKEY_CLASSES_ROOT 中也可以看到跟 HKEY_LOCAL_MACHINE\Software\ClassesHKEY_CURRENT_USER\Software\Classes 中一样的文件关联项,是因为 HKEY_CLASSES_ROOTHKEY_LOCAL_MACHINE\Software\ClassesHKEY_CURRENT_USER\Software\Classes 合并之后的一个视图,其中用户键值会覆盖此计算机上的相同键值。因此我们不能直接修改 HKEY_CLASSES_ROOT 中的值,而是要在 HKEY_CURRENT_USER\Software\Classes 或者 HKEY_CURRENT_USER\Software\Classes 中修改,通常建议在 HKEY_CURRENT_USER 下修改,因为这样不需要管理员权限。

2 python操作注册表

警告:如果你不知道注册表中的项是干什么的,千万不要随便修改和删除已经存在的注册表项,否则可能导致系统崩溃!!

winreg是 python自带的模块,可以通过 winreg对注册表的值进行添加、删除和修改操作。

在继续了解 winreg的用法之前我们需要了解一些概念的对应关系,winreg中用 key来表示注册表中的项。key可以是一个路径,当 key是一个路径时 key所表示的就是路径的最后一个项,比如 HKEY_CURRENT_USER\Software\Classes 表示的就是 HKEY_CURRENT_USERSoftware 下的 Classes 项。

2.1 创建注册表项

通过调用 winreg.CreateKey(key, sub_key) 可以在注册表中创建一个 key并返回该 key的对象。其中 参数 key可以是 HKEY 开头的根路径(比如:winreg.HKEY_CURRENT_USER)也可以是已经打开的 key,所谓已经打开的 key就是 CreateKey 的返回值。sub_key 是要创建的 key 的路径,不同的项之间用 \ 分隔。如果 key已经存在,则直接返回 key的对象。下面看看示例代码:

import winreg

# 创建 key
test_key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, 'test')
sub_test_key = winreg.CreateKey(test_key, 'sub_test')
# 下面两句是等效的
sub_sub_test_key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, r'test\sub_test\sub_sub_test')
sub_sub_test_key = winreg.CreateKey(sub_test_key, r'sub_sub_test')

2.2 删除注册表项

如果我们在创建了注册表项之后要删除它们,可以使用 winreg.DeleteKey(key, sub_key) 来执行删除操作。DeleteKey 的参数和 CreateKey 的参数完全相同,不过需要注意几点:

  • DeleteKey 只能删除没有子节点的项。
  • sub_key 必须是 key 的子节点。
import winreg

# 报错
try:
    winreg.DeleteKey(winreg.HKEY_CURRENT_USER, r'test')
except PermissionError:
    pass
# 成功删除
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, r'test\sub_test\sub_sub_test')
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, r'test\sub_test')
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, r'test')

2.3 打开注册表项

前面讲到可以使用 CreateKey 来获取打开的 key对象,但是毕竟 CreateKey 的主要功能还是用来创建 key的,对于已经存在的 key我们还是用 OpenKey 来打开更加合适。并且当我们要修改 key的值时需要声明权限,这是 CreateKey 所不能的(虽然 CreateKeyEx 可以)。

OpenKey 的函数签名 winreg.OpenKey(key, sub_key, reserved=0, access=KEY_READ) 其中 access 表示以什么权限打开,默认以只读权限打开,如果需要修改 key的值,则需要以 winreg.KEY_SET_VALUE 权限打开,是否能够成功打开取决于当前用户是否有对应的权限。

2.4 设置注册表项的值

一共有两个方法可以设置注册表项的值,分别是 winreg.SetValue(key, sub_key, type, value)winreg.SetValueEx(key, value_name, reserved, type, value)。前者设置的是 sub_key 的默认值,后者设置的是 keyvalue_name 的值,并且 SetValueEx 需要以 winreg.KEY_SET_VALUE 权限打开 key才能正常设置值。

import winreg

sub_sub_test = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'test\sub_test\sub_sub_test', access=winreg.KEY_SET_VALUE)
winreg.SetValueEx(sub_sub_test, 'test', 0, winreg.REG_SZ, "test")
# 或者
sub_sub_test = winreg.CreateKeyEx(winreg.HKEY_CURRENT_USER, r'test\sub_test\sub_sub_test', access=winreg.KEY_SET_VALUE)
winreg.SetValueEx(sub_sub_test, 'test', 0, winreg.REG_EXPAND_SZ, "test1")

2.5 删除注册表项的值

winreg.DeleteValue(key, value_name) 删除 key的 value_name,当 value_name为空字符时会清空 key的默认值。key需要以 winreg.KEY_SET_VALUE 权限打开。

import winreg

sub_sub_test = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'test\sub_test\sub_sub_test', access=winreg.KEY_SET_VALUE)
winreg.SetValueEx(sub_sub_test, 'test', 0, winreg.REG_SZ, "test")
winreg.DeleteValue(sub_sub_test, 'test')

3 注册表的使用

3.1 添加开机自启

将要开机自启的程序的启动路径添加到 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 即可,示例如下:

improt winreg

def set_auto_start(program_name, path):
    key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', access=winreg.KEY_SET_VALUE)
    winreg.SetValueEx(key, program_name, 0, winreg.REG_SZ, path)

参考

[1] CSDN-如何为你的 Windows 应用程序关联一种或多种文件类型

[2] 简书-如何在Windows下用Python开发右键菜单功能?

[3] python官方文档-Windows registry access