windows 关机重启

一 windows 关机重启流程

1 用户请求关机:
用户通过开始菜单、快捷键(如Alt+F4),或其他手段(如命令行)发起关机请求。

2 通知应用程序:
Windows向所有运行中的应用程序发送WM_QUERYENDSESSION消息。这是一个通知,告知应用程序系统即将关闭。

https://learn.microsoft.com/zh-cn/windows/win32/shutdown/wm-queryendsession
image.png

应用程序应保存数据并清理资源。如果需要,应用程序可以请求取消关机(尽管用户可以决定强制关机)。

3 确认关机意图:
用户有机会通过对话框确认或取消关机请求。

4 终止应用程序:
Windows向所有应用程序发送WM_ENDSESSION消息。应用程序必须保存未完成的工作并关闭。
在一段时间后,Windows强制关闭未响应的应用程序,不过这可能导致数据丢失。

5 关闭用户会话:
关闭所有用户会话,释放用户相关资源。
用户配置和设置会被保存。

6停止服务:
Windows开始逐步停止系统服务。
大多数后台服务在其他用户进程之前被告知关闭。

7 卷影复制/存储快照:
如果启用,Windows会处理卷影复制,以确保磁盘的一致状态。
断开网络连接:

关闭所有网络连接,包括网络共享和远程存取。

8 写入系统日志:
Windows将关机事件记录到事件日志中,包括原因和时间。

9 关闭设备驱动程序:
按照与骚扰硬件的顺序,关闭设备驱动程序。
设备驱动程序完成所有未完成的I/O操作并释放硬件资源。

10 电源管理逻辑:
操作系统通过ACPI与系统固件交互,准备进入关机状态。
Windows指示固件关闭所有系统电源。

11 电源关闭:
在最底层,最后的电源信号被传递,计算机完全断电。

二 区分windows系统重启\关机

从《windows 关机重启流程》得知windows 消息无法区分重启\关机,只能通过系统user32 日志判断了

1 基于Topshelf 配置HostConfigurator


 hostConfig.EnableShutdown();
 hostConfig.EnableSessionChanged();

2 实现 ConfigService

 public void ConfigService(ServiceConfigurator<IService> serviceConfig)
 {
     serviceConfig.WhenShutdown(Shutdown);
     serviceConfig.WhenSessionChanged((service, session) =>
   {
     WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
     switch (session.ReasonCode)
     {
         case SessionChangeReasonCode.SessionLogoff:
             _shutdownRebootService.Watcher();
             break;
     }
 });

3 实现Shutdown

 private async void Shutdown(IService service, HostControl control)
 {
    Log.Info("=======>>系统即将关闭.....");
     var systemPowerCycle = _shutdownRebootService.GetSystemPowerCycle();
     ServiceCenters.Log.Info($"当前系统电源状态:{systemPowerCycle}");
     // 获取到重启、关机状态
 }

4 ShutdownRebootService 重启关机具体实现类

internal class ShutdownRebootService
{
    /// <summary>
    /// 监听重启关机系统事件
    /// </summary>
    public void Watcher()
    {
        Task.Run(() =>
        {
            try
            {
                var systemEventLog = new EventLog("System");
                EventLogEntry latestUser32Entry = null;
                var entries = systemEventLog.Entries;
                for (int i = entries.Count; i > 0; i--)
                {
                    var entry = entries[i - 1];
                    if (string.Equals(entry.Source, "USER32", StringComparison.OrdinalIgnoreCase) && entry.EventID == 1074)
                    {
                        latestUser32Entry = entry;
                        break;
                    }
                }
                if (latestUser32Entry != null)
                {
                    logger.Info($"命令来源:{latestUser32Entry.ReplacementStrings[0]}");
                    logger.Info($"原因:{latestUser32Entry.ReplacementStrings[2]}");
                    logger.Info($"原因代码:{latestUser32Entry.ReplacementStrings[3]}");
                    logger.Info($"关机类型:{latestUser32Entry.ReplacementStrings[4]}");
                    logger.Info($"记录时间:{latestUser32Entry.TimeGenerated}");
                    _state = latestUser32Entry.ReplacementStrings[4];
                }
                logger.Info($"完成主动查询系统(重启、开机)");
            }
            catch (Exception e)
            {
                logger.Error($"主动查询系统(重启、开机)异常:{e}");
            }
        });
    }

    /// <summary>
    /// 获取电源循环(包括关机和重新启动)
    /// </summary>
    /// <returns></returns>
    public SystemPowerCycle GetSystemPowerCycle()
    {    
        // 使用正则表达式检查状态字符串
        if (System.Text.RegularExpressions.Regex.IsMatch(_state, @"(?i)(重启|restart)"))
        {
            return SystemPowerCycle.Reboot;
        }

        if (System.Text.RegularExpressions.Regex.IsMatch(_state, @"(?i)(关闭电源|power\s+off)"))
        {
            return SystemPowerCycle.Shutdown;
        }
        return SystemPowerCycle.Unknown;
    }
    private string _state = string.Empty;
    private SystemPowerCycle _systemPowerCycle = SystemPowerCycle.Unknown;
}

posted on 2026-07-20 10:34  TanZhiWei  阅读(3)  评论(0)    收藏  举报