【问题标题】:How to determine if the PC has been rebooted since my program's last run?如何确定自我的程序上次运行以来 PC 是否已重新启动?
【发布时间】:2021-03-28 04:38:18
【问题描述】:

标题说明了一切。

确定自上次运行我的程序后 PC 是否已重新启动的最佳方法是什么?

上下文: C# - Win XP 及更高版本

我正在配置的一块硬件(PCIe 板)要求设置在每次重启时仅发送一次,但用户可能会在重启 PC 之前多次关闭和打开程序。

我在想我需要某种全局引用,我的程序在启动时启动/设置,然后它可以检查所述全局引用在每次启动时是否正在运行/为真并采取相应的行动。

想法?有什么建议吗?

【问题讨论】:

  • 您可以在程序运行时在注册表中存储一个时间戳。如果时间戳存在,表明您的程序之前已经运行过,您可以获得系统正常运行时间并查看您的时间戳是在它之前还是之后。 stackoverflow.com/questions/972105/…
  • 您可以添加一个计划任务,该任务在启动时触发以写入文件。然后在发送硬件设置后清空该文件。
  • 我认为应该有一个系统调用告诉你这个
  • PCIe 板上是否有任何易失性设置可以用来记住其设置已设置?
  • 通电总是记录在事件日志中。您无需向注册表写入任何内容或使用任何可能实际失败的计划任务

标签: c# windows boot


【解决方案1】:

请参阅How to know when was Windows started or shutdown,了解如何获取上次启动时间。

您可以将启动时间写入文件。启动程序时,您可以检查保存的值是否与当前值匹配,并在需要时使用新值更新文件。

另见Getting last reboot time

【讨论】:

  • 这些方法通常不适用于 Windows 10,因为关机不会重置计时器。重启会,关机不会。
【解决方案2】:

看起来可以在Windows Event Log 中查找启动时间。我还没有验证这一点,但也许这对你有用。

您可以手动use the Event Viewer to find the PC's boot time。这将为您提供进行编程调用以获取相关数据所需的信息。你会做这样的事情(不是一个完整的解决方案):

var logs = EventLog.GetEventLogs();
// not sure about this; you may need to change the search below...
var log = logs.Single(l => l.LogDisplayName == "Application and Services Log");
// search entries
var bootEntries = log.Entries.Where(x => ...);
...

这使用了这些 API

因此,看起来可以深入到您需要的条目,获取时间戳并进行各种检查。祝你好运!

【讨论】:

    【解决方案3】:

    保存上次启动时间(例如在user.config 中),然后将其与当前值进行比较。 Environment.TickCount64 跟踪系统启动后的时间。

    var storedLastBootTime = LoadBootTimeFromSettings();
    
    var currentTime = DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond;
    var lastBootTime = currentTime - Environment.TickCount64;
    
    if (lastBootTime > storedLastBootTime)
    {
        // A system reboot must have taken place!
    }
    
    SaveBootTimeToSettings(lastBootTime);
    
    

    如果保存的值更大,则必须重新启动。要处理这个问题,您还需要保存当前时间。

    【讨论】:

      【解决方案4】:

      作为用户Panagiotis Kanavos commented,Windows 启动时会写入一个事件日志条目。

      如果您查看系统日志中的事件查看器,您会发现这些条目的事件 ID == 12,可以使用 EventLogEntry 的 InstanceId 属性在代码中访问(不推荐使用 EventID 属性)。

      因此,您可以获取所有这些日志条目,对其进行排序,然后获取最新的条目,如下所示:

      using System;
      using System.Diagnostics;
      using System.Linq;
      
      namespace ConsoleApp2
      {
          class Program
          {
              static void Main(string[] args)
              {
                  EventLog systemLog = new EventLog("System");
                  var bootEntry = systemLog?.Entries.Cast<EventLogEntry>().
                      Where(x => x.InstanceId == 12).
                      OrderByDescending(x => x.TimeGenerated).
                      FirstOrDefault();
      
                  if (bootEntry != null)
                  {
                      Console.WriteLine("Last boot: " + bootEntry.TimeGenerated.ToString("yyyy-MM-dd HH:mm:ss"));
                  }
                  else
                  {
                      Console.WriteLine("Could not open System log or no boot event found.");
                  }
      
                  Console.ReadLine();
              }
          }
      }
      

      (经测试可在 Windows 10 20H2 上运行。)

      现在,我的计算机有一个快速的 SSD,而我从 HDD 读取事件日志的经验是,这可能很慢,所以您可能希望在某些后台任务中获取条目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-18
        • 1970-01-01
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        相关资源
        最近更新 更多