KubosKube

Shutdown Later v2.0.1

Aug 24th, 2025
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Batch 15.53 KB | Software | 0 0
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. goto :initialize
  4.  
  5.  
  6.  
  7.  
  8. :changelog
  9.  
  10. call :operation_tracker "Changelog"
  11.  
  12. cls
  13.  
  14. echo.
  15. call :splash
  16. echo.
  17. echo  v2.0.1
  18. echo   + Added description to splash text for what the script does
  19. echo   + Added functionality for negative numbers in offset time
  20. echo   + Changed logic for selecting preset input in code
  21. echo   + Fixed a bug regarding octal numbers
  22. echo   + Fixed a bug regarding wait times longer than 99,999 seconds
  23. echo  v2.0.0
  24. echo   + Re-made UI
  25. echo   + Added ability to shut down at a set time
  26. echo   + Added splash text to every screen
  27. echo   + Added a help menu
  28. echo   + Added a changelog
  29. echo.
  30. echo  v1.0
  31. echo   + Added the ability to shut down after a delay
  32. echo.
  33.  
  34. pause
  35.  
  36. goto :start
  37.  
  38.  
  39.  
  40.  
  41. :initialize
  42.  
  43. call :operation_tracker "Initialize"
  44.  
  45. set "title=Shutdown Later"
  46. set "version=2.0.1"
  47.  
  48. set "splash1= %title% v%version%"
  49. set "splash2=  An overly-complicated script from KubosKube to you, free of charge."
  50. set "splash3=  Shuts down your computer at a later point in time."
  51.  
  52. title %splash1%
  53.  
  54. set "preset1= 1m"
  55. set "preset2= 2m"
  56. set "preset3= 3m"
  57. set "preset4= 5m"
  58. set "preset5=10m"
  59. set "preset6=20m"
  60. set "preset7=30m"
  61. set "preset8= 1h"
  62. set "preset9= 2h"
  63. set "preset0= 3h"
  64.  
  65. goto :start
  66.  
  67.  
  68.  
  69. rem Splash Text
  70. :splash
  71.  
  72. echo %splash1%
  73. echo %splash2%
  74. echo %splash3%
  75.  
  76. goto :eof
  77.  
  78.  
  79.  
  80.  
  81. :start
  82.  
  83. call :operation_tracker "Start"
  84.  
  85. cls
  86. echo.
  87. call :splash
  88. echo.
  89. echo  Choose a preset time offset, or provide your own timestamp and offset.
  90. echo   1 ............ %preset1%
  91. echo   2 ............ %preset2%
  92. echo   3 ............ %preset3%
  93. echo   4 ............ %preset4%
  94. echo   5 ............ %preset5%
  95. echo   6 ............ %preset6%
  96. echo   7 ............ %preset7%
  97. echo   8 ............ %preset8%
  98. echo   9 ............ %preset9%
  99. echo   0 ............ %preset0%
  100. echo.
  101. echo   +01:30:00 .... shutdown in 1h30m
  102. echo   01:30:00 ..... shutdown at 1:30am
  103. echo.
  104. echo   help ......... Show examples of how to use non-preset times.
  105. echo   changelog .... Show changes from previous versions to current version.
  106. echo.
  107. echo.
  108.  
  109. echo  Enter a number preset or a custom input...
  110. set /p "user_input="
  111.  
  112. ::set "user_input=08.00+30.00"
  113.  
  114. if not defined user_input goto :start
  115.  
  116. if %user_input% == changelog goto :changelog
  117. if %user_input% == help goto :help
  118.  
  119. call :convertTime %time%
  120. set /a "time_now=%convertTime_output% + 0"
  121.  
  122. rem call :debug "time_now=%time_now%"
  123.  
  124. rem Early jump to Custom Input
  125. if not %user_input% == %user_input:+=% goto :custom
  126.  
  127. rem Check for Preset input
  128. set "loop=9"
  129. :inputLoop
  130. if "%user_input%" == "%loop%" goto :presets
  131. set /a "loop-=1"
  132. if %loop% GTR -1 goto inputLoop
  133.  
  134. rem No preset given, go to Custom Input
  135. goto :custom
  136.  
  137.  
  138.  
  139.  
  140. :presets
  141.  
  142. call :operation_tracker "Presets"
  143.  
  144. rem call :debug "Preset input provided"
  145.  
  146. if %user_input% EQU 1 set /a "offset_delay_seconds=1*60"
  147. if %user_input% EQU 2 set /a "offset_delay_seconds=2*60"
  148. if %user_input% EQU 3 set /a "offset_delay_seconds=3*60"
  149. if %user_input% EQU 4 set /a "offset_delay_seconds=5*60"
  150. if %user_input% EQU 5 set /a "offset_delay_seconds=10*60"
  151. if %user_input% EQU 6 set /a "offset_delay_seconds=20*60"
  152. if %user_input% EQU 7 set /a "offset_delay_seconds=30*60"
  153. if %user_input% EQU 8 set /a "offset_delay_seconds=1*60*60"
  154. if %user_input% EQU 9 set /a "offset_delay_seconds=2*60*60"
  155. if %user_input% EQU 0 set /a "offset_delay_seconds=3*60*60"
  156.  
  157. goto :execute
  158.  
  159.  
  160.  
  161.  
  162. :custom
  163.  
  164. call :operation_tracker "Custom"
  165.  
  166. rem call :debug "Custom input provided"
  167.  
  168. set "time_set="
  169. set "time_offset="
  170.  
  171. if %user_input% == %user_input:+=% (
  172.     set "mode=set"
  173.     set "time_set=%user_input%"
  174. ) else (
  175.     set "mode=offset"
  176.     set "time_offset=%user_input:*+=%"
  177.     call set "time_set=%%user_input:+!time_offset!=%%"
  178. )
  179.  
  180. rem call :debug "user_input = %user_input%   time_set = %time_set%   time_offset = %time_offset%"
  181.  
  182. if defined time_set (
  183.  
  184.     call :operation_tracker "Time_Set Calculations"
  185.     rem call :debug "Entering time_set calculations"
  186.    
  187.     call :tokenize %time_set%
  188.    
  189.     for /f "tokens=1-3" %%a in ("!tokenize_output!") do (
  190.         set /a "time_set_hours=%%a + 0"
  191.         set /a "time_set_minutes=%%b + 0"
  192.         set /a "time_set_seconds=%%c + 0"
  193.     )
  194.     set "time_set_hours_00=00!time_set_hours!"
  195.     set "time_set_minutes_00=00!time_set_minutes!"
  196.     set "time_set_seconds_00=00!time_set_seconds!"
  197.  
  198.     set "time_set_full=!time_set_hours!.!time_set_minutes!.!time_set_seconds!"
  199.     set "time_set_full_00=!time_set_hours_00:~-2!:!time_set_minutes_00:~-2!:!time_set_seconds_00:~-2!"
  200.  
  201.     rem call :debug "Time Stamp = !time_set_full!"
  202.    
  203.     call :convertTime !time_set_full!
  204.     set /a "time_then=!convertTime_output! + 0"
  205.  
  206.     set /a "set_delay_seconds=(!time_then!-!time_now!) + 0"
  207.    
  208.     rem call :debug "time_now = !time_now!   time_then = !time_then!   set_delay_seconds = !set_delay_seconds!"
  209.  
  210.     if !set_delay_seconds! LSS 0 (
  211.         set /a "set_delay_seconds= !set_delay_seconds! + (1*24*60*60)"
  212.        
  213.         rem call :debug "Corrected set_delay_seconds = !set_delay_seconds!"
  214.     )
  215. ) else ( set "set_delay_seconds=0" )
  216.  
  217. if defined time_offset (
  218.  
  219.     call :operation_tracker "Time_Offset Calculations"
  220.     rem call :debug "Entering timestamp calculations"
  221.    
  222.     call :tokenize +%time_offset%
  223.    
  224.     for /f "tokens=1-4" %%a in ("!tokenize_output!") do (
  225.         set /a "time_offset_days=%%d + 0"
  226.         set /a "time_offset_hours=%%c + 0"
  227.         set /a "time_offset_minutes=%%b + 0"
  228.         set /a "time_offset_seconds=%%a + 0"
  229.     )
  230.  
  231.     set offset_nominal=!time_offset_days! days, !time_offset_hours! hours, !time_offset_minutes! minutes, !time_offset_seconds! seconds
  232.  
  233.     rem call :debug "Offset = !offset_nominal!"
  234.  
  235.     rem call :debug "about to run the command: set /a offset_delay_seconds=((!time_offset_days! * 24 * 60 * 60) + (!time_offset_hours! * 60 * 60) + (!time_offset_minutes! * 60) + !time_offset_seconds!)"
  236.     set /a "offset_delay_seconds=((!time_offset_days! * 24 * 60 * 60) + (!time_offset_hours! * 60 * 60) + (!time_offset_minutes! * 60) + !time_offset_seconds!)"
  237.  
  238.     rem call :debug "offset_delay_seconds = !offset_delay_seconds!"
  239. ) else ( set "delay_offset=0" )
  240.  
  241. rem call :debug "adding set_delay_seconds %set_delay_seconds% with %offset_delay_seconds% to get total wait time %total_wait_seconds%"
  242.  
  243. goto :execute
  244.  
  245. call :error "Oops, something seems to have gone catestrophically and horrendously insanely wrong. Try again?"
  246.  
  247. rem Failsafe
  248. goto :eof
  249.  
  250.  
  251.  
  252.  
  253. :tokenize
  254.  
  255. call :operation_tracker "Tokenize"
  256.  
  257. set "tokenize_input=%1"
  258.  
  259. if not "%tokenize_input%" == "%tokenize_input:+=%" ( set "token_type=offset" ) else ( set "token_type=set" )
  260.  
  261. for /f "tokens=1-4 delims=:.,+" %%a in ("%tokenize_input%") do (
  262.     if not "%%a" == "" ( call :strip_lead_zeros %%a & set "token_a=!strip_lead_zeros_output!" )
  263.     if not "%%b" == "" ( call :strip_lead_zeros %%b & set "token_b=!strip_lead_zeros_output!" )
  264.     if not "%%c" == "" ( call :strip_lead_zeros %%c & set "token_c=!strip_lead_zeros_output!" )
  265.     if not "%%d" == "" ( call :strip_lead_zeros %%d & set "token_d=!strip_lead_zeros_output!" )
  266. )
  267.  
  268. set "tokenize_output=%token_a% %token_b% %token_c% %token_d%"
  269.  
  270. if "%token_type%" == "offset" (
  271.     set "reverse="
  272.     for %%a in (%tokenize_output%) do (
  273.         set "reverse=%%a !reverse!"
  274.         shift
  275.     )
  276.     set "tokenize_output=!reverse!"
  277. )
  278.  
  279. set "token_a="
  280. set "token_b="
  281. set "token_c="
  282. set "token_d="
  283.  
  284. goto :eof
  285.  
  286.  
  287.  
  288.  
  289. :strip_lead_zeros
  290.  
  291. call :operation_tracker "Strip Lead Zeros"
  292.  
  293. set "strip_lead_zeros_input=%1"
  294.  
  295. rem call :debug "strip_lead_zeros_input=%strip_lead_zeros_input% multiplier=%multiplier% strip_lead_zeros_output=%strip_lead_zeros_output%
  296.  
  297. if "%strip_lead_zeros_input%" == "%strip_lead_zeros_input:-=%" ( set /a "multiplier=1" ) else ( set /a "multiplier=-1" )
  298.  
  299. rem call :debug "strip_lead_zeros_input=%strip_lead_zeros_input% multiplier=%multiplier% strip_lead_zeros_output=%strip_lead_zeros_output%
  300.  
  301. set /a "strip_lead_zeros_output=1%strip_lead_zeros_input:-=% - ( 11%strip_lead_zeros_input:-=% - 1%strip_lead_zeros_input:-=% ) / 10"
  302.  
  303. rem call :debug "strip_lead_zeros_input=%strip_lead_zeros_input% multiplier=%multiplier% strip_lead_zeros_output=%strip_lead_zeros_output%
  304.  
  305. set /a "strip_lead_zeros_output= %strip_lead_zeros_output% * %multiplier%"
  306.  
  307. rem call :debug "strip_lead_zeros_input=%strip_lead_zeros_input% multiplier=%multiplier% strip_lead_zeros_output=%strip_lead_zeros_output%"
  308.  
  309. goto :eof
  310.  
  311.  
  312.  
  313. rem Time Format -> Seconds
  314. :convertTime
  315.  
  316. call :operation_tracker "Convert Time"
  317.  
  318. for /f "tokens=1-3 delims=:.," %%a in ("%1") do (
  319.  
  320.     rem call :debug "Converting Time: arg1 %%1   deliminated a %%a   b %%b   c %%c"
  321.    
  322.     set /a "convertTime_output=(( %%a * 60 * 60) + ( (%%b * 60) + %%c +0))"
  323.     rem call :debug "Convert Time %1 -> (( %%a * 60 * 60) + ( (%%b * 60) + %%c +0)) = !convertTime_output!"
  324. )
  325.  
  326.  
  327. goto :eof
  328.  
  329.  
  330.  
  331. rem Debug
  332. :debug
  333.  
  334. if not defined debug_count ( set "debug_count=0" )
  335. set /a "debug_count+=1"
  336.  
  337. echo.
  338. echo  Debug %debug_count%
  339. echo %1
  340. echo.
  341.  
  342. pause
  343.  
  344. goto :eof
  345.  
  346.  
  347.  
  348.  
  349. :operation_tracker
  350.  
  351. set "operation_step=%operation_step% -> %1"
  352. set "operation_step=%operation_step:"=%"
  353.  
  354. rem call :debug "%operation_step%"
  355.  
  356. goto :eof
  357.  
  358.  
  359.  
  360. rem Nominalize ( well, kinda, not really )
  361. :nominalize
  362.  
  363. call :operation_tracker "Nominalize"
  364.  
  365. set /a "seconds_per_day=(24*60*60)"
  366. set /a "seconds_per_hour=(60*60)"
  367. set /a "seconds_per_minute=(60)"
  368.  
  369. set /a "number_of_days=(%1 / %seconds_per_day%)", "remainder=(%1 %% %seconds_per_day%)"
  370. set /a "number_of_hours=(%remainder% / %seconds_per_hour%)", "remainder=(%remainder% %% %seconds_per_hour%)"
  371. set /a "number_of_minutes=(%remainder% / %seconds_per_minute%)", "number_of_seconds=(%remainder% %% %seconds_per_minute%)"
  372.  
  373. rem call :debug "Nominalize from %1 seconds to days %number_of_days% hours %number_of_hours% minutes %number_of_minutes% seconds %number_of_seconds%"
  374.  
  375. goto :eof
  376.  
  377.  
  378.  
  379. rem Execution of Shut Down
  380. :execute
  381.  
  382. call :operation_tracker "Execute"
  383.  
  384. if not defined set_delay_seconds set set_delay_seconds=0
  385. if not defined offset_delay_seconds set offset_delay_seconds=0
  386.  
  387. set /a "total_wait_seconds=(%set_delay_seconds% + %offset_delay_seconds%)"
  388.  
  389. cls
  390. echo.
  391. call :splash
  392. echo.
  393.  
  394. rem call :debug "Entering Execution. Adding timestamp %timestamp% and %offset_delay_seconds% to get total wait time %total_wait_seconds%"
  395.  
  396. call :nominalize %total_wait_seconds%
  397.  
  398. echo  Shutdown will begin in %number_of_days% days, %number_of_hours% hours, %number_of_minutes% minutes, and %number_of_seconds% seconds.
  399. echo.
  400.  
  401. set /a "shutdown_time=%time_now% + %total_wait_seconds%"
  402.  
  403. call :nominalize %shutdown_time%
  404.  
  405. set number_of_minutes=00%number_of_minutes%
  406. set number_of_seconds=00%number_of_seconds%
  407.  
  408. echo  That will be in %number_of_days% days at %number_of_hours%:%number_of_minutes:~-2%:%number_of_seconds:~-2%
  409.  
  410.  
  411.  
  412. echo.
  413. echo  Closing this window will interrupt the process safely.
  414. echo  Have a nice day!
  415. echo.
  416.  
  417. if %total_wait_seconds% LSS 0 (
  418.  
  419. cls
  420.  
  421. echo.
  422. call :splash
  423. echo.
  424. echo  Whoops, the time you specified is in the past. Try again.
  425. echo.
  426.  
  427. pause
  428.  
  429. goto :start
  430.  
  431. )
  432.  
  433. call :wait
  434.  
  435. shutdown /s /t 5
  436.  
  437. echo.
  438. echo  Goodbye
  439. echo.
  440.  
  441. timeout 10 /nobreak
  442.  
  443. call :error "Script reached conclusion, but PC has yet to shut down."
  444.  
  445. goto :eof
  446.  
  447.  
  448.  
  449.  
  450. :wait
  451.  
  452. set /a "timeout_limit=24 * 60 * 60"
  453.  
  454. if %total_wait_seconds% GTR %timeout_limit% (
  455.    
  456.     timeout %timeout_limit% /nobreak
  457.    
  458. ) else (
  459.  
  460.     timeout %total_wait_seconds% /nobreak
  461. )
  462.    
  463. set /a "total_wait_seconds-=%timeout_limit%"
  464.  
  465. if %total_wait_seconds% GTR 0 ( goto :wait )
  466.  
  467. goto :eof
  468.  
  469.  
  470.  
  471.  
  472. :help
  473. cls
  474. echo.
  475. call :splash
  476. echo.
  477. echo -----
  478. echo.
  479. echo  This script can understand two types of custom input.
  480. echo.
  481. echo    "Set" Time
  482. echo    and
  483. echo    "Offset" Time
  484. echo.
  485. echo  It differentiates between the two based on the presense/location of a "+" symbol.
  486. echo.
  487. echo  A custom input of "12:00:00" will translate to 12:00pm.
  488. echo  A custom input of "+12:00:00" will translate to mean twelve hours from time of input.
  489. echo.
  490. echo  Both can be used together.
  491. echo.
  492. echo  A custom input of "12:00:00+12:00:00" will translate to
  493. echo  Twelve hours after 12:00pm.
  494. echo.
  495. echo.
  496. echo  page 1 / 6
  497. echo.
  498.  
  499. pause
  500.  
  501. echo -----
  502. echo.
  503. echo  Colons can be replaced with Decimals freely.
  504. echo  This is to make entry on the 10-key Number Pad easier.
  505. echo.
  506. echo  Also, the number of digits is not monitored.
  507. echo.
  508. echo  For example, the following custom inputs would all be parsed identically:
  509. echo.
  510. echo    12:00:00
  511. echo    12.00.00
  512. echo.
  513. echo    12:00000:00
  514. echo    12.0.0
  515. echo.
  516. echo.
  517. echo  page 2 / 6
  518. echo.
  519.  
  520. pause
  521.  
  522. echo -----
  523. echo.
  524. echo  For "Set" Time, the hours and minutes are required.
  525. echo  If you do not include a placeholder for seconds, it will be assumed to be zero.
  526. echo.
  527. echo  The following two examples are parsed identically:
  528. echo.
  529. echo    12:00:00
  530. echo    12:00
  531. echo.
  532. echo.
  533. echo  page 3 / 6
  534. echo.
  535.  
  536. pause
  537.  
  538. echo -----
  539. echo.
  540. echo  For "Offset" Time, parsing assumes you input seconds, and builds up from there.
  541. echo  "Offset" Time also can accept up to a number of days to delay for.
  542. echo.
  543. echo  The following table shows a handful of inputs and their effect to demonstrate these points.
  544. echo.
  545. echo    +30 ........... plus 30 seconds
  546. echo    +1:30 ......... plus 1 minute 30 seconds
  547. echo    +1:30:00 ...... plus 1 hour 30 minutes
  548. echo    +1:00:00:00 ... plus 1 day
  549. echo.
  550. echo.
  551. echo  page 4 / 6
  552. echo.
  553.  
  554. pause
  555.  
  556. echo -----
  557. echo.
  558. echo  For "Offset" Time, parsing accounts for negative numbers.
  559. echo  While you cannot have an over-all sum of less than zero seconds,
  560. echo  this may make inputting some amounts of time easier.
  561. echo.
  562. echo  The following table shows a handful of inputs and their effect to demonstrate these points.
  563. echo.
  564. echo    +30:-30 ............. plus 30 minutes minus 30 seconds,  or  plus 29 minutes and 30 seconds
  565. echo    +1:-15:00 ........... plus 1 hours minus 15 minutes,     or  plus 45 minutes
  566. echo    12:00:00+-1:00:00 ... 12:00 PM minus 1 hour,             or  11:00 AM.
  567. echo.
  568. echo.
  569. echo  page 5 / 6
  570. echo.
  571.  
  572. pause
  573.  
  574. echo -----
  575. echo.
  576. echo  This script only has limited error handling.
  577. echo.
  578. echo  Always double-check the final screen after input shows the correct value.
  579. echo.
  580. echo.
  581. echo  page 6 / 6
  582. echo.
  583. echo  Continuing now will lead back to the main menu.
  584. echo.
  585.  
  586. pause
  587.  
  588. goto :start
  589.  
  590.  
  591.  
  592. rem Error Reporter
  593. :error
  594.  
  595. cls
  596.  
  597. echo.
  598. set convertTime_output
  599. set multiplier
  600. set number_of_days
  601. set number_of_hours
  602. set number_of_minutes
  603. set number_of_seconds
  604. set offset_delay_seconds
  605. set offset_nominal
  606. set preset0
  607. set preset1
  608. set preset2
  609. set preset3
  610. set preset4
  611. set preset5
  612. set preset6
  613. set preset7
  614. set preset8
  615. set preset9
  616. set remainder
  617. set reverse
  618. set seconds_per_day
  619. set seconds_per_hour
  620. set seconds_per_minute
  621. set set_delay_seconds
  622. set shutdown_time
  623. set splash1
  624. set splash2
  625. set splash3
  626. set strip_lead_zeros_input
  627. set strip_lead_zeros_output
  628. set timeout_limit
  629. set time_now
  630. set time_offset
  631. set time_offset_days
  632. set time_offset_hours
  633. set time_offset_minutes
  634. set time_offset_seconds
  635. set title
  636. set tokenize_input
  637. set tokenize_output
  638. set token_type
  639. set total_wait_seconds
  640. set user_input
  641. set version
  642. echo.
  643. echo.
  644. echo  An error has occured.
  645. echo   %1
  646. echo.
  647. echo  The error was in:
  648. echo    " %operation_step:~4% "
  649. echo.
  650. echo  A list of all variables made up to this point is listed above.
  651. echo.
  652. echo  If you wish to report this error,
  653. echo  copy the entirety of the text in this window and send it to KubosKube someway, somehow.
  654. echo  You can copy it to your clipboard, or take a screenshot.
  655. echo.
  656. echo  The script can be exited anytime. Thank you for your patience.
  657. echo.
  658. echo  Pressing any key will exit the script while this window is in focus.
  659. echo.
  660. pause
  661.  
  662. exit
Tags: batch
Advertisement
Add Comment
Please, Sign In to add comment