在 Windows 机器上,有没有办法在不持续监视 WM_TIMECHANGE 消息的情况下找出时间是否向后更改?
例如,我想让我的应用程序在启动时执行的第一件事是查看自上次运行应用程序以来时间是否已改回。
据我所知,查看更改的唯一方法是查看 WM_TIMECHANGE 消息,但只有在我的应用程序正在运行时我才会看到。
是的。您可以阅读 Windows 事件日志 并查找系统时间的更改。 (系统时间更改是自动记录的系统事件之一。)例如,我刚刚将系统时间调整了几秒钟,系统事件日志中出现以下内容:
信息 10/21/2011 11:16:26 AM 内核常规 1 无
系统时间已更改为u200e2011u200e-u200e10u200e-u200e21T16:16:26.000000000Z 从u200e2011u200e-u200e10u200e-u200e21T16:16:26.000000000Z.
您可以使用 Win32 API 访问事件日志,然后查询这些事件以确定时间是否确实被更改。该解决方案的优点在于它是内置的并且始终运行。无需通过自定义服务等监控事件。您只需查询操作系统的数据。
这仍然不是一个万无一失的解决方案,因为具有管理员权限的人可以更改设置、清除日志等。但您肯定会对您的应用程序进行外行防护。系统事件日志不是普通 Windows 用户考虑的事情。
该特定事件的 XML:(出于隐私和安全考虑,已去识别化)
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Kernel-General"
Guid="{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" />
<EventID>1</EventID>
<Version>0</Version>
<Level>4</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000010</Keywords>
<TimeCreated SystemTime="2011-10-21T16:16:26.001000000Z" />
<EventRecordID>138478</EventRecordID>
<Correlation />
<Execution ProcessID="40044" ThreadID="50016" />
<Channel>System</Channel>
<Computer>xxxxx.xxxxxxxxx.org</Computer>
<Security UserID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
</System>
<EventData>
<Data Name="NewTime">2011-10-21T16:16:26.000000000Z</Data>
<Data Name="OldTime">2011-10-21T16:16:26.000000000Z</Data>
</EventData>
</Event>
不,你不能。这就是为什么时间敏感的 DRM 方案通常毫无用处。
你可以尝试通过使用服务来解决这个问题,然后你必须通过使用另一个黑客以及在此基础上的另一个黑客来解决服务的停机时间。
无论如何,如果这就是您想要做的,那么只需将程序关闭时的系统时间值存储在某个地方(可能是加密的),然后确保它没有在程序启动时传递应该就足够了。它不会阻止用户基本上“冻结”从关机到启动的时间,但对于 9/10 试图通过定时试用的人来说这已经足够了。
您可以让您的应用程序(当它恰好正在运行时)定期将系统时间与从某处服务器资源获取的时间进行比较。如果你突然发现系统时间和服务器时间的差距变大了,那就说明系统时间被调回来了。
显然这在无法访问互联网的机器上不起作用。
上述的一个想法(虽然我注意到,如果可行的话,检查外部时钟是最终的答案) - 您还可以定期读取系统时钟并将其存储(可能是加密的)在某个隐藏文件中。每次执行此操作时,您都会检查以确保新值比文件中的值更新。执行此操作的触发因素可能是在每次启动时等。
与所有内部方法一样,这个方法很容易被人发现隐藏文件。因此,如果隐藏文件丢失,或者其日期戳与其内容不匹配,您也可以标记问题。