在给电脑重新分盘时,想把 Software 盘的驱动器号(E:)改为对应的首字母 S,因此导致了所有软件崩溃。主要原因是软件主要依据驱动器号识别位置,而更改驱动器号后,并不会将软件设置的驱动器号一并更改。
解决办法有如下两个:
- 删除原有软件文件夹,重装一遍。
- 手动更改注册表,将 E:\ 改为 S:\。
两个方案的工作量都不小:
- 方案一的缺点是,注册表中原有的记录不会被删除,在操作电脑时会偶尔弹出一些无图标的选项很烦人。
- 方案二的缺点是,难以更改完全,因为不清楚每个软件安装和使用时都向注册表写了些什么东西。。。
这里介绍一下方案二的解决办法,但也并不是很好的方案。
1 手动替换
win11下,点击 win 按键,搜索框里搜索“注册表”,打开“注册表编辑器”后,点击左上角“编辑 ->
查找”选项,搜索更改前的盘符,点击“查找下一个。此处我输入 “E:\”。
可以看到,搜索到了一个结果,即软件安装时写入的注册表数据。双击“URL Protocol”,将其手动替换为“S:\BcutBilibili\Bcut.exe”。
2 Python 替换
手动替换效率过慢,因此使用 Python 来自动替换。给出如下示例代码。
注意:在运行代码时,需要右键点击 Python 或 IDE 图标(如 PyCharm、VS Code),并选择“以管理员身份运行”。否则,会抛出错误:[WinError 5] 拒绝访问。
import re
import winreg as regdef replace_all(old_drive_pattern, new_drive, access_flag=0):# 打开注册表根键replace_root(reg.HKEY_CLASSES_ROOT, "HKEY_CLASSES_ROOT", "", old_drive_pattern, new_drive, access_flag)replace_root(reg.HKEY_CURRENT_USER, "HKEY_CURRENT_USER", "", old_drive_pattern, new_drive, access_flag)replace_root(reg.HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", "", old_drive_pattern, new_drive, access_flag)replace_root(reg.HKEY_USERS, "HKEY_USERS", "", old_drive_pattern, new_drive, access_flag)replace_root(reg.HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG", "", old_drive_pattern, new_drive, access_flag)def replace_root(root_key, root_name, key_path, old_drive_pattern, new_drive, access_flag=0):try:# 打开注册表键reg_key = reg.OpenKey(root_key, key_path, 0, reg.KEY_READ | reg.KEY_WRITE | access_flag)# 遍历所有值i = 0while True:try:value_name, value_data, value_type = reg.EnumValue(reg_key, i)# 处理 REG_SZ 和 REG_EXPAND_SZ 类型的值if value_type == reg.REG_SZ or value_type == reg.REG_EXPAND_SZ:if re.search(old_drive_pattern, value_data):new_value_data = re.sub(old_drive_pattern, new_drive, value_data)reg.SetValueEx(reg_key, value_name, 0, value_type, new_value_data)print(f"{root_name}\\{key_path}\\{value_name}:\n{value_data}\n修改为 -> {new_value_data}\n")# 处理 REG_MULTI_SZ 类型的值elif value_type == reg.REG_MULTI_SZ:new_value_data = []modified = Falsefor item in value_data:if re.search(old_drive_pattern, item):new_value_data.append(re.sub(old_drive_pattern, new_drive, item))modified = Trueelse:new_value_data.append(item)if modified:reg.SetValueEx(reg_key, value_name, 0, value_type, new_value_data)print(f"{root_name}\\{key_path}\\{value_name}:\n{value_data}\n修改为 -> {new_value_data}\n")# 替换键名if re.search(old_drive_pattern, value_name):reg.DeleteValue(reg_key, value_name) # 删除旧的键值对new_name = re.sub(old_drive_pattern, new_drive, value_name)reg.SetValueEx(reg_key, new_name, 0, value_type, value_data) # 创建新的键值对,保留值不变,仅更改键名print(f"{root_name}\\{key_path}:\n修改了键名: {value_name}\n修改为 -> {new_name}\n")i += 1except OSError:break# 遍历子键i = 0while True:try:subkey_name = reg.EnumKey(reg_key, i)subkey_path = f"{key_path}\\{subkey_name}"if key_path == "": # 根目录不添加反斜杠 \subkey_path = subkey_namereplace_root(root_key, root_name, subkey_path, old_drive_pattern, new_drive, access_flag)i += 1except OSError:breakreg.CloseKey(reg_key)except PermissionError:# print(f"没有权限访问键: {key_path}")passexcept FileNotFoundError:# print(f"未找到键: {key_path}")passexcept Exception as e:# print(f"无法打开键: {key_path}, 错误: {e}")pass# 正则表达式模式,仅匹配以"E:\"开头的路径,确保盘符后面直接跟随的是反斜杠
old_drive_pattern = r"(?<![A-Z])E:\\"# 设置新盘符
new_drive = r"S:\\"# 访问 64 位注册表视图
access_flag = reg.KEY_WOW64_64KEY# replace_root(reg.HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Folders", old_drive_pattern, new_drive, access_flag)
replace_all(old_drive_pattern, new_drive, access_flag)print("所有修改完成。")
2.1 注册表数据说明
需要修改的注册表的数据分为以下几种:
- REG_SZ:字符串类型(单行)。
- REG_EXPAND_SZ:可延展字符串,即字符串中含有其他变量的值,类似 C# 内插字符串。
- REG_MULTI_SZ:字符串类型(多行)。
在 replace_root()
函数中,对每种类型进行了分类处理。主要过程还是字符串的匹配替换,以及注册表的读取和写入。
-
REG_SZ 和 REG_EXPAND_SZ:
在程序中,对应的
value_data
为字符串,直接匹配替换即可。 -
REG_MULTI_SZ:
在程序中,对应的
value_data
为字符串列表,需要遍历其中的字符串进行匹配替换。 -
键名:
在程序中,
value_name
也是字符串,直接匹配替换即可。
2.2 正则匹配
使用正则匹配:old_drive_pattern = r"(?<![A-Z])E:\\"
。(?<![A-Z])
是一个负向前瞻断言,确保在 E:
之前没有大写字母。防止像 "SOME:\XXX"
类似情况被匹配。
2.3 其他
- 推荐最好先进行测试,并备份注册表,以防出错。测试时可将 92 行取消注释,并注释 93 行。在 92 行指定测试的路径,这样即便出错,也仅是小范围,方便更改回来。
- 测试通过时,建议程序多运行几次,以更改完全。
- 可以根据具体需求更改正则匹配。
- 注册表部分内容在程序运行时不允许更改,需重启电脑后才能生效。
- 完成注册表修改后,先测试相关软件或功能是否按预期运行。如果没有生效,再考虑重启。如果不确定某些系统配置的更改是否需要重启,重启电脑可以确保所有更改生效。
3 图标问题
对于桌面上已经失效的图标,只有一个个手动更改路径了。
或者将其删除,然后新创建桌面快捷方式,但也需要一个个创建。
4 总结
最好是不要替换盘符,新电脑分区时一旦确定后就不要更改,因为永远不清楚安装的什么软件在什么时候向注册表写了哪些东西。
花了快 2 天时间,初步解决问题。但不清楚后续可能发生什么其他问题,遇到了再说吧!