Определите, ожидается ли завершение работы.

Вопрос или проблема

Windows имеет команду shutdown /t, чтобы выключить или перезагрузить компьютер через определённую задержку. Ожидающее завершение работы можно отменить с помощью shutdown /a.

Но как я могу определить, и когда завершение работы в настоящее время ожидается или запланировано, не отменяя его?

Как я могу определить, ожидается ли завершение работы и когда, не отменяя его?

Я не думаю, что возможно определить когда произойдёт завершение работы.

Вы можете определить если завершение работы запланировано, используя следующий алгоритм:

  1. Выполните “тестовое” завершение работы с помощью shutdown /t xxx с большим значением времени.

    • Для Windows 7 или более поздних версий максимальное допустимое время было увеличено с 600 секунд до 315 360 000 секунд (10 лет)
  2. Если уже ожидается завершение работы, то shutdown /t xxx не выполнится с кодом ошибки 1190:

    Системное завершение работы уже было запланировано.(1190)

  3. Если вы не получили вышеуказанную ошибку, значит, ранее завершение работы не было запланировано, поэтому вам нужно отменить “тестовое” завершение работы с помощью shutdown /a.

Всё вышеупомянутое можно выполнить в пакетном файле:

@echo off
rem выполняем "тестовое" завершение работы с большим временем
shutdown /t 999999
rem если уже ожидается завершение работы, то %ERRORLEVEL% будет 1190
if %ERRORLEVEL% equ 1190 (
  echo Завершение работы в ожидании
  ) else (
  rem отменяем "тестовое" завершение работы
  shutdown /a
  echo Завершение работы не ожидается
  )

Примечание:

  • Я не тестировал вышеуказанный пакетный файл, так как не хочу выключать свой ПК в данный момент.

Дополнительное чтение

  • Индекс A-Z командной строки Windows CMD – Отличная справка по всем вопросам, связанным с командной строкой Windows.
  • Errorlevel – Почти все приложения и утилиты устанавливают код завершения, когда они завершаются/оканчиваются.
  • if – Условно выполнять команду.
  • shutdown – Выключить компьютер.

Несколько более сложный способ выяснить, запланировано ли завершение работы или нет – это отладить winlogon.exe и проверить статус флага ShutdownInProgress. Вам понадобятся инструменты отладки для Windows.

Я не пробовал это, но в этом сообщении блога MSDN объясняется, что происходит за кулисами, когда Windows выключается и как отлаживать winlogon.exe (который является “потоком пользовательского режима, который обрабатывает задачу входа и выхода интерактивных пользователей”). Команда отладчика для получения статуса флага, похоже, выглядит так:

dd winlogon!ShutdownInProgress l 1
01062b3c  00000000

