I've tried to create an invisible countdown.
For example, the script starts the countdown, but in the meantime the script runs like an MMORPG. When you are entering an instance dungeon, it starts the countdown and you can walk etc. But when I do it with PING -n 6 127.0.0.1 //Delay the script for 5 seconds. I want the PING to run in the background and meanwhile the script goes on. I've got a response from Stephan but his code didn't work :(
Stephan's Code:
#echo off
setlocal enabledelayedexpansion
REM create a CarriageReturn:
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
for /L %%i in (5,-1,0) do (
<nul set /p =King Albireo is spawning in %%i seconds...!CR!
ping -n 2 127.0.01 >nul
)
goto Main
:Main
#title Example: Countdown
cls
echo It works
pause
Can someone make this script so it is running in the background and meanwhile the script goes on.
I know I used the same words over and over just to make sure everyone is getting what I am trying to say.
BTW thanks Stephan for the code.
You can try with
start "" /b cmd /q /v /e /c"(for /l %%a in (5 -1 1) do (echo respawn in %%a seconds&>nul ping -n 2 ""))&echo RESPAWN"
Related
I am trying to make a text-based game, and when the user enters something, I want the computer's character to have some kind of thinking animation.
I've come up with this: [. ] [.. ] [...]
Only problem is, I want it all to be on one line, so it's like an actual animation. I've successfully recreated this without removed the text already echo'd, but it requires that you cls, then send all that was on the screen before, three times. Obviously this takes too much space and is pretty inefficient.
I found a code that changes the last like without clearing all that was before it,
#echo off
echo This won't disappear!
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
for /L %%n in (5 -1 1) do (
<nul set /P "=This window will close in %%n seconds!CR!"
ping -n 2 localhost > nul
)
It counts down without erasing the echo before, but I do not understand how to adapt it to add periods to my string... Does anyone know a way to do this? Thanks!
You were almost there with the code you found; you just need to use your own text instead of somebody else's.
for /L %%A in (1,1,3) do (
set /p "=."<nul
ping -n 2 localhost >nul
)
If you want to put the periods inside of brackets, you can use this:
for /f %%A in ('"prompt $H &echo on &for %%B in (1) do rem"') do set BS=%%A
set /p "=[ ]"<nul
ping -n 2 localhost >nul
set /p "=%BS%%BS%%BS%%BS%. ]"<nul
ping -n 2 localhost >nul
set /p "=%BS%%BS%%BS%. ]"<nul
ping -n 2 localhost >nul
set /p "=%BS%%BS%.]"<nul
ping -n 2 localhost >nul
I want to make this code to ask for a password that timeouts after 10 seconds and if you wrote the correct password it goes to :wow but if it's incorrect it just continues the code . (the code is just an example)
#ECHO OFF
TIMEOUT /t 10>nul
exit
:wow
echo now this is fun!
pause
exit
MD5sum
Batch scripts, as they live in the world of plain text files, aren't very conducive to storing and matching passwords. After all, the person running the script could just as easily open it in Notepad and see the expected password. That's not very hacksy, now, is it?
These batch password questions pop up from time to time, and hard-coded passwords in scripts always irritate me. So how about, for a change, we obfuscate the password with an MD5 hash? There's no simple command built into Windows that makes this happen, but it can be accomplished with a (admittedly convoluted) PowerShell one-liner.
Save this helper script as md5sum.bat:
#echo off
setlocal
if "%~1"=="" goto :EOF
powershell "[Security.Cryptography.HashAlgorithm]::Create('MD5').ComputeHash([Text.Encoding]::UTF8.GetBytes('%~1')) | %%{write-host -n $_.tostring('x2')}"
Then use it to find the MD5 hash of the password you want like this:
md5sum.bat "password"
The result will output
5f4dcc3b5aa765d61d8327deb882cf99
Rather than hard coding the password itself into your script, you can now hard code 5f4dcc3b5aa765d61d8327deb882cf99.
User Entry
Now comes the interesting stuff. You can also borrow from Powershell to obfuscate the user entry like this:
#echo off
setlocal
<NUL set /P "=Password? "
set "psCommand=powershell -command "$p=read-host -AsSecureString;^
$m=[Runtime.InteropServices.Marshal];$m::PtrToStringAuto($m::SecureStringToBSTR($p))""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set "pass=%%p"
setlocal enabledelayedexpansion
echo You entered !pass!
endlocal
Combine the two methods and you can check to see whether the password entered by the user matches the hash hard coded into the script.
#echo off
setlocal
<NUL set /P "=Password? "
set "psCommand=powershell "$p=read-host -AsSecureString;^
$m=[Runtime.InteropServices.Marshal];$x=$m::PtrToStringAuto($m::SecureStringToBSTR($p));^
[Security.Cryptography.HashAlgorithm]::Create('MD5').ComputeHash([Text.Encoding]::UTF8.GetBytes($x)) ^| %%{write-host -n $_.tostring('x2')}""
for /f "usebackq delims=" %%I in (`%psCommand%`) do (
if "%%~I"=="5f4dcc3b5aa765d61d8327deb882cf99" goto :match
)
echo Nope.
goto :EOF
:match
echo w00!
Voila! Now you can expect a user entry of password but the user can't easily see by opening in Notepad that password is the correct password. Cool, huh?
Self-Destruct
Back to your original question of how you can make this timeout after 10 seconds, you'll have to get a little creative. One solution would be to launch a helper script in the background that waits for 10 seconds, then kills all powershell.exe tasks. This can interfere with other powershell-ish stuff you might have running -- but let's be honest. Given the elementary nature of the question, I think it's safe to assume that won't be a problem in this situation.
I would do it this way:
#echo off
setlocal
if "%~1"=="helper" goto helper
start /b "" "%~f0" helper
<NUL set /P "=Password? "
set "psCommand=powershell "$p=read-host -AsSecureString;^
$m=[Runtime.InteropServices.Marshal];$x=$m::PtrToStringAuto($m::SecureStringToBSTR($p));^
[Security.Cryptography.HashAlgorithm]::Create('MD5').ComputeHash([Text.Encoding]::UTF8.GetBytes($x)) ^| %%{write-host -n $_.tostring('x2')}""
for /f "usebackq delims=" %%I in (`%psCommand%`) do (
waitfor /s %computername% /si PasswordEntered >NUL 2>NUL
if "%%~I"=="5f4dcc3b5aa765d61d8327deb882cf99" goto :match
)
echo Nope.
goto :EOF
:match
echo w00!
goto :EOF
:: // END MAIN RUNTIME
:helper
>NUL 2>NUL (
title Enter password.
waitfor PasswordEntered /t 10 || taskkill /im "powershell.exe" /f
)
exit
If you'd rather not taskkill Powershell, it is possible to make read-host time out, but I'll leave that as an exercise for the reader.
You could start a VBS file with a password prompt.
http://www.robvanderwoude.com/vbstech_ui_password.php
The link above links to a page with a password prompt script. You could add a timeout wich would wait for 10 seconds and then close.
This is probably impossible, but I have a loop that displays a animated logo by using TYPE to type logo_(framenumber).txt and the framenumber is determined by a loop:
:s
if %m%==379 set m=0
cls
TYPE Logo_%m%.txt
set /a m=%m%+1
goto s
I wanted to be able to use a set /p option and without disturbing/stopping the loop so the animation plays while a user is typing in the set /p input. I think there is a way to do it with FOR but I'm not sure how. Any ideas? Thanks.
Although this topic is somewhat old, I just discovered it. This is a pure Batch file solution that works pretty well:
EDIT: I slightly modified the code in order to made it simpler.
#echo off
setlocal EnableDelayedExpansion
if "%1" equ "Animate" goto %1
for /F %%a in ('echo prompt $H ^| cmd') do set "BS=%%a"
for /F %%a in ('copy /Z "%~F0" NUL') do set "CR=%%a"
cd . > input.txt
start "" /B "%~F0" Animate
set "input="
:nextKey
set "key="
for /F "delims=" %%K in ('xcopy /W "%~F0" "%~F0" 2^>NUL') do if not defined key set "key=%%K"
if "!key:~-1!" equ "!CR!" goto endInput
if "!key:~-1!" equ "!BS!" (
if defined input set "input=%input:~0,-1%"
) else (
set "input=%input%!key:~-1!"
)
set /P "=%input%" > input.txt < NUL
goto nextKey
:endInput
del input.txt
echo/
echo/
echo Input read: "%input%"
goto :EOF
:Animate
set "banner= Enter your name please "
set m=0
:loop
if not exist input.txt exit
set /A m=(m+1)%%51
cls
echo/
echo/ !banner:~%m%,31!
echo/
echo/
if exist input.txt (type input.txt) else exit
ping -n 1 -w 300 localhost > NUL
ping -n 1 -w 300 localhost > NUL
ping -n 1 -w 300 localhost > NUL
goto loop
In this solution the animated "logo" is replaced by a banner, but the method to display a series of files is practically the same.
EDIT: This is possible in batch. See Aacini's answer.
This is not possible with batch files. Batch commands are single-threaded. To run two things simultaneously requires two instances of cmd.exe. But the console subsystem only allows one program to own the console at a time, so if the second instance of cmd is attached to the same console, one of them must be blocked.
It is possible to do something like this with a win32 executable which uses WriteConsoleOutput to modify the characters on the console screen. If you do that, you are no longer limited to just dumping text files, but the downside is that it's a lot more work than calling type in batch.
New to batch scripting. Trying to write a script which checks for files with filename starting with LEND by polling a directory and if the file is not received by 17:30, then write a log message to log file. I have written the below batch script, the script runs fine as long as there are no files in the directory. As soon as I put files in there, it stops running. And restarts if I delete the files from that directory. Could you please advise where I am going wrong?
Thanks
#echo off
set I=0
set log=C:\logs\alerting.log
:recurse
for /f %%P in ('dir /b "C:\incoming\LEND*"') do (call :countfiles)
set Time=%time:~0,5%
echo Filecount: %I% at Time: %Time% >> %log%
if %Time%==17:30 goto OUT
pause 60
goto :recurse
:countfiles
set /a I+=1
:OUT
if %I%==0 echo LEND Files not received >> %log%
EXIT
Your code goes from countfiles to exit. Try this:
:countfiles
set /a I+=1
goto:eof
There were actually several flaws - reusing the time variable, expecting pause to be used as a delay, the time frame could have been missed in the test, and other more minor things.
This is tested as far as the file counting goes but not the 17:30 branch
I changed the style of a few commands and variable names (I is too much like l and i and 1 in many fonts)
#echo off
set log=C:\logs\alerting.log
:loop
for /f %%P in ('dir /b "C:\incoming\LEND*" 2^>nul ^| find /c /v "" ') do set c=%%P
set now=%time:~0,5%
echo Filecount: %c% at Time: %now%
echo Filecount: %c% at Time: %now% >> %log%
if %now:~0,2%%now:~3,2% GTR 1730 goto :OUT
ping -n 60 localhost >nul
goto :loop
:OUT
if %c% EQU 0 echo LEND Files not received >> %log%
EXIT
I'm creating a simple bat file that plays some ASCII animation stored in 120 .txt files. My script works but it works too fast. I'd like to find a way to slow it dow a bit. I've tried the TIMEOUT 1 command but it only plays 1 picture per second which is too slow. Is there a workable solution without moving from Windows 7 command line?
This is my script so far
#echo off
MODE CON: COLS=91 LINES=41
cls
:3
setlocal enableextensions enabledelayedexpansion
FOR /R %%i in (*.txt) do (type "%%i"
)
goto :3
You could use a FOR /L loop to introduce a delay. Here is a script that introduces an approximate 100 msec delay. A simple test near the top computes how many iterations are required to approximate 100 msec. The number will vary between machines. Adjust the definition of msecDelay as required to get your desired result.
#echo off
setlocal
:: Compute the number of iterations required to get the desired delay
set msecDelay=100
set ticks=100000
set "start=%time%"
for /l %%N in (1 1 %ticks%) do rem
set "stop=%time%"
for /f "tokens=3,4 delims=:.," %%A in ("%start%") do set /a start=1%%A%%B-10000
for /f "tokens=3,4 delims=:.," %%A in ("%stop%") do set /a stop=1%%A%%B-10000
if %start% gtr %stop% set /a stop+=6000
set /a delay=msecDelay*ticks/(stop-start)/10
MODE CON: COLS=91 LINES=41
cls
:3
FOR /R %%i in (*.txt) do (
type "%%i"
for /l %%n in (1 1 %delay%) do rem
)
goto :3
I'm wondering if you will get better results by moving CLS within the loop, just before your TYPE statement.
This is a very simple way to slow between frames
Example:
#echo exiting script
ping localhost -n 2 > nul
cls
#echo exiting script .
ping localhost -n 2 > nul
cls
#echo exiting script ..
ping localhost -n 2 > nul
cls
#echo exiting script ...
ping localhost -n 2 > nul
cls
#echo exiting script ....
ping localhost -n 2 > nul
cls
#echo exiting script .....
ping localhost -n 5 > nul
cls
Not built in, but still command line: sleep.exe from Windows Resource Kit (available here: http://www.microsoft.com/en-us/download/details.aspx?id=17657)
Usage: sleep time-to-sleep-in-seconds
sleep [-m] time-to-sleep-in-milliseconds
sleep [-c] commited-memory ratio (1%-100%)