关于本站
1、基于Django+Bootstrap开发
2、主要发表本人的技术原创博客
3、本站于 2015-12-01 开始建站
最近有个Python项目需要操作注册表。网上搜一下,基本都是同一篇文章,都是一样的代码。而且只有使用_winreg库操作注册表的方法。
相当无语,连个原创的好文章都没有。
Python操作注册表有两个库_winreg和win32api。
其中,_winreg在64位系统中有个缺陷。所以使用win32api操作注册表、读写注册表。
自己研究win32api中的相关API函数操作注册表,最后封装成一个类。
相关代码见:https://github.com/HaddyYang/pyregedit
操作注册表之前先了解注册表的结构。
注册表分两部分:键和值。
1)键是一个树结构
一个键下面可以有很多子键。也可以理解为键是文件夹。
一个注册表有5个根键。类似我们平常使用的硬盘分区:C盘、D盘等。
2)值是相当于文件
每个值项包含名称、类型、数据。一个键下可以有多个值。
微软设计的这个注册表有个相当不合理的地方:键还有默认值,键还当作值来使用。这个设计造成了不少麻烦。
了解大致结构之后,先讲如何判断一个键是否存在。
我们要对一个键操作至少要先知道它是否存在。这个可以通过打开一个键的方法判断。
若该键存在,即可以顺利打开。若不存在,则会报错。
#coding:utf-8 import win32api, win32con #根节点 reg_root = win32con.HKEY_LOCAL_MACHINE #键的路径(具体路径自行修改) reg_path = r"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders" #权限和参数设置 reg_flags = win32con.WRITE_OWNER|win32con.KEY_WOW64_64KEY|win32con.KEY_ALL_ACCESS try: key = win32api.RegOpenKeyEx(reg_root, reg_path, 0, reg_flags) except Exception as e: key = None
通过该代码,即可知道对应路径的键是否存在。
使用win32api,需要安装pywin32。用pip install pywin32安装即可。
打开一个键之后,遍历枚举一个键的所有子键,代码如下:
#coding:utf-8 import win32api, win32con reg_root = win32con.HKEY_LOCAL_MACHINE reg_path = r"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders" reg_flags = win32con.WRITE_OWNER|win32con.KEY_WOW64_64KEY|win32con.KEY_ALL_ACCESS #遍历枚举子键 key = win32api.RegOpenKeyEx(reg_root, reg_path, 0, reg_flags) for item in win32api.RegEnumKeyEx(key): print(item) #关闭键 win32api.RegCloseKey(key)
该代码是读取HKEY_LOCAL_MACHINE下,路径为SOFTWARE\Microsoft\.NETFramework\AssemblyFolders的键所有子键。
结果如下:
得到5个子键,这些都是元组。一般有用的是每个元组的第1个元素:子键名称。
一个键的值有两部分:键的默认值和键的其他值。默认值对应的名称是空字符串"",代码如下:
#coding:utf-8 import win32api, win32con reg_root = win32con.HKEY_LOCAL_MACHINE reg_path = r"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\SQL Server Assemblies" reg_flags = win32con.WRITE_OWNER|win32con.KEY_WOW64_64KEY|win32con.KEY_ALL_ACCESS key = win32api.RegOpenKeyEx(reg_root, reg_path, 0, reg_flags) #遍历其他键值 try: i = 0 while True: print(win32api.RegEnumValue(key, i)) i += 1 except Exception as e: #raise(e) pass #关闭键 win32api.RegCloseKey(key)
其中相关路径自行修改。由于无法获取一个键下面有多少个值项。所以只能弄个循环处理。
获取每个值的数据分别为值的名称、值的数值和值的类型。
效果如下图:
若默认值显示数值未设置,则没有默认值的值项。例如下图:
若我们知道注册表项的路径以及值的名称,可以用RegQueryValueEx方法直接获取数据。
#coding:utf-8 import win32api, win32con reg_root = win32con.HKEY_LOCAL_MACHINE reg_path = r"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\v3.5" reg_flags = win32con.WRITE_OWNER|win32con.KEY_WOW64_64KEY|win32con.KEY_ALL_ACCESS #读取键值 key = win32api.RegOpenKeyEx(reg_root, reg_path, 0, reg_flags) value, key_type = win32api.RegQueryValueEx(key, 'All Assemblies In') print(value, key_type) #关闭键 win32api.RegCloseKey(key)
读写注册表,有读就有写。有时需要给自己软件写一些注册信息,需要创建一个专门保存自己数据的键。
那么就需要先创建键之后,再创建值。代码如下。
#coding:utf-8 import win32api, win32con reg_root = win32con.HKEY_LOCAL_MACHINE reg_path = r"SOFTWARE\Microsoft\test_key" reg_flags = win32con.WRITE_OWNER|win32con.KEY_WOW64_64KEY|win32con.KEY_ALL_ACCESS #直接创建(若存在,则为获取) key, _ = win32api.RegCreateKeyEx(reg_root, reg_path, reg_flags) #设置项 win32api.RegSetValueEx(key, "test_value", 0, win32con.REG_SZ, 'This is a test item') #关闭 win32api.RegCloseKey(key)
执行之后,刷新注册表。可以看到成功创建。
其中,RegSetValueEx方法各个参数分别是 键、值的名称、0、值的类型、值的数值。
没错,第3个参数固定是0。
删除键和值也是操作注册表的方式之一。删除刚刚创建的键和值代码如下:
#coding:utf-8 import win32api, win32con import os reg_root = win32con.HKEY_LOCAL_MACHINE reg_path = r"SOFTWARE\Microsoft\test_key" reg_flags = win32con.WRITE_OWNER|win32con.KEY_WOW64_64KEY|win32con.KEY_ALL_ACCESS #删除值(key也有close方法,可以用with结构) with win32api.RegOpenKeyEx(reg_root, reg_path, 0, reg_flags) as key: win32api.RegDeleteValue(key, 'test_value') #删除键(需要获取其父键,通过父键删除子键) reg_parent, subkey_name = os.path.split(reg_path) with win32api.RegOpenKeyEx(reg_root, reg_parent, 0, reg_flags) as key: win32api.RegDeleteKeyEx(key, subkey_name)
当然,若你想删除整个键,可以不需要先删除其中的值才删除键。直接删除键即可。
有关win32api操作注册表的方法大致这些。也希望网上的文章别抄来抄去,多一些原创,多一些进步。