【问题标题】:Set /p Instantly立即设置 /p
【发布时间】:2015-04-02 20:55:58
【问题描述】:

我一直在尝试创建一个对用户输入进行计时的文件。 我可以得到这个文件

start /min b1.bat
(:b1.bat)
@echo off
cls
set num=0
:time
set /a num=%num%+1
echo %num% >waiter.txt
set time=0
:wait
cls
set /a time=%time%+1
if "%time%" equ "1000" goto time
goto wait

在这里,b1.bat 计算自启动以来经过的秒数。

(:b2.bat)
cls
:begin
set /p time= <waiter.txt
echo %time%    
if "%time%" equ "5" echo Five secconds.
set /p cho=Input:
goto begin

如果在一段时间内没有输入,我想知道如何让 b2.bat 做某事。根本没有输入,甚至没有按回车键。

所以,如果我根本没有按任何键并且一分钟过去了,它会打印 A minute has passed without input.

我希望这对你有意义。

【问题讨论】:

    标签: batch-file input time call


    【解决方案1】:

    在回答您的问题之前,我需要指出循环 1000 次并不一定意味着您已暂停 1 秒。有更好的睡眠方式——Vista 或更新版本中的timeout /t seconds,或XP 中的ping -n seconds+1 localhostchoice /t seconds。您还应该避免踩existing environment variables,例如%time%

    要回答您的问题,没有优雅的方法可以为set /p 设置超时。但是,您可以使用start /b 在同一窗口中启动后台线程,以在间隔内回显内容。您可以使用waitfor(仅限Vista或更高版本)设置活动线程与后台之间的线程间通信以重置计时器,并将辅助线程设置为在waiter.txt消失时自毁。

    只要您在同一个窗口中启动一个辅助线程,不妨将您的 waiter.txt 线程也放在那里。当您可以重复使用已有的窗口时,为什么还要生成一个最小化的窗口?由于我们在同一窗口中合并进程线程,不妨更进一步,将所有脚本合并为一个脚本,该脚本使用不同线程的不同参数重新启动自身。

    @echo off
    setlocal
    
    if "%~1"=="" (
        >waiter.txt echo 0
        start /b "" "%~f0" helper1
        start /b "" "%~f0" helper2
    ) else goto %~1
    
    :begin
    cls
    set /p "seconds="<waiter.txt
    echo Alive for %seconds%s.
    
    :read-host
    set "cho="
    set /p "cho="
    if not defined cho goto read-host
    
    rem // delayed expansion prevents evaluation of special characters in user input
    setlocal enabledelayedexpansion
    for %%c in (quit exit die EOL) do if /i "!cho!"=="%%c" (
        del waiter.txt
        echo OK, bye!
    )
    rem // send signal to helper2 acknowledging entry
    waitfor /s %computername% /si UserEntry >NUL 2>NUL
    if not exist waiter.txt exit /b
    
    rem // ========================================
    rem // Do something meaningful with !cho! here.
    rem // ========================================
    endlocal
    
    goto begin
    
    rem // formerly b1.bat
    :helper1
    set "num=0"
    :helper1_loop
    timeout /t 1 /nobreak >NUL 2>NUL
    set /a num+=1
    if not exist waiter.txt exit
    >waiter.txt echo %num%
    goto helper1_loop
    
    :helper2
    if not exist waiter.txt exit
    waitfor /t 60 UserEntry >NUL 2>NUL || (
        echo A minute has passed without input.
    )
    goto helper2
    

    为了额外的功劳,让我们也去掉 waiter.txt。我不确定这种偏执是否成立,但我相信硬盘驱动器扇区可以承受有限数量的写入。每秒重写一次 waiter.txt 可能会困扰我几个小时。因此,让我们创建一个混合 Jscript 块来计算从脚本开始到现在所经过的秒数。

    为了控制后台帮助线程的执行,我们仍将使用一个临时文件,但我们将使用一个lock file,它只会被写入一次,然后在最后被删除。

    @if (@CodeSection == @Batch) @then
    
    @echo off
    setlocal
    
    if "%~1"=="" (
        rem // relaunch self as helper if lock file is writeable
        2>NUL (>"%~dpn0.lock" type NUL) && start /b "" "%~f0" helper
    
        rem // create a lock file for the duration of the main runtime
        rem // Credit: Dave Benham -- https://stackoverflow.com/a/27756667/1683264
        8>&2 2>NUL (2>&8 9>"%~dpn0.lock" call :init) || (
          echo Only one instance is allowed.
          timeout /t 3 /nobreak >NUL
          exit /b
        )
    ) else goto %~1
    
    rem // cleanup and end main runtime
    del "%~dpn0.lock" >NUL 2>NUL
    waitfor /s %computername% /si UserEntry >NUL 2>NUL
    exit /b
    
    :init
    rem // set %start% to current epoch
    call :jscript start
    
    :begin
    cls
    call :jscript seconds
    echo Alive for %seconds%s.
    
    :read-host
    set "cho="
    set /p "cho="
    if not defined cho goto read-host
    
    rem // delayed expansion prevents evaluation of special characters in user input
    setlocal enabledelayedexpansion
    for %%c in (quit exit die EOL) do if /i "!cho!"=="%%c" (
        echo OK, bye!
        exit /b
    )
    rem // send signal to helper2 acknowledging entry
    waitfor /s %computername% /si UserEntry >NUL 2>NUL
    
    rem // ========================================
    rem // Do something meaningful with !cho! here.
    rem // ========================================
    endlocal
    
    goto begin
    
    :helper
    del "%~dpn0.lock" >NUL 2>NUL
    if not exist "%~dpn0.lock" exit
    waitfor /t 60 UserEntry >NUL 2>NUL || (
        echo A minute has passed without input.
    )
    goto helper
    
    :jscript
    for /f %%I in ('cscript /nologo /e:JScript "%~f0" "%start%"') do set "%~1=%%I"
    goto :EOF
    
    @end // end batch / begin JScript hybrid code
    WSH.Echo(
        WSH.Arguments(0)
        ? Math.round((new Date() - WSH.Arguments(0)) / 1000)
        : new Date().getTime()
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 2013-12-27
      相关资源
      最近更新 更多