Если вы знаете, как отлаживать процессы ядра в Windows, вы можете попробовать это. Этот руководство для начинающих по отладке с помощью CDB и NTSD может помочь.

    //
    // RestartOrShutdown.cs, Aad Slingerland, октябрь 2024.
    // install-package System.Diagnostics.EventLog
    // См. также:
    // https://morgantechspace.com/2013/08/convert-datetime-to-ticks-and-ticks-to.html
    // Ограничения:
    // Только английская локализация, но тексты "перезагрузка" и "выключить" могут быть изменены на другую локализацию.  
    //
    using System.Diagnostics;

    namespace RestartOrShutdown;

    internal class Program
    {
        static int Main(string[] args)
        {
            int rc = 0;
            int minutes = 1;
            try
            {
                if (args.Length > 0)
                {
                    minutes = int.Parse(args[0]);
                }
    #pragma warning disable CA1416 // Проверка совместимости платформы
               EventLog syslog = new("System");
               //
               DateTime _now = DateTime.Now;
               long minus = 10000000;           // одна секунда в тиках
               DateTime _past = _now.AddTicks(-(minus * 60 * minutes));
               //
               Debug.WriteLine(_now.Ticks);
               Debug.WriteLine(_past.Ticks);
               //
               var entries = syslog.Entries.Cast<EventLogEntry>()
                   .Where(x => x.TimeWritten.Ticks > _past.Ticks && x.EventID == 1074)
                   .ToList();
    #pragma warning restore CA1416 // Проверка совместимости платформы
               //
               foreach (EventLogEntry e in entries)
               {
                   Debug.WriteLine(e.TimeWritten.Ticks);
                   Debug.WriteLine(e.Message);
                   if (e.Message.Contains("перезагрузка"))
                   {
                       rc = 1;
                   }
                   else if (e.Message.Contains("выключить"))
                   {
                       rc = 2;
                   }
               }
           }
           catch (System.FormatException)
           {
               Usage();
               rc = 9;
           }
           Console.WriteLine($"Код возврата={rc}");
           return rc;
       }

       static void Usage()
       {
           Console.WriteLine(@"
           Использование: RestartOrShutdown [минуты]

           Запрашивает операционную систему, находится ли она в процессе перезагрузки или завершения работы.
           Код возврата 0 = ни то, ни другое.
           Код возврата 1 = осуществляется перезагрузка.
           Код возврата 2 = осуществляется завершение работы.
           Код возврата 9 = недопустимое значение аргумента. 
           Аргумент [минуты] по умолчанию равен 1 минуте.
           Аргумент [минуты] сообщает этой программе, как далеко следует заглянуть назад в журнал событий Windows 
           для записи с EventID 1074.");
       }
   }

Ответ или решение

Для определения того, запланировано ли завершение работы компьютера с операционной системой Windows, существует несколько подходов, которые не требуют прерывания самого процесса завершения. Рассмотрим их подробно.

Метод 1: Использование команды shutdown

Первый и наиболее простой способ — использовать команду shutdown с временной задержкой. Этот метод заключается в выполнении "тестового" завершения работы с помощью команды shutdown /t xxx, где значение xxx — это большое число, например, 999999 (примерно 10 лет).

  1. Выполнение тестовой команды:

    shutdown /t 999999

    Это создаст предстоящее завершение работы с задержкой на почти 10 лет.

  2. Проверка статуса завершения работы:

    • Если предстоящая остановка уже запланирована, команда завершения работы вернёт код ошибки 1190 (переводится как "Системное завершение работы уже запланировано.").
    • В противном случае, вы получите другой код, и это означает, что завершение работы не было запланировано.
  3. Отмена тестового завершения:
    В случае успешного выполнения первой команды необходимо отменить тестовое завершение с помощью:

    shutdown /a

Ниже представлен пример пакетного файла, который реализует описанный выше подход:

@echo off
rem Выполнение "тестового" завершения с большим временем
shutdown /t 999999
rem Проверка кода ошибки
if %ERRORLEVEL% equ 1190 (
    echo Завершение работы запланировано
) else (
    rem Отмена "тестового" завершения
    shutdown /a
    echo Завершение работы не запланировано
)

Примечание: Рекомендуется протестировать данный пакетный файл на тестовой машине, чтобы избежать нежелательных последствий.

Метод 2: Проверка системного журнала событий

Второй более надежный метод — это использование системного журнала событий Windows. Для этого можно воспользоваться языком программирования C# для чтения записей из журнала.

using System;
using System.Diagnostics;
using System.Linq;

namespace RestartOrShutdown
{
    internal class Program
    {
        static int Main(string[] args)
        {
            int rc = 0;
            int minutes = 1;
            try
            {
                if (args.Length > 0)
                {
                    minutes = int.Parse(args[0]);
                }

                EventLog syslog = new EventLog("System");
                DateTime _now = DateTime.Now;
                DateTime _past = _now.AddMinutes(-minutes);
                var entries = syslog.Entries.Cast<EventLogEntry>()
                    .Where(x => x.TimeWritten > _past && x.EventID == 1074)
                    .ToList();

                foreach (EventLogEntry e in entries)
                {
                    if (e.Message.Contains("restart"))
                    {
                        rc = 1;
                    }
                    else if (e.Message.Contains("power off"))
                    {
                        rc = 2;
                    }
                }
            }
            catch (FormatException)
            {
                Usage();
                rc = 9;
            }
            Console.WriteLine($"Код возврата={rc}");
            return rc;
        }

        static void Usage()
        {
            Console.WriteLine(@"
            Использование: RestartOrShutdown [minutes]

            Проверяет, находится ли операционная система в процессе перезагрузки или завершения работы.
            Код возврата 0 = нет ни перезагрузки, ни завершения работы.
            Код возврата 1 = перезагрузка в процессе.
            Код возврата 2 = завершение работы в процессе.
            Код возврата 9 = недопустимое значение аргумента.");
        }
    }
}

Этот код запрашивает записи в системном журнале и ищет события с идентификатором 1074, который относится к событиям завершения работы или перезагрузки. Возврат кода позволяет определить текущее состояние системы.

Заключение

Вышеописанные методы позволяют определить, запланировано ли завершение работы компьютера на операционной системе Windows, без его остановки. Метод с использованием команды shutdown прост и легок в исполнении, но может вызвать временное состояние завершения, которое будет отменено. Проверка системного журнала с использованием C# — это более надежный и устойчивый способ, но требует навыков программирования.

Изучение этих методов может помочь системным администраторам и пользователям в управлении состоянием своих компьютерных систем более эффективно.

Оцените материал
Добавить комментарий

Капча загружается...