如何修复等待变量的特定值

问题描述 投票:0回答:1

我正在尝试为文件夹中的每个文件执行一些操作,等到虚拟机的属性设置为特定值并执行一些其他任务:

ECHO off
setlocal enabledelayedexpansion

SET VM_NAME=Win10-Pro-x32
SET TESTS_FOLDER=C:\tests
SET STATE=
SET FINISHED_STATE=Finished

FOR %%f IN (%TESTS_FOLDER%\*) DO (
    echo "doing some task"
    :checking_loop
    IF !STATE! NEQ !FINISHED_STATE! call :check_state
    echo "doing some other task"
)

goto :eof

:check_state
    FOR /f "tokens=*" %%i IN ('VBoxManage guestproperty get %VM_NAME% "State"') DO SET STATE=%%i
    SET STATE=%STATE:~7%
    ping 127.0.0.1 -n 2 > nul
    goto :checking_loop

这段代码输出

"doing some task"
并继续做其他事情(我的意思是它不打印任何其他内容并且不停止),如何解决这个问题?

更新: 对 Mofi 的一些说明:我需要在所有迭代中等待

STATE
属性 - 该属性意味着我的脚本在来宾虚拟机中完成。所以,如果我在目标文件夹中有 2 个文件,批处理文件应该执行类似的操作:

  • 恢复虚拟机
  • 将文件复制到VM并在VM中运行python脚本
  • 等到上述 python 脚本将
    STATE
    属性设置为“Finished”
  • 将文件从访客复制到主机

(迭代 2)

  • 恢复虚拟机
  • 将文件复制到VM并在VM中运行python脚本
  • (我省略了它,但我认为
    STATE
    变量应该被清除)
  • 再次等待,直到上述 python 脚本将
    STATE
    属性设置为“完成”
  • 将文件从访客复制到主机 我会考虑您的所有建议,但现在对我来说主要问题是如何将工作流程从
    check_state
    子例程返回到外部
    FOR
    循环。 注意:我已经修复了缺失的
    setlocal enabledelayedexpansion
    线。

更新2:我厌倦了处理批处理,所以我使用Python重写了我的脚本。但是,我仍然有兴趣了解如何使用批处理文件来完成此操作。

windows for-loop batch-file
1个回答
1
投票

也许可以使用以下代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

set "VM_NAME=Win10-Pro-x32"
set "TESTS_FOLDER=C:\tests"
if exist %SystemRoot%\System32\timeout.exe (
    set "WaitASecond=%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK"
) else (
    set "WaitASecond=%SystemRoot%\System32\ping.exe -n 2 -w 1000 127.0.0.1"
)

for %%I in ("%TESTS_FOLDER%\*") do (
    echo doing some task
    call :wait_for_state
    if not errorlevel 1 (
        echo doing some other task
    ) else (
        echo Do something on state Finished not returned within 60 retries.
    )
)
rem Exit the batch file processing without a fall through to the subroutine.
exit /B

rem The subroutine below exits with value 0 on executed program/script has
rem output a string containing anywhere case-insensitive the word Finished.
rem The program/script is otherwise executed after a delay of one second
rem once more. But the retry loop is exited after 60 retries which is
rem approximately 60 seconds (one minute) on VBoxManage finishes always
rem quickly in a few milliseconds to avoid an endless running retry loop.
rem The value 1 is returned in this error case by the subroutine to the
rem calling FOR loop above which should handle this error case appropriately.

:wait_for_state
set "State=Wait"
set "LoopCount=60"
:Retry
for /F "tokens=*" %%J in ('VBoxManage guestproperty get "%VM_NAME%" "State"') do set "STATE=%%J"
if not "%State:Finished=%" == "%State%" exit /B 0
set /A LoopCount-=1
if %LoopCount% == 0 exit /B 1
%WaitASecond% >nul
goto Retry

代码期望子例程中的 FOR 在后台执行以下命令行

wait_for_state
总是在几毫秒内快速完成:

C:\Windows\System32\cmd.exe /c VBoxManage guestproperty get "Win10-Pro-x32" "State"

命令 FOR 始终等待启动的

cmd.exe
的自终止,该自终止在执行
VBoxManage
(可执行文件或脚本)后自行关闭。然后 FOR 处理通过 VBoxManage 写入后台命令进程句柄
STDOUT
(标准输出)的捕获输出。

IF 条件 if not "%State:Finished=%" == "%State%" exit /B 0

 将分配给环境变量 
State
 的字符串替换为空字符串(不区分大小写)所有出现的单词 
Finished
(删除该单词),并将结果字符串与分配的未修改字符串进行比较到环境变量
State
。仅当分配给环境变量 
State
 的字符串包含不区分大小写的至少一次单词 
Finished
 时,两个比较的字符串才不相等,在这种情况下,子例程将以值 0 退出以继续处理批处理文件在命令行下方
call :wait_for_state

我通过在当前目录中创建第二个批处理文件来测试批处理文件,其名称为

VBoxManage.cmd

,仅包含以下命令行:

@if exist test.txt del test.txt & echo ... Finished ...
我在上面的批处理文件运行时打开了第二个命令提示符窗口,并以当前目录作为包含两个批处理文件的目录执行命令

echo Test>Test.txt

,以测试子例程的两个退出条件。

要了解所使用的命令及其工作原理,请打开

命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。

  • call /?
    
    
  • echo /?
    
    
  • endlocal /?
    
    
  • exit /?
    
    
  • goto /?
    
    
  • if /?
    
    
  • set /?
    
    
  • setlocal /?
    
    
© www.soinside.com 2019 - 2024. All rights reserved.