Время осталось до запланированного выключения?

8

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

Под запланированным отключением я подразумеваю завершение работы (или перезапуск), запланированное с помощью shutdown.exeприложения командной строки , например:

shutdown /t 600 /s

Появится окно с сообщением о том, что до выключения осталось 10 минут, а также фактическое время выключения системы.

В любое время, большее 600секунды, вместо этого используется всплывающее сообщение.

Я смутно припоминаю, что XP предоставляет монитор прогресса с графическим интерфейсом и обратным отсчетом.

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

Я предпочитаю какой-то метод через командную строку (т.е. не-GUI). Что еще более важно, это выполнимо в Windows, то есть без каких-либо сторонних программ?

Если это невозможно осуществить с помощью стандартных утилит Windows (и я граничу с территорией переполнения стека), существует ли функция Windows API (или .NET, которую можно даже использовать в PowerShell!)? Любой из них будет предпочтительнее какой-либо случайной сторонней программы.

боб
источник
superuser.com/a/317062/117590 выглядел многообещающе, однако желательно / необходимо, чтобы команда shutdown не изменялась, как это /c <time>делает добавление комментария ( ).
Боб
Я думаю, что пакетный файл не составит труда написать .. Запрашивать время, и каждые 5 минут или около того он может отвечать временем, т.е. "10 минут осталось" ... а когда он достигает 1, отсчитывать секунды или что-то.
cutrightjm
Мне не нужен обратный отсчет, мне нужен какой-то метод, чтобы получить время, оставшееся в данный момент. Команда выключения вызывается внешней программой.
Боб

Ответы:

5

Вопрос был интересным, поэтому я написал пакет, который может сделать работу за вас.

В основном это таймер обратного отсчета, я не включил shutdownкоманду в это, но оставил это как домашнее задание. Расчеты не точные, это не заботится о високосных годах, длине месяца, ... это главным образом для удобства чтения, так как я хотел, чтобы его было легко выучить.

В настоящее время два файла работают вместе: один запускает таймер, а другой, при вызове, сообщает, сколько времени прошло с момента запуска таймера. Эти два файла можно довольно легко объединить в один сценарий cmd, таким образом, вы можете сделать некоторые строки многократно используемыми ( например, определенные методы ).

Хорошо, давайте посмотрим на сценарии,

Вот StartTimer.cmd:

@ECHO OFF
FOR /F "skip=1 tokens=1-6" %%a IN ('wmic Path Win32_Localtime GET year^,month^,day^,hour^,minute^,second /format:TABLE ^| findstr /r "."') DO (
  SET DateD=%%a
  SET TimeH=%%b
  SET TimeM=%%c
  SET DateM=%%d
  SET TimeS=%%e
  SET DateY=%%f
)
SET /A EPOCH=((%DateY%-1970)*365*24*60*60)+(%DateM%*30*24*60*60)+(%DateD%*24*60*60)+(%TimeH%*60*60)+(%TimeM%*60)+%TimeS%
ECHO %EPOCH% > Timer.start.state

В строке, начинающейся с FOR /F "skip=1 ...:
1. Запросите wmicтекущее время и дату.
2. Пропустите первую строку вывода, которая является заголовками, на skip=1
3. Считайте значения, используя tokens=1-6значения, %%a-%%fразделенные SpaceorTAB.
4. Значение будет хранить в переменных %DateY%, ... %TimeH%, %TimeM%...

После этого в начале строки SET /A EPOCH=...мы используем выражение, которое вычисляет истекшие секунды1.1.1970 ( это просто приблизительное, а не реальное время Unix. Посмотрите Google, если вам нужно точно ).

Затем в последней строке ECHO %EPOCH% > ...записывается рассчитанное время в файл с именем " Timer.start.state".

И здесь GetTimerValue.cmd:

@ECHO OFF

GOTO CHECKFILE

:TIMEOUT
FOR /F "skip=1 tokens=1-6" %%a IN ('wmic Path Win32_Localtime GET year^,month^,day^,hour^,minute^,second /format:TABLE ^| findstr /r "."') DO (
    SET DateD=%%a
    SET TimeH=%%b
    SET TimeM=%%c
    SET DateM=%%d
    SET TimeS=%%e
    SET DateY=%%f
)
SET /P Timer=<"Timer.start.state"
SET /A EPOCH=((%DateY%-1970)*365*24*60*60)+(%DateM%*30*24*60*60)+(%DateD%*24*60*60)+(%TimeH%*60*60)+(%TimeM%*60)+%TimeS%
SET /A Elapsed=%EPOCH%-%Timer%
ECHO "Seconds since timer started: %Elapsed%"
GOTO EOF

:CHECKFILE
IF EXIST "Timer.start.state" (
  GOTO TIMEOUT
) ELSE (
  ECHO "Timer not started. Start timer by running Timer.cmd"
)

:EOF

Здесь поток кода не является линейным сверху вниз. Сначала мы GOTO CHECKFILEпомечаем так, чтобы команды выполнения действительно начинались со строки с надписью :CHECKFILE. Многие вещи здесь такие же, как и с, StartTimer.cmdпоэтому я объясняю только новые или измененные строки.

Сначала мы проверяем, существует ли файл состояния Timer.start.state, если нет, затем завершаем работу с сообщением. Если таймер запущен и файлы существуют, мы продолжаем и делаем некоторую математику:
1. Переходим туда, :TIMEOUTгде мы выводим истекшие секунды. Вы можете выбрать лучшую метку для этого ...
2. SET /P %Timer% ... читает время запуска из файла и присваивает значение %Timer%переменной.
3. SET /A Elapsed ... рассчитывает секунды между временем запуска и сейчас.
4. ECHO "Seconds ... выводит рассчитанное значение (в секундах с момента запуска таймера).

