Pozostały czas przed planowanym zamknięciem?

8

Czy jest jakiś sposób, aby sprawdzić, ile czasu pozostało do zaplanowanego wyłączenia w systemie Windows 7?

Przez zaplanowane zamknięcie rozumiem wyłączenie / ponowne uruchomienie zaplanowane przy użyciu shutdown.exeaplikacji wiersza poleceń , np .:

shutdown /t 600 /s

Pojawi się okno komunikatu z informacją, że do zamknięcia jest 10 minut, a rzeczywisty czas zamknięcia systemu.

Dowolny czas dłuższy niż 600sekundy używa wiadomości balonowej.

Niejasno pamiętam XP zapewniający monitor postępu GUI z odliczaniem.

Jak działały? Pozostały czas wyłączenia lub zaplanowany czas musi być gdzieś zapisany, jak mogę uzyskać do niego dostęp?

Moje preferencje to metoda z linii poleceń (tj. Bez GUI). Co ważniejsze, czy można to osiągnąć w systemie Windows, tj. Bez programów innych firm?

Jeśli nie jest to możliwe w przypadku standardowych narzędzi systemu Windows (i tu graniczę z terytorium Przepełnienia stosu), czy istnieje funkcja Windows API (lub .NET, która może być nawet używana w programie PowerShell!)? Albo byłby lepszy niż jakiś losowy program strony trzeciej.

Kok
źródło
superuser.com/a/317062/117590 wyglądało obiecująco, jednak preferowane / wymagane jest, aby polecenie zamykania nie było modyfikowane, tak jak /c <time>robi to dodawanie komentarza ( ).
Bob
Myślę, że plik wsadowy nie byłby trudny do napisania. Pytaj o czas, a co około 5 minut może odpowiadać czasem, IE „pozostało 10 minut” .. a kiedy osiągnie 1, odliczaj sekund czy coś.
cutrightjm
Nie potrzebuję odliczania, potrzebuję metody, aby uzyskać czas pozostały w <tym> momencie. Polecenie zamknięcia jest wywoływane przez program zewnętrzny.
Bob

Odpowiedzi:

5

Pytanie było interesujące, więc napisałem partię, która może zrobić dla ciebie robotę.

Zasadniczo jest to odliczanie do zera, nie shutdownpodałem tego polecenia, ale zostawiłem go jako zadanie domowe. Obliczenia nie są dokładne, nie obchodzi ich lata przestępne, długość miesiąca, ... dotyczy to głównie czytelności, ponieważ chciałem ułatwić naukę.

Obecnie dwa pliki wykonują zadanie razem, jeden uruchamia stoper, a drugi, gdy jest wywoływany, mówi, ile czasu upłynęło od uruchomienia timera. Te dwa pliki można dość łatwo połączyć w jeden skrypt cmd, dzięki czemu niektóre linie mogą być ponownie używane ( jak zdefiniowane metody ).

Dobra, spójrzmy na skrypty,

Oto 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

Zgodnie z FOR /F "skip=1 ...:
1. Zapytaj wmico aktualną godzinę i datę.
2. Pomiń pierwszy wiersz wyniku, którym są nagłówki, o skip=1
3. Odczytaj wartości, używając tokens=1-6znaczenia %%a-%%foddzielonego przez SpaceorTAB.
4. Wartości sklepu do zmiennych %DateY%, ... %TimeH%, %TimeM%...

Następnie na początku linii SET /A EPOCH=...używamy wyrażenia, które oblicza upływające sekundy1.1.1970 ( jest to prosty przybliżony, a nie rzeczywisty czas uniksowy. Zobacz Google, jeśli potrzebujesz dokładności ).

Następnie w ostatniej linii ECHO %EPOCH% > ...zapisuje obliczony czas do pliku o nazwie „ Timer.start.state”.

A tutaj 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

