问题
在我们的公司环境中,我们使用几个批处理文件,这些文件使用 WMIC 来检索当前时间。通常将其打印到日志文件中,但也将时间戳包含在文件名中。
从 Windows 10 开始(我们不记得在 Windows 7 上看到过这种行为),我们发现我们的一些日志文件解析器(它们会创建一些不错的图表供评估)似乎会绘制出奇怪的东西。经过一番研究,我们发现,在短时间内,对 WMIC 的调用会返回不同的时间戳。
这就是我们调用 WMIC 的方式以及它返回的内容。
C:\> WMIC.exe OS Get localdatetime /value
LocalDateTime=20191114112607.134000+060
现在我们做了一个实验,在更长的时间内每秒调用一次 WMIC。以下是结果时间戳的摘录:
20191114112607.134000+060
20191114122608.394000+120
20191114122609.687000+120
[...]
20191114123105.161000+120
20191114123106.431000+120
20191114113107.672000+060
我们生活在 MEZ 时区,即 UTC+1。这就是为什么我们期望时间戳带有+060
分钟指示的原因。我们也不期望它会改变,除非每年两次,即夏令时切换到 MESZ(UTC+2)反之亦然。
正如您在上面的时间戳中看到的:几乎正好 5 分钟,WMIC 返回了+120
时间戳。
分析
我还记录了一些其他调用的输出,以检查这是否是 Windows 的全局问题,还是 wmic 的行为。所有这些似乎都是 WMIC 的一种(有缺陷的?)行为。
所有函数/程序甚至另一个 WMIC 调用都返回了预期时间。这是我的脚本
while ($true) {
Get-Date -Format G
Get-TimeZone
$timeservers | ForEach-Object {
$server = $_
w32tm.exe /stripchart /computer:$server /dataonly /samples:1 | Out-Default
}
cmd.exe /c date /T | Out-Default
cmd.exe /c time /T | Out-Default
WMIC.exe Path Win32_LocalTime Get /Format:value | Out-Default
# All 'correct' except:
WMIC.exe OS Get localdatetime /value | Out-Default
Start-Sleep -Seconds 1
}
上述脚本的输出显示,只有调用OS Get localdatetime
返回了“错误”的时间戳。我们已经在系统和应用程序事件日志中搜索了可以告诉我们为什么会发生这种情况的条目,但没有记录任何条目。我还检查了任务计划程序,看是否安排了某些操作在发生这种情况时运行,但什么也没有。
註冊時區信息
C:\>reg query HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
Bias REG_DWORD 0xffffffc4
DaylightBias REG_DWORD 0xffffffc4
DaylightName REG_SZ @tzres.dll,-321
DaylightStart REG_BINARY 00000300050002000000000000000000
DynamicDaylightTimeDisabled REG_DWORD 0x0
StandardBias REG_DWORD 0x0
StandardName REG_SZ @tzres.dll,-322
StandardStart REG_BINARY 00000A00050003000000000000000000
TimeZoneKeyName REG_SZ W. Europe Standard Time
ActiveTimeBias REG_DWORD 0xffffffc4
问题
- 有人可以解释这种行为吗?
- 哪些因素可能影响 WMIC 的结果?
- 您认为这是一种错误吗?
- 还可以进行哪些分析来缩小范围?
答案1
这是一个已知的 Windows Bug。
内部有一个全局变量,用于缓存 DST 偏移量,该变量的值会保留 5 分钟。5 分钟后,该值会消失,导致本地时间跳跃。
该逻辑在 RS5/1809 中使用过,但在 19H1 或 Windows Server 2012 R2 中没有使用。
解决方法:
经常启动机器,以便机器长时间运行时 LocalDateTime 和 LastBootUpTime 不会出现不同的时区
使用启动时运行的脚本将 InstallDate 设置为上次重启的时间也应该可以避免这个问题