Tempo restante antes do encerramento programado?

8

Existe alguma maneira de ver quanto tempo resta antes de um desligamento programado no Windows 7?

Por desligamento agendado, quero dizer um desligamento (ou reinicialização) agendado usando o shutdown.exeaplicativo de linha de comando , por exemplo:

shutdown /t 600 /s

Isso abriria uma caixa de mensagem informando que há 10 minutos até o desligamento e a hora real do desligamento do sistema.

Qualquer tempo superior a 600segundos usa uma mensagem de balão.

Lembro-me vagamente do XP fornecendo um monitor de progresso da GUI, com uma contagem regressiva.

Como eles funcionaram? O tempo de desligamento restante ou o horário programado devem ser armazenados em algum lugar. Como posso acessá-lo?

Minha preferência é algum método através da linha de comando (ou seja, não GUI). Mais importante, isso é possível no Windows, ou seja, sem nenhum programa de terceiros?

Se isso não for possível com os utilitários padrão do Windows (e eu estou fazendo fronteira com o território Stack Overflow aqui), existe uma função de API do Windows (ou .NET, que pode até ser usada no PowerShell!)? Qualquer um deles seria preferido em relação a algum programa aleatório de terceiros.

Prumo
fonte
superuser.com/a/317062/117590 parecia promissor, no entanto, é preferível / necessário que o comando shutdown não seja modificado como a adição de um comentário ( /c <time>).
19412 Bob
Eu acho que um arquivo em lote não seria difícil de escrever. Solicite o tempo e, a cada 5 minutos ou mais, ele poderá responder com um tempo, ou seja, "10 minutos restantes". Quando chegar a 1, faça a contagem regressiva segundos ou algo assim.
Cutrightjm
Não preciso de uma contagem regressiva, preciso de algum método para obter o tempo restante neste momento. O comando shutdown está sendo chamado por um programa externo.
24512 Bob

Respostas:

5

A pergunta foi interessante, então eu escrevi um lote que pode fazer um trabalho para você.

Basicamente, é temporizador de contagem regressiva, eu não incluí shutdowncomando, mas o deixei como lição de casa. Os cálculos não são precisos, isso não se importa com anos bissextos, duração do mês, ... isso é principalmente para facilitar a leitura, pois eu queria facilitar a aprendizagem.

Atualmente, existem dois arquivos trabalhando juntos, um inicia o cronômetro e outro, quando chamado, informa quanto tempo decorreu do início do cronômetro. Esses dois arquivos podem ser facilmente combinados em um script de cmd, dessa forma você também pode reutilizar algumas linhas ( como métodos definidos ).

Ok, vamos dar uma olhada nos scripts,

Aqui está 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

De acordo com FOR /F "skip=1 ...:
1. Peça wmica hora e a data atuais.
2. Pule a primeira linha de saída, que é o cabeçalho, por skip=1
3. Leia os valores usando o tokens=1-6significado %%a-%%fseparado por SpaceorTAB.
4. Armazenar valores para as variáveis %DateY%, ... %TimeH%, %TimeM%...

Depois disso, no início da linha SET /A EPOCH=..., usamos uma expressão que calcula os segundos decorridos1.1.1970 ( este é o tempo aproximado simples, não o unix real. Consulte o Google se precisar ).

Então, na última linha, ECHO %EPOCH% > ...escreve o tempo calculado no arquivo chamado " Timer.start.state".

E aqui 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

Aqui o fluxo de código não é linear de cima para baixo. Primeiro, GOTO CHECKFILErotulamos para que os comandos de execução realmente iniciem na linha que diz :CHECKFILE. Muitas coisas aqui são exatamente as mesmas, StartTimer.cmdentão só explico linhas novas ou alteradas.

Primeiro, verificamos se o arquivo de estado Timer.start.stateexiste; caso contrário, encerramos a mensagem de humor. Se o timer iniciar e os arquivos existirem, continuamos e fazemos algumas contas:
1. Vá para o local :TIMEOUTonde produzimos os segundos decorridos. Você pode escolher uma etiqueta melhor para isso ...
2. SET /P %Timer% ... lê a hora de início do arquivo e atribui valor à %Timer%variável.
3. SET /A Elapsed ... calcula segundos entre a hora de início e agora.
4. ECHO "Seconds ... reproduz o valor calculado (segundos desde a inicialização do timer.

Como obter tempo restante:

Você pode subtrair %Elapsed%de %MaxTime%:

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

OK, explicou o suficiente. Aqui está o script completo Timer.cmd:

Neste ponto, esqueci tudo o que já foi dito. Esse arquivo em lotes aqui está funcionando por si próprio, portanto não há separadores StartTimer.cmdou GetTimerValue.cmdapenas isso Timer.cmd. Basicamente, ainda é o mesmo, mas o fluxo de código é diferente e o uso também é completamente diferente. No entanto, isso não salva o estado no arquivo, assim você não pode mais obter o valor do timer após o logoff / reinicialização, se você precisar deste exemplo de uso acima para salvar / ler o estado no / do arquivo.

O uso / ajuda para Timer.cmdé impresso quando executado sem argumentos. Eu não testei completamente isso e pode haver alguns erros de digitação etc., os argumentos não são verificados à prova de falhas.

@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

Integre com shutdownou qualquer outro comando:

Arquivo poweroff.cmd:

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

Uso: poweroff <wait_seconds>para iniciar o desligamento programado e Timer getobter o tempo decorrido / restante.

Sampo Sarrala - codidact.org
fonte
Aplaudo o esforço. Acabei de perceber o quanto a pergunta estava mal formulada, mas você ainda conseguiu responder. Só por isso você recebe um voto positivo. Infelizmente, isso não funciona com comandos de desligamento arbitrários, ou seja, StartTimer.cmddeve ser chamado explicitamente. Escrevi um pequeno programa para resolver meu problema, que publicarei quando voltar ao meu computador.
Bob
Ok, eu vou aceitar isso. Acabei escrevendo um programa em C # chamado shutdown.exe, que chamou shutdown_original.exe. Ele verificaria o /tsinalizador e, se existisse, criaria um arquivo com os horários de início e término salvos. Nos tempos de recuperação ( /retrievesinalizador), ele verifica o log de eventos para ver se uma inicialização ou abortamento foi realizada desde o início do cronômetro. Não tenho certeza de como ele lidaria com hibernações. Não vou postar o código ou programa: é uma bagunça de buggy. E para que o programa funcionasse, tive que mexer bastante nas configurações de segurança, que não quero promover.
22412 Bob
O conceito básico foi interceptar a shutdown.exechamada e registrar os horários em um arquivo, que foi o que você fez e por que estou aceitando isso.
22412 Bob
2
@ Bob - Você ia postar sobre seu programa quando voltasse? Links para exe / código fonte?
Alex S