Winreg Python,QueryInfoKey 为上次更改提供不正确的日期/时间?

Posted

技术标签:

【中文标题】Winreg Python,QueryInfoKey 为上次更改提供不正确的日期/时间?【英文标题】:Winreg Python, QueryInfoKey giving incorrect date/times for the last changed? 【发布时间】:2018-01-20 12:08:27 【问题描述】:

我有一个函数可以遍历包含找到的注册表项路径的列表。 我现在需要从该键列表中找到每个注册表键最后一次更改的日期。

def get_values(subkeylist):
try:
    x = 0
    nanos = []
    while x < len(subkeylist):
        keypath = subkeylist[x]
        key = OpenKey(HKEY_CURRENT_USER, keypath, 0, KEY_ALL_ACCESS)
        secs = QueryInfoKey(key)[2] / 1e9
        dt = datetime.fromtimestamp(secs)
        dt.strftime('%Y-%m-%dT%H:%M:%S.%f')
        print(dt)
        x += 1
except WindowsError:
 pass

我觉得我在这里做错了什么,或者键中保存的值不正确。 shell中的输出如下:

1974-03-04 05:54:37.481353 1974-03-04 05:54:37.481433 1974-03-04 05:54:37.481443

这是自 EPOCH 1601 以来转换前的实际输出(以纳秒为单位)。(QueryInfoKey:一个整数,给出自 1601 年 1 月 1 日以来最后一次修改密钥的时间(如果可用)为 100 纳秒)。

131608477481353446 131608477481433451 131608477481443451

【问题讨论】:

【参考方案1】:

正如您所指出的,注册表似乎以 FILETIME structure 格式存储时间戳,而 Python 的日期和时间函数需要 Unix 时间戳,即自 1970 年 1 月 1 日以来的 数。

如果您将01.01.1601 + (131608477481353446 * 100 ns) 插入 WolframAlpha,您会看到它转换为 2018 年 1 月 19 日,因此键中的值似乎是正确的,您只需正确解码即可。

from datetime import datetime, timedelta

WIN32_EPOCH = datetime(1601, 1, 1)

def dt_from_win32_ts(timestamp):
    return WIN32_EPOCH + timedelta(microseconds=timestamp // 10)

key = OpenKey(...)
ts = QueryInfoKey(key)[2]
dt = dt_from_win32_ts(ts)
print(dt.strftime('%Y-%m-%dT%H:%M:%S.%f'))
# 2018-01-19T15:02:28.135344

Python 的datetime 模块支持微秒分辨率,这意味着我们会丢失一位小数。

【讨论】:

非常感谢您的帮助。为迟到的回复道歉。

以上是关于Winreg Python,QueryInfoKey 为上次更改提供不正确的日期/时间?的主要内容,如果未能解决你的问题,请参考以下文章

python _winreg模块

转 Python模块——_winreg操作注册表

转 Python的:WinReg项模块:Windows 7中:无无效HKEY错误

转 Python的WinReg项通过子键循环

转 python的_winreg的SetValueEx如何使用

转 python _winreg 操作注册表