Python用win32api操作注册表

  • 发布时间:2017年2月22日 09:36
  • 作者:杨仕航
  • 分类标签: Python
  • 阅读(19587)
  • 评论(0)

最近有个Python项目需要操作注册表。网上搜一下,基本都是同一篇文章,都是一样的代码。而且只有使用_winreg库操作注册表的方法。

相当无语,连个原创的好文章都没有。

Python操作注册表有两个库_winreg和win32api。

其中,_winreg在64位系统中有个缺陷。所以使用win32api操作注册表、读写注册表。

自己研究win32api中的相关API函数操作注册表,最后封装成一个类。

相关代码见:https://github.com/HaddyYang/pyregedit


操作注册表之前先了解注册表的结构。

20170221/20170221172848062.png

注册表分两部分:键和值。

1)键是一个树结构

一个键下面可以有很多子键。也可以理解为键是文件夹。

一个注册表有5个根键。类似我们平常使用的硬盘分区:C盘、D盘等。


2)值是相当于文件

每个值项包含名称、类型、数据。一个键下可以有多个值。

微软设计的这个注册表有个相当不合理的地方:键还有默认值,键还当作值来使用。这个设计造成了不少麻烦。


1、判断键是否存在

了解大致结构之后,先讲如何判断一个键是否存在。

我们要对一个键操作至少要先知道它是否存在。这个可以通过打开一个键的方法判断。

若该键存在,即可以顺利打开。若不存在,则会报错。

#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安装即可。


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

#遍历枚举子键
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的键所有子键。

结果如下:

20170221/20170221174405650.png

得到5个子键,这些都是元组。一般有用的是每个元组的第1个元素:子键名称。


3、遍历枚举值

一个键的值有两部分:键的默认值和键的其他值。默认值对应的名称是空字符串"",代码如下:

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

其中相关路径自行修改。由于无法获取一个键下面有多少个值项。所以只能弄个循环处理。

获取每个值的数据分别为值的名称、值的数值和值的类型。

效果如下图:

20170222/20170222084907325.png

若默认值显示数值未设置,则没有默认值的值项。例如下图:

20170222/20170222085212566.png


4、直接获取某个值的数据

若我们知道注册表项的路径以及值的名称,可以用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)


5、创建键和值

读写注册表,有读就有写。有时需要给自己软件写一些注册信息,需要创建一个专门保存自己数据的键。

那么就需要先创建键之后,再创建值。代码如下。

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

执行之后,刷新注册表。可以看到成功创建。

20170222/20170222091611018.png

其中,RegSetValueEx方法各个参数分别是 键、值的名称、0、值的类型、值的数值。

没错,第3个参数固定是0。


6、删除键和值

删除键和值也是操作注册表的方式之一。删除刚刚创建的键和值代码如下:

#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操作注册表的方法大致这些。也希望网上的文章别抄来抄去,多一些原创,多一些进步。

Github地址:https://github.com/HaddyYang/pyregedit

上一篇:我的网站搭建(第45天) 上传头像

下一篇:我的网站搭建(第44天) 添加头像字段

评论列表

智慧如你,不想发表一下意见吗?

新的评论

清空