【问题标题】:Find out if computer rebooted since the last time my program ran?找出自上次运行我的程序后计算机是否重新启动?
【发布时间】:2009-11-12 22:21:46
【问题描述】:

我的程序如何知道自上次运行以来 Windows 是否重新启动?所有版本的 Windows XP 及更高版本。

【问题讨论】:

    标签: windows winapi


    【解决方案1】:

    这可以使用global atom table 轻松完成。只需确保您的 atom 名称不太可能与另一个 atom 冲突。

    if (GlobalFindAtom ("MySecretName") == 0)
    {
      // First time run since reboot
      GlobalAddAtom ("MySecretName");
    }
    

    【讨论】:

    • 比 GetTickCount() 解决方案干净得多。 +1
    • “不太可能发生冲突”:我总是将新的 GUID 放入全局名称中。
    【解决方案2】:

    您可以调用 Windows API 调用 GetTickCount...

    http://msdn.microsoft.com/en-us/library/ms724408%28VS.85%29.aspx

    编辑:这个想法是,当你的程序启动时,你调用 GetTickCount(它返回 Windows 已经运行了多少毫秒),然后计算一个确切的开始日期(现在减去毫秒数)。存储该日期,然后下次程序启动时,再次计算日期并将其与之前存储的日期进行比较。如果日期不同,则 Windows 已重新启动。如果可能,请使用GetTickCount64(但不要仅使用此函数编写解决方案。

    【讨论】:

    • 它可以解决 99% 的用例。请注意暗角:仅当程序在启动后不久启动时才能正常工作(即last_ticks >> current_ticks)。另一个限制是它只计算最多 49.7 天
    • 使用GetTickCount64() 避免在正常运行约 50 天后出现包装问题。 msdn.microsoft.com/en-us/library/ms724411%28VS.85%29.aspx
    • ...虽然需要特定版本的 Windows 内核才能使用该功能。
    • @Jon:公平地说,49.7 天通常不是问题。
    • GetTickCount() 有什么帮助?
    【解决方案3】:

    您可以使用 WMI:

        strComputer = "."
    Set objWMIService = GetObject _
        ("winmgmts:\\" & strComputer & "\root\cimv2")
    Set colOperatingSystems = objWMIService.ExecQuery _
        ("Select * from Win32_OperatingSystem")
    For Each objOS in colOperatingSystems
        dtmBootup = objOS.LastBootUpTime
        dtmLastBootupTime = WMIDateStringToDate(dtmBootup)
        dtmSystemUptime = DateDiff("h", dtmLastBootUpTime, Now)
        Wscript.Echo dtmSystemUptime
    Next
    Function WMIDateStringToDate(dtmBootup)
        WMIDateStringToDate = CDate(Mid(dtmBootup, 5, 2) & "/" & _
             Mid(dtmBootup, 7, 2) & "/" & Left(dtmBootup, 4) _
             & " " & Mid (dtmBootup, 9, 2) & ":" & _
             Mid(dtmBootup, 11, 2) & ":" & Mid(dtmBootup, _
             13, 2))
    End Function
    

    【讨论】:

    • 你怎么知道他的程序是用VB写的?
    • 我没有。但 WMI api 可供他研究。
    【解决方案4】:
    net statistics workstation|find "Statistics since"
    

    【讨论】:

      【解决方案5】:

      Microsoft 实用程序uptime.exe“处理机器的事件日志以确定系统可用性和当前正常运行时间”。

      【讨论】:

        【解决方案6】:

        简单但丑陋的解决方案:只需启动一个永无止境的虚拟进程 :-)

        如果它仍然在这里,则说明您没有重新启动。如果不是,很可能您刚刚重新启动。

        【讨论】:

        • 如果有人杀死了那个虚拟进程?
        • 这是主要问题(这就是我说“机会是”的原因)。实际上你可以定期检查它的存在,但它更像是一个丑陋的黑客而不是真正的解决方案(寻找尾随的笑脸)
        【解决方案7】:

        在丑陋的黑客中......在RunOnce 注册表项之一中粘贴一些东西

        【讨论】:

        • 请您解释一下您的想法。以及它如何在不同的非管理员用户帐户下连续运行。 TIA。
        • 它可能不适用于非管理员帐户......这是一个丑陋的黑客!模糊的想法是查看 Windows 是否删除了该条目,这意味着发生了重新启动。
        【解决方案8】:

        如何将文件添加到 %TMP% 并检查它是否仍然存在(%TMP% 应该在 Windows 每次重新启动时清除)

        更健壮的方法,在某处创建一个文件并在下次重新启动时将其标记为删除(请参阅MoveFileEx API)并检查该文件

        【讨论】:

        • %TMP% 是否在每次重新启动时清除?我那里有几年前的文件!此外,MoveFileEx 技巧似乎需要管理员权限,对吧?
        • 嗯,我的 %TMP% 中也有一些最后修改 = yr 2006 的文件,而这个系统此时 不存在,所以看起来 %TMP% 不是那么临时. MoveFileEx 不需要管理员权限 AFAIK,您只需要删除或重命名您希望它操作的文件的权限。
        • %TMP% 在每次重新启动时清除,并且根据文档MoveFileEx() 可以与MOVEFILE_DELAY_UNTIL_REBOOT 一起使用 仅当进程在属于管理员组或 LocalSystem 帐户的用户的上下文
        猜你喜欢
        • 2021-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-14
        • 1970-01-01
        • 1970-01-01
        • 2011-05-16
        相关资源
        最近更新 更多