Tutaj przepływ kodu nie jest liniowy od góry do dołu. Najpierw oznaczamy GOTO CHECKFILEetykietę, aby komendy wykonania naprawdę zaczynały się od linii, która mówi :CHECKFILE. Wiele rzeczy tutaj jest tak samo jak z, StartTimer.cmdwięc wyjaśniam tylko nowe lub zmienione linie.

Najpierw sprawdzamy, czy plik stanu Timer.start.stateistnieje, a jeśli nie, to zakończ komunikat wit. Jeśli timer się uruchomił i pliki istnieją, kontynuujemy i wykonujemy matematykę:
1. Przejdź do :TIMEOUTmiejsca, w którym wyprowadzamy upływające sekundy. Możesz wybrać lepszą etykietę do tego ...
2. SET /P %Timer% ... czyta czas rozpoczęcia z pliku i przypisuje wartość do %Timer%zmiennej.
3. SET /A Elapsed ... oblicza sekundy między czasem rozpoczęcia a teraz.
4. ECHO "Seconds ... generuje echo obliczonej wartości (sekundy od uruchomienia timera.

Jak uzyskać pozostały czas:

Możesz odjąć %Elapsed%od %MaxTime%:

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

OK, wystarczająco wyjaśnione. Oto pełny skrypt Timer.cmd:

W tym momencie zapomniałem o wszystkim, co już powiedziano. Ten plik wsadowy działa tutaj samodzielnie, więc nie ma osobnego StartTimer.cmdlub GetTimerValue.cmdtylko to Timer.cmd. Zasadniczo jest nadal taki sam, ale przepływ kodu jest inny, a użycie jest również zupełnie inne. Nie powoduje to jednak zapisania stanu do pliku, więc nie można już uzyskać wartości timera po wylogowaniu / ponownym uruchomieniu, jeśli potrzebujesz tego przykładu użycia powyżej, aby zapisać / odczytać stan do / z pliku.

Użycie / pomoc dla Timer.cmdjest drukowane po uruchomieniu bez argumentów. Nie przetestowałem tego w pełni i mogą występować literówki itp. Argumenty nie są niezawodne.

@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

Zintegruj z shutdowndowolnym innym poleceniem:

Plik poweroff.cmd:

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

Zastosowanie: poweroff <wait_seconds>do rozpoczęcia czasowego wyłączenia i Timer getdo upływu czasu / pozostałego czasu.

Sampo Sarrala - codidact.org
źródło
Klaskam za wysiłek. Właśnie zdałem sobie sprawę, jak źle sformułowane było to pytanie, ale nadal udało ci się na nie odpowiedzieć. Tylko za to dostajesz opinię. Niestety nie działa to z dowolnymi poleceniami zamykania, tzn. StartTimer.cmdMusi być jawnie wywołane. Napisałem mały program, aby rozwiązać mój problem, który opublikuję po powrocie na komputer.
Bob
Ok, zaakceptuję to. Skończyło się na napisaniu programu o nazwie C # shutdown.exe, który wywołał shutdown_original.exe. Sprawdziłby /tflagę i gdyby istniał, stworzył plik z zapisanymi godzinami rozpoczęcia i zakończenia. Podczas pobierania czasów ( /retrieveflaga) sprawdzałby dziennik zdarzeń, aby sprawdzić, czy uruchomienie lub przerwanie zostało wykonane od czasu uruchomienia timera. Nie jestem pewien, jak poradziłby sobie z hibernacjami. Nie zamierzam publikować kodu ani programu: to jest błędny bałagan. Aby program działał, musiałem dużo popsuć ustawieniami zabezpieczeń, których nie chcę promować.
Bob
Podstawową koncepcją było przechwytywanie shutdown.exepołączenia i rejestrowanie czasu do pliku, co właśnie zrobiłeś i dlaczego to akceptuję.
Bob
2
@Bob - Zamierzałeś pisać o swoim programie, kiedy wrócisz? Linki do exe / kodu źródłowego?
Alex S