Как получить оставшееся время:

Вы можете вычесть %Elapsed%из %MaxTime%:

@ECHO OFF
GetTimerValue
SET /A TimeLeft=%MaxTime%-%Elapsed%
ECHO "You have %TimeLeft% seconds remaining"

Хорошо, объяснил достаточно. Вот полный сценарий Timer.cmd:

На данный момент забыл, все уже сказано. Этот пакетный файл здесь работает сам по себе, поэтому нет отдельного StartTimer.cmdили GetTimerValue.cmdтолько этого Timer.cmd. В основном это все то же самое, но поток кода отличается, и использование также совершенно другое. Это, однако, не сохраняет состояние в файл, поэтому вы больше не можете получить значение таймера после выхода из системы / перезагрузки, если вам нужен приведенный выше пример использования для сохранения / чтения состояния в / из файла.

Использование / справка Timer.cmdвыводится при запуске без аргументов. Я не полностью проверил это, и могут быть некоторые опечатки и т. Д., Аргументы не проверены на защиту от ошибок.

@ECHO OFF

GOTO TimerUser%1

:: ===================================
:: Operation is start, (re)start timer
:: ===================================
:TimerUserstart
ECHO %2 | FINDSTR /R "^[1-9]"
IF %ERRORLEVEL%==0 (
  SET Timer.max=%2
  GOTO TimerStart
) ELSE (
  ECHO.
  ECHO   !! ERROR !!
  ECHO   You must specify maximum value.
  ECHO   ===============================
  GOTO TimerUser
)

:: =============================================
:: Operation is get, get values if timer running
:: =============================================
:TimerUserget
IF DEFINED Timer.start.state (
  GOTO TIMEOUT
) ELSE (
  ECHO.
  ECHO   !! ERROR !!
  ECHO   Timer is not started, start timer first.
  ECHO   ========================================
  GOTO TimerUser
)

:: ============
:: Usage / Help
:: ============
:TimerUser
  ECHO.
  ECHO Timer.cmd Usage: Timer.cmd operation [options]
  ECHO.
  ECHO - Operations
  ECHO   start    Start new timer, n must be specified.
  ECHO   get      Get current value of started timer.
  ECHO.
  ECHO - Options:
  ECHO   n        Max value in seconds, used to calculate remaining time.
  ECHO.
GOTO EOF

:: =============================
:: Update %Timer.epoch% variable
:: =============================
:TimerUpdateEpoch
FOR /F "skip=1 tokens=1-6" %%a IN ('wmic Path Win32_Localtime GET year^,month^,day^,hour^,minute^,second /format:TABLE ^| findstr /r "."') DO (
    SET DateD=%%a
    SET TimeH=%%b
    SET TimeM=%%c
    SET DateM=%%d
    SET TimeS=%%e
    SET DateY=%%f
)
SET /A Timer.epoch=((%DateY%-1970)*365*24*60*60)+(%DateM%*30*24*60*60)+(%DateD%*24*60*60)+(%TimeH%*60*60)+(%TimeM%*60)+%TimeS%
GOTO %Timer.Callback%

:: ===========================================
:: Start new timer destoying/resetting old one
:: ===========================================
:TimerStart
SET Timer.Callback=TimerStartC1
GOTO TimerUpdateEpoch
:TimerStartC1
SET Timer.start.state=%Timer.epoch%
GOTO EOF

:: =============================
:: Echo out current timer values
:: =============================
:TIMEOUT
SET Timer.Callback=TimerEchoJ1
GOTO TimerUpdateEpoch
:TimerEchoJ1
SET /A Timer.elapsed=%Timer.epoch%-%Timer.start.state%
SET /A Timer.remaining=%Timer.max%-%Timer.elapsed%
ECHO "Seconds since timer started: %Timer.elapsed% Time remaining %Timer.remaining%"
GOTO EOF

:EOF

Интегрировать с shutdownили любой другой командой:

Файл poweroff.cmd:

@ECHO OFF
Timer start %1
shutdown -t %1 -s

Использование: poweroff <wait_seconds>для запуска по времени и Timer getдля определения истекшего / оставшегося времени.

Сампо Саррала - codidact.org
источник
Я приветствую вас за усилия. Я только что понял, насколько плохо сформулирован вопрос, но вам все же удалось ответить на него. Просто за это вы получите голос. К сожалению, это не работает с произвольными командами выключения, то есть StartTimer.cmdдолжно вызываться явно. Я написал небольшую программу для решения своей проблемы, которую я опубликую, когда вернусь к своему компьютеру.
Боб
Хорошо, я приму это. Я закончил тем, что написал программу на C #, которая получила shutdown.exeназвание shutdown_original.exe. Он проверит наличие /tфлага и, если он существует, создаст файл с сохраненным временем начала и окончания. При извлечении времени ( /retrieveфлаг) он будет проверять журнал событий, чтобы увидеть, был ли выполнен запуск или отмена с момента запуска таймера. Я не уверен, как бы он справился с зимней спячкой. Я не собираюсь публиковать код или программу: это гадкий беспорядок. И чтобы заставить программу работать, мне пришлось много возиться с настройками безопасности, которые я не хочу рекламировать.
Боб
Основная концепция заключалась в том, чтобы перехватить shutdown.exeвызов и записать время в файл, что вы и сделали, и почему я это принимаю.
Боб
2
@Bob - Ты собирался написать о своей программе, когда вернулся? Ссылки на exe / исходный код?
Алекс С