You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3.11中winreg.SaveKey()返回WinError1314并生成空文件求助

解决Winreg.SaveKey报WinError 1314的问题

你遇到的问题核心是:管理员身份默认不包含SaveKey所需的备份/还原特权,虽然IsUserAnAdmin()返回True,但这两个特权在默认管理员会话里是禁用状态,必须手动启用才能正常调用SaveKey。

解决步骤

需要通过ctypes调整进程的特权状态,启用SeBackupPrivilege和SeRestorePrivilege,之后再执行SaveKey操作。以下是修正后的代码:

import winreg
import ctypes
from ctypes import wintypes

# 定义所需的Windows API结构和函数
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)

class LUID(ctypes.Structure):
    _fields_ = [
        ('LowPart', wintypes.DWORD),
        ('HighPart', wintypes.LONG)
    ]

class LUID_AND_ATTRIBUTES(ctypes.Structure):
    _fields_ = [
        ('Luid', LUID),
        ('Attributes', wintypes.DWORD)
    ]

class TOKEN_PRIVILEGES(ctypes.Structure):
    _fields_ = [
        ('PrivilegeCount', wintypes.DWORD),
        ('Privileges', LUID_AND_ATTRIBUTES * 1)
    ]

TOKEN_ADJUST_PRIVILEGES = 0x0020
TOKEN_QUERY = 0x0008
SE_PRIVILEGE_ENABLED = 0x00000002

def enable_privilege(privilege_name):
    htoken = wintypes.HANDLE()
    # 获取当前进程的令牌
    if not advapi32.OpenProcessToken(
        ctypes.windll.kernel32.GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
        ctypes.byref(htoken)
    ):
        raise ctypes.WinError(ctypes.get_last_error())
    
    try:
        luid = LUID()
        # 获取特权对应的LUID
        if not advapi32.LookupPrivilegeValueW(
            None, privilege_name, ctypes.byref(luid)
        ):
            raise ctypes.WinError(ctypes.get_last_error())
        
        tp = TOKEN_PRIVILEGES()
        tp.PrivilegeCount = 1
        tp.Privileges[0].Luid = luid
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
        
        # 启用特权
        if not advapi32.AdjustTokenPrivileges(
            htoken,
            False,
            ctypes.byref(tp),
            ctypes.sizeof(tp),
            None,
            None
        ):
            raise ctypes.WinError(ctypes.get_last_error())
        
        # 检查特权是否成功启用
        error = ctypes.get_last_error()
        if error == 1300:
            raise RuntimeError("特权未被授予")
    finally:
        ctypes.windll.kernel32.CloseHandle(htoken)

# 启用备份和还原特权
enable_privilege('SeBackupPrivilege')
enable_privilege('SeRestorePrivilege')

# 验证管理员身份
print(ctypes.windll.shell32.IsUserAnAdmin())  # 应该返回True

location = r"C:\Users\Key.reg"
# 注意:打开键时用KEY_READ即可,SaveKey不需要KEY_ALL_ACCESS
with winreg.OpenKey(winreg.HKEY_USERS, ".DEFAULT", access=winreg.KEY_READ) as key:
    winreg.SaveKey(key, location)

# 验证文件内容
with open(location, 'r') as f:
    print(f.read())

关键说明

  • 为什么需要这两个特权?Windows的RegSaveKey API(winreg.SaveKey底层调用的就是它)明确要求调用者拥有SeBackupPrivilege,否则会返回ERROR_PRIVILEGE_NOT_HELD(1314)。
  • 打开注册表键时不需要KEY_ALL_ACCESS,KEY_READ权限足够,减少不必要的权限风险。
  • 特权启用后仅对当前进程有效,关闭进程后特权会自动失效。

内容的提问来源于stack exchange,提问作者kubinka0505

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:12:53