Python實(shí)現(xiàn)批量修改電腦Windows注冊表
手動(dòng)打開 regedit,逐層找到目標(biāo)鍵值,修改,確認(rèn),重啟……一臺電腦 5 分鐘,1000 臺就是 83 小時(shí)。用 Python?30 分鐘搞定。
為什么需要自動(dòng)化注冊表操作?
Windows 注冊表(Registry)是系統(tǒng)的"中央配置數(shù)據(jù)庫",幾乎所有系統(tǒng)行為都可以通過注冊表控制:
- 軟件配置:安裝路徑、版本號、許可證信息
- 網(wǎng)絡(luò)設(shè)置:代理配置、DNS、防火墻規(guī)則
- 安全策略:密碼策略、賬戶鎖定、UAC 設(shè)置
- 啟動(dòng)項(xiàng)管理:開機(jī)自啟程序、服務(wù)配置
- 文件關(guān)聯(lián):默認(rèn)打開程序、右鍵菜單
在 IT 運(yùn)維中,我們經(jīng)常需要:
- 批量修改代理服務(wù)器地址
- 統(tǒng)一配置防火墻策略
- 禁用 USB 存儲設(shè)備
- 修改遠(yuǎn)程桌面端口
- 清理過期的啟動(dòng)項(xiàng)
手動(dòng)一臺臺改?不存在的。
基礎(chǔ)篇:用 winreg 讀寫本地注冊表
Python 標(biāo)準(zhǔn)庫的 winreg 模塊提供了完整的注冊表操作能力。
注冊表的五大根鍵
HKEY_CLASSES_ROOT (HKCR) — 文件關(guān)聯(lián)和 COM 類信息 HKEY_CURRENT_USER (HKCU) — 當(dāng)前用戶配置 HKEY_LOCAL_MACHINE (HKLM) — 本機(jī)系統(tǒng)配置(最常用) HKEY_USERS (HKU) — 所有用戶配置 HKEY_CURRENT_CONFIG(HKCC) — 當(dāng)前硬件配置
讀操作:查詢注冊表值
import winreg
def read_registry(key_path, value_name, hive=winreg.HKEY_LOCAL_MACHINE):
"""
讀取注冊表值
key_path: 例如 r"SOFTWARE\Microsoft\Windows\CurrentVersion"
value_name: 值的名稱,如 "ProgramFilesDir"
"""
try:
key = winreg.OpenKey(hive, key_path)
value, value_type = winreg.QueryValueEx(key, value_name)
winreg.CloseKey(key)
return value, value_type
except FileNotFoundError:
print(f"鍵或值不存在: {key_path}\\{value_name}")
return None, None
except Exception as e:
print(f"讀取失敗: {e}")
return None, None
# 示例:讀取 Windows 安裝路徑
path, vtype = read_registry(
r"SOFTWARE\Microsoft\Windows\CurrentVersion",
"ProgramFilesDir"
)
print(f"安裝路徑: {path}, 類型: {vtype}")
# 輸出: 安裝路徑: C:\Program Files, 類型: 1 (REG_SZ)
寫操作:修改注冊表值
def write_registry(key_path, value_name, value, hive=winreg.HKEY_LOCAL_MACHINE):
"""
寫入注冊表值(自動(dòng)判斷類型)
"""
# 類型映射
type_map = {
str: winreg.REG_SZ,
int: winreg.REG_DWORD,
bytes: winreg.REG_BINARY,
list: winreg.REG_MULTI_SZ,
}
reg_type = type_map.get(type(value), winreg.REG_SZ)
try:
# 打開鍵(不存在則創(chuàng)建)
key = winreg.CreateKeyEx(hive, key_path, 0, winreg.KEY_WRITE)
winreg.SetValueEx(key, value_name, 0, reg_type, value)
winreg.CloseKey(key)
return True
except PermissionError:
print("權(quán)限不足,請以管理員身份運(yùn)行!")
return False
except Exception as e:
print(f"寫入失敗: {e}")
return False
# 示例:修改代理設(shè)置
write_registry(
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings",
"ProxyEnable",
1 # 啟用代理
)
write_registry(
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings",
"ProxyServer",
"proxy.company.com:8080"
)
列舉子鍵和值
def enumerate_registry(key_path, hive=winreg.HKEY_LOCAL_MACHINE):
"""列舉某個(gè)鍵下的所有子鍵和值"""
key = winreg.OpenKey(hive, key_path)
print(f"=== {key_path} 的子鍵 ===")
idx = 0
while True:
try:
subkey_name = winreg.EnumKey(key, idx)
print(f" [{subkey_name}]")
idx += 1
except OSError:
break
print(f"\n=== {key_path} 的值 ===")
idx = 0
while True:
try:
name, value, vtype = winreg.EnumValue(key, idx)
type_names = {
winreg.REG_SZ: "REG_SZ",
winreg.REG_DWORD: "REG_DWORD",
winreg.REG_BINARY: "REG_BINARY",
winreg.REG_EXPAND_SZ: "REG_EXPAND_SZ",
winreg.REG_MULTI_SZ: "REG_MULTI_SZ",
}
type_name = type_names.get(vtype, f"UNKNOWN({vtype})")
# 二進(jìn)制數(shù)據(jù)截?cái)囡@示
if isinstance(value, bytes):
display = f"<{len(value)} bytes>"
elif isinstance(value, list):
display = ", ".join(str(v) for v in value[:3])
if len(value) > 3:
display += f" ... ({len(value)} items)"
else:
display = str(value)
print(f" {name} = {display} ({type_name})")
idx += 1
except OSError:
break
winreg.CloseKey(key)
# 示例:查看當(dāng)前運(yùn)行的服務(wù)
enumerate_registry(r"SYSTEM\CurrentControlSet\Services")
進(jìn)階篇:注冊表備份與恢復(fù)
修改注冊表前必須備份,這是鐵律。
導(dǎo)出注冊表為 .reg 文件
import subprocess
import datetime
from pathlib import Path
def export_registry(key_path, output_dir=None, hive="HKLM"):
"""
導(dǎo)出注冊表分支到 .reg 文件
使用 Windows 自帶的 reg.exe 命令
"""
if output_dir is None:
output_dir = Path("registry_backups")
output_dir.mkdir(exist_ok=True)
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
safe_name = key_path.replace("\\", "_").replace(" ", "")
filename = output_dir / f"{hive}_{safe_name}_{timestamp}.reg"
cmd = f'reg export "{hive}\\{key_path}" "{filename}" /y'
result = subprocess.run(
cmd, shell=True, capture_output=True, text=True
)
if result.returncode == 0:
print(f"備份成功: {filename}")
return str(filename)
else:
print(f"備份失敗: {result.stderr}")
return None
# 示例:備份代理設(shè)置
export_registry(
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings"
)
通過 .reg 文件恢復(fù)
def import_registry(reg_file):
"""從 .reg 文件恢復(fù)注冊表"""
cmd = f'reg import "{reg_file}"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode == 0:
print(f"恢復(fù)成功: {reg_file}")
return True
else:
print(f"恢復(fù)失敗: {result.stderr}")
return False
# 使用
import_registry("registry_backups/HKLM_SOFTWARE_Microsoft_...20260506.reg")
純 Python 備份(遞歸導(dǎo)出)
如果你需要在 Python 里直接操作而不是調(diào)用 reg.exe:
def backup_key_recursive(key_path, hive=winreg.HKEY_LOCAL_MACHINE):
"""
遞歸備份注冊表鍵,返回嵌套字典結(jié)構(gòu)
"""
try:
key = winreg.OpenKey(hive, key_path)
except FileNotFoundError:
return None
data = {"_values": {}, "_subkeys": {}}
# 備份所有值
idx = 0
while True:
try:
name, value, vtype = winreg.EnumValue(key, idx)
data["_values"][name] = {"value": value, "type": vtype}
idx += 1
except OSError:
break
# 遞歸備份子鍵
idx = 0
while True:
try:
subkey_name = winreg.EnumKey(key, idx)
sub_path = f"{key_path}\\{subkey_name}"
data["_subkeys"][subkey_name] = backup_key_recursive(sub_path, hive)
idx += 1
except OSError:
break
winreg.CloseKey(key)
return data
# 導(dǎo)出為 JSON
import json
backup = backup_key_recursive(
r"SOFTWARE\MyApp\Config"
)
with open("registry_backup.json", "w", encoding="utf-8") as f:
json.dump(backup, f, ensure_ascii=False, indent=2, default=str)
實(shí)戰(zhàn)篇:批量遠(yuǎn)程注冊表操作
核心場景來了——一次性修改 1000 臺電腦的注冊表。
方案一:WMI 遠(yuǎn)程操作
import wmi
from concurrent.futures import ThreadPoolExecutor, as_completed
def remote_read_registry(
computer, key_path, value_name,
hive="HKEY_LOCAL_MACHINE",
username=None, password=None
):
"""
通過 WMI 遠(yuǎn)程讀取注冊表
需要目標(biāo)電腦開啟 WMI 服務(wù)和遠(yuǎn)程管理
"""
try:
if username and password:
# 帶憑據(jù)連接
c = wmi.WMI(
computer,
user=f".\\{username}",
password=password
)
else:
# 當(dāng)前域憑據(jù)連接
c = wmi.WMI(computer)
# 使用 StdRegProv 類
registry = c.StdRegProv
# hive 映射
hive_map = {
"HKEY_CLASSES_ROOT": 0x80000000,
"HKEY_CURRENT_USER": 0x80000001,
"HKEY_LOCAL_MACHINE": 0x80000002,
"HKEY_USERS": 0x80000003,
}
hive_id = hive_map.get(hive, 0x80000002)
# 先獲取值的類型
result, value_type = registry.GetStringValue(
hDefKey=hive_id,
sSubKeyName=key_path,
sValueName=value_name
)
if result == 0:
return {"computer": computer, "value": value, "status": "ok"}
else:
return {"computer": computer, "value": None, "status": "not_found"}
except wmi.x_wmi as e:
return {"computer": computer, "value": None, "status": f"WMI錯(cuò)誤: {e}"}
except Exception as e:
return {"computer": computer, "value": None, "status": f"錯(cuò)誤: {e}"}
def batch_read_registry(computers, key_path, value_name, max_workers=20):
"""并發(fā)批量讀取多臺電腦的注冊表"""
results = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {
executor.submit(
remote_read_registry, pc, key_path, value_name
): pc
for pc in computers
}
for future in as_completed(futures):
result = future.result()
results.append(result)
status_icon = "?" if result["status"] == "ok" else "?"
print(f" {status_icon} {result['computer']}: {result['status']}")
return results
# 示例:檢查 100 臺電腦的代理設(shè)置
computers = [f"PC-{i:03d}" for i in range(1, 101)]
results = batch_read_registry(
computers,
key_path=r"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings",
value_name="ProxyServer"
)
# 統(tǒng)計(jì)
success = sum(1 for r in results if r["status"] == "ok")
print(f"\n成功: {success}/{len(results)}")
方案二:PsExec 遠(yuǎn)程執(zhí)行
對于 WMI 不方便的場景,可以用 PsExec 遠(yuǎn)程執(zhí)行命令:
import subprocess
import tempfile
from pathlib import Path
def remote_registry_via_psexec(
computer, script_content,
psexec_path=r"C:\Tools\PSTools\PsExec.exe",
username=None, password=None
):
"""
通過 PsExec 在遠(yuǎn)程電腦上執(zhí)行注冊表操作腳本
"""
# 生成臨時(shí) Python 腳本
with tempfile.NamedTemporaryFile(
mode="w", suffix=".py", delete=False, encoding="utf-8"
) as f:
f.write(script_content)
temp_script = f.name
try:
cmd = [
psexec_path,
f"\\\\{computer}",
"-s", # 以 SYSTEM 賬戶運(yùn)行
"-nobanner",
]
if username and password:
cmd.extend(["-u", username, "-p", password])
cmd.extend([
"python",
temp_script
])
result = subprocess.run(
cmd, capture_output=True, text=True, timeout=120
)
return {
"computer": computer,
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode,
}
finally:
Path(temp_script).unlink(missing_ok=True)
實(shí)用工具函數(shù)集合
以下是運(yùn)維中最高頻的注冊表操作,直接拿去用。
禁用/啟用 USB 存儲設(shè)備
def disable_usb_storage(enable=True):
"""
禁用或啟用 USB 大容量存儲設(shè)備
enable=False 禁用, enable=True 啟用
"""
value = 4 if not enable else 3 # 4=禁用, 3=啟用
# 方法1:通過注冊表
write_registry(
r"SYSTEM\CurrentControlSet\Services\USBSTOR",
"Start",
value
)
# 方法2:額外阻止安裝新 USB 設(shè)備
write_registry(
r"SOFTWARE\Policies\Microsoft\Windows\RemovableStorageDevices",
"Deny_All",
1 if not enable else 0
)
print(f"USB 存儲 {'已啟用' if enable else '已禁用'}")
修改遠(yuǎn)程桌面端口
def change_rdp_port(new_port=33890):
"""修改遠(yuǎn)程桌面端口(默認(rèn) 3389)"""
if not (1024 <= new_port <= 65535):
print("端口范圍必須在 1024-65535 之間")
return False
# 1. 修改注冊表中的端口
success = write_registry(
r"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp",
"PortNumber",
new_port
)
if success:
# 2. 添加防火墻規(guī)則
firewall_cmd = (
f'netsh advfirewall firewall add rule '
f'name="RDP {new_port}" dir=in action=allow '
f'protocol=TCP localport={new_port}'
)
subprocess.run(firewall_cmd, shell=True, capture_output=True)
print(f"RDP 端口已修改為 {new_port}")
print("請重啟電腦使更改生效")
return success
自動(dòng)清理無效的卸載殘留
def cleanup_uninstall_entries():
"""
掃描并報(bào)告注冊表中的無效卸載條目
(程序已刪除但注冊表殘留的情況)
"""
uninstall_key = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, uninstall_key)
orphaned = []
idx = 0
while True:
try:
subkey_name = winreg.EnumKey(key, idx)
subkey = winreg.OpenKey(key, subkey_name)
try:
display_name, _ = winreg.QueryValueEx(subkey, "DisplayName")
install_location, _ = winreg.QueryValueEx(
subkey, "InstallLocation"
)
# 檢查安裝路徑是否存在
if install_location and not Path(install_location).exists():
orphaned.append({
"name": display_name,
"subkey": subkey_name,
"path": install_location,
})
except FileNotFoundError:
# 沒有 DisplayName 或 InstallLocation,跳過
pass
finally:
winreg.CloseKey(subkey)
idx += 1
except OSError:
break
winreg.CloseKey(key)
if orphaned:
print(f"發(fā)現(xiàn) {len(orphaned)} 個(gè)無效卸載條目:")
for item in orphaned:
print(f" - {item['name']}")
print(f" 路徑: {item['path']} (不存在)")
print(f" 鍵: {item['subkey']}")
else:
print("未發(fā)現(xiàn)無效卸載條目")
return orphaned
批量查詢所有電腦的安裝軟件
def get_installed_software(hive=winreg.HKEY_LOCAL_MACHINE):
"""獲取已安裝軟件列表"""
uninstall_paths = [
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
]
software = []
for uninstall_path in uninstall_paths:
try:
key = winreg.OpenKey(hive, uninstall_path)
except FileNotFoundError:
continue
idx = 0
while True:
try:
subkey_name = winreg.EnumKey(key, idx)
subkey = winreg.OpenKey(key, subkey_name)
info = {}
for field in ["DisplayName", "DisplayVersion",
"Publisher", "InstallDate", "UninstallString"]:
try:
val, _ = winreg.QueryValueEx(subkey, field)
info[field] = val
except FileNotFoundError:
pass
if info.get("DisplayName"):
software.append(info)
winreg.CloseKey(subkey)
idx += 1
except OSError:
break
winreg.CloseKey(key)
# 去重 + 排序
seen = set()
unique = []
for s in sorted(software, key=lambda x: x.get("DisplayName", "")):
name = s.get("DisplayName", "")
if name not in seen:
seen.add(name)
unique.append(s)
return unique
# 使用
software = get_installed_software()
print(f"已安裝 {len(software)} 個(gè)軟件")
for s in software[:10]:
print(f" {s.get('DisplayName')} {s.get('DisplayVersion', '')}")
安全注意事項(xiàng)
操作注冊表時(shí),務(wù)必記住:
備份優(yōu)先:修改前總是先導(dǎo)出相關(guān)鍵值
最小權(quán)限:能用 HKCU 就不用 HKLM(后者影響所有用戶)
管理員權(quán)限:修改 HKLM 需要管理員權(quán)限,腳本開頭加檢查:
import ctypes
import sys
def require_admin():
"""檢查是否以管理員身份運(yùn)行"""
if not ctypes.windll.shell32.IsUserAnAdmin():
print("此操作需要管理員權(quán)限!")
print("請右鍵選擇「以管理員身份運(yùn)行」")
sys.exit(1)
require_admin()
64 位注意:在 64 位系統(tǒng)上,Python 默認(rèn)訪問 64 位視圖。如需訪問 32 位視圖:
# 訪問 32 位注冊表視圖
KEY_WOW64_64KEY = 0x0100
KEY_WOW64_32KEY = 0x0200
key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\MyApp",
0,
winreg.KEY_READ | KEY_WOW64_32KEY # 強(qiáng)制 32 位視圖
)
測試先行:先在測試機(jī)上驗(yàn)證,再批量推生產(chǎn)環(huán)境
完整實(shí)戰(zhàn):一鍵配置新電腦
把上面的函數(shù)組合起來,做一個(gè)新電腦初始化腳本:
def setup_new_computer():
"""新電腦初始化配置"""
require_admin()
print("=== 新電腦初始化配置 ===\n")
# 1. 備份當(dāng)前配置
print("[1/6] 備份當(dāng)前配置...")
export_registry(r"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings")
export_registry(r"SYSTEM\CurrentControlSet\Services\USBSTOR")
# 2. 配置代理
print("[2/6] 配置代理服務(wù)器...")
write_registry(
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings",
"ProxyEnable", 1
)
write_registry(
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings",
"ProxyServer", "proxy.company.com:8080"
)
# 3. 修改 RDP 端口
print("[3/6] 修改遠(yuǎn)程桌面端口...")
change_rdp_port(33990)
# 4. 禁用 USB 存儲
print("[4/6] 禁用 USB 存儲...")
disable_usb_storage(enable=False)
# 5. 配置 PowerShell 執(zhí)行策略
print("[5/6] 配置 PowerShell 執(zhí)行策略...")
subprocess.run(
["powershell", "-Command", "Set-ExecutionPolicy RemoteSigned -Scope MachinePolicy"],
capture_output=True
)
# 6. 啟用 Windows 遠(yuǎn)程管理
print("[6/6] 啟用 WinRM...")
subprocess.run(
["powershell", "-Command", "Enable-PSRemoting -Force"],
capture_output=True
)
print("\n=== 配置完成!請重啟電腦使所有更改生效 ===")
setup_new_computer()
小結(jié)
| 操作 | 方法 | 適用場景 |
|---|---|---|
| 讀注冊表 | winreg.QueryValueEx() | 獲取配置信息 |
| 寫注冊表 | winreg.SetValueEx() | 修改系統(tǒng)配置 |
| 枚舉子鍵 | winreg.EnumKey() | 遍歷服務(wù)/軟件列表 |
| 遠(yuǎn)程操作 | WMI StdRegProv | 批量管理多臺電腦 |
| 備份恢復(fù) | reg export/import 或 Python 遞歸 | 修改前必須備份 |
| 64位視圖 | KEY_WOW64_32KEY 標(biāo)志 | 訪問 32 位軟件注冊表 |
注冊表操作是 Windows 運(yùn)維的基本功。掌握了這些,批量配置電腦、排查問題、安全加固都能輕松搞定。
以上就是Python實(shí)現(xiàn)批量修改電腦Windows注冊表的詳細(xì)內(nèi)容,更多關(guān)于Python修改Windows注冊表的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python搭建代理IP池實(shí)現(xiàn)存儲IP的方法
這篇文章主要介紹了Python搭建代理IP池實(shí)現(xiàn)存儲IP的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
python實(shí)現(xiàn)讀取學(xué)術(shù)論文PDF文件內(nèi)容
這篇文章主要為大家詳細(xì)介紹了如何通過python實(shí)現(xiàn)讀取學(xué)術(shù)論文PDF文件內(nèi)容的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10
Python中pandas庫sort_values()方法的使用
最后去看了有關(guān)于 sort_values 的文檔,成功解決先把單詞出現(xiàn)頻次由高往低依次排序,再把頻次相同的情況下的單詞按照 MD5 值排序這個(gè)問題,下面通過本文講解下Python中pandas庫sort_values()方法的使用,感興趣的朋友一起看看吧2023-07-07

