【发布时间】:2022-11-25 14:58:41
【问题描述】:
我正在尝试为文件夹中的每个文件做一些工作,等到虚拟机的属性设置为特定值并执行其他一些任务:
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 属性 - 此属性意味着我的脚本在来宾 VM 中完成。所以,如果我在目标文件夹中有 2 个文件,批处理文件应该这样做:
- 恢复虚拟机
- 将文件复制到 VM 并在 VM 中运行 python 脚本
- 等到上面提到的 python 脚本将
STATE属性设置为“完成” - 将文件从来宾复制到主机
(迭代 2)
- 恢复虚拟机
- 将文件复制到 VM 并在 VM 中运行 python 脚本
- (我省略了它,但我想应该清除
STATE变量) - 再次等待,直到上述 python 脚本将
STATE属性设置为“完成” - 将文件从来宾复制到主机
我会考虑你所有的建议,但我现在的主要问题是如何将工作流从
check_state子程序返回到外部FOR循环。 注意:我已经修复了缺失的setlocal enabledelayedexpansion行。
更新 2:我厌倦了处理批处理,所以我用 Python 重写了我的脚本。但是,我仍然有兴趣了解如何使用批处理文件来完成它。
【问题讨论】:
-
比较运算符
NEQ主要用于整数比较,即NEQ左边的整数不等于NEQ右边的整数。出于这个原因,应该使用IF NOT !STATE! == !FINISHED_STATE!对区分大小写的不相等字符串进行比较。有关字符串比较的更多信息如果在Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files 上查看我的回答。 -
发布的代码不包含
setlocal EnableExtensions EnableDelayedExpansion,它根据需要为此批处理文件启用命令扩展(默认情况下启用)和延迟环境变量扩展(默认情况下禁用)。但是,问题是:checking_loop和goto :checking_loop在标签check_state下面的块中用命令调用称呼作为子例程(嵌入批处理文件中的批处理文件)。命令块中的标签以(开头并以匹配的)结尾是不可能的。删除行:checking_loop和最后一行或最好是最后两行。 -
更改代码时不需要延迟变量扩展,如下所示:1.删除行
SET FINISHED_STATE=Finished2.删除行:checking_loop,3.用IF NOT DEFINED STATE CALL :check_state替换IF !STATE! NEQ !FINISHED_STATE! call :check_state4.将SET STATE=%STATE:~7%替换为if "%STATE:~7%" == "Finshed" goto :EOF以退出子程序,环境变量STATE定义在前七个字符上,区分大小写Finished。5.最后的编辑对我来说不是很清楚,因为缺少关于什么应该是想要的行为的描述。 -
必须将最后两行替换为
set "STATE=" & goto :EOF才能退出子程序 on state is notFinishedwith environment variableSTATEagain undefined 并继续为了用echo "doing some other task"循环或用%SystemRoot%\System32\ping.exe -n 2 127.0.0.1 >nul或%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK >nul和goto check_state行替换最后两行等待一秒钟并保持子程序直到状态等于Finished在这种情况下子程序永远不会又被主叫了为了环形。 -
关于“Update2”:Mofi 已经告诉过你:不要在代码块中使用标签。你能够
goto :outOfLoop,但这结束了循环上下文。 (call不同,因为它在不中断循环的情况下返回)。当然“代码块内没有标签”也意味着“不可能跳入代码块”。在我看来,您刚刚阅读/处理了 Mofi 的第一条评论(共四条),这很遗憾,因为 Mofi 花了很多精力来解释您的代码有什么问题以及如何使其工作。不要指望在这里得到定制的“复制&粘贴&避免思考”解决方案。
标签: windows for-loop batch-file