问题描述
应该能够对此进行排序,但我正在绕圈子。我知道这与 setlocal 有关 EnableDelayedExpansion,但我遗漏了一些东西。
目标: 在远程机器上执行 windows (cleanmgr.exe) 脚本,等到 Cleanmgr.exe 关闭然后有 启动脚本从远程“键入”结果日志文件(通过清理脚本生成) CMD 窗口中的系统。
什么是有效的: 在远程机器上运行的脚本运行良好,它将 C: 可用驱动器空间回显到日志文件中, 然后清理PC,然后重新运行磁盘空间报告并将结果回显到同一个日志文件中, 因此用户可以通过前后结果看到(/具有透明度)回收的空间。
坏处: 用于在目标 PC 上检查 Cleanmgr.exe 的 WMIC 命令仅在等待重试时起作用一次 包含主机名的变量已被清除。我可以通过回显来查看行为 可变回。
修复尝试: 我有一种预感,这与一旦 if 语句在 括号。我尝试了很多选择,但它们的行为都一样。我试过跳 使用 %1 而不是 %%i 处理 out 以在原始代码之外循环,但无法完全到达那里。
感谢您的任何改进。
@echo off
pushd %~dp0
color 1e
setlocal EnableDelayedExpansion
title HDD Space Checker...
for /f %%i in (hostnames.txt) do (
xcopy /y cleanupwindows-sfd.bat \\%%i\C$\IT
WMIC /node:"%%i" process call create "C:\IT\cleanupwindows-sfd.bat"
echo Waiting For Processes...
timeout -t 10 /nobreak >nul
:loop
WMIC /node:"%%i" process where name="cleanmgr.exe" get name |find "cleanmgr.exe">nul
IF "!errorlevel!"=="0" set running=var
IF "!running!"=="var" timeout -t 4 >nul & echo Still Running & goto :loop
IF "!running!"=="" timeout -t 4 >nul & type \\%%i\C$\IT\%%i_HHD_Space.log
)
pause
exit
解决方法
至少有两点要看。
- 您的
running
变量一旦设置,就永远不会重置,从而触发无限循环 - 您在括号内的
goto
语句驱动命令解释器 (cmd.exe) 停止评估块,因此您的脚本松开%%i
并离开 for 循环,因此在终止 { {1}} 循环您的脚本将离开 for 循环而不循环到:loop
中的其他值。
要解决这个问题,请将您的流程代码放入使用 hostnames.txt
调用的子例程中,并在每个 CALL
周期重置 running
变量:
:loop
说明:@echo off
pushd %~dp0
color 1e
setlocal EnableDelayedExpansion
title HDD Space Checker...
for /f %%i in (hostnames.txt) do (
CALL:Process "%%i"
)
pause
exit
:Process
xcopy /y cleanupwindows-sfd.bat \\%~1\C$\IT
WMIC /node:"%~1" process call create "C:\IT\cleanupwindows-sfd.bat"
echo Waiting For Processes...
timeout -t 10 /nobreak >nul
:loop
set "running="
WMIC /node:"%~1" process where name="cleanmgr.exe" get name |find "cleanmgr.exe">nul
IF "!errorlevel!"=="0" set "running=var"
IF "!running!"=="var" timeout -t 4 >nul & echo Still Running & goto :loop
IF "!running!"=="" timeout -t 4 >nul & type \\%~1\C$\IT\%~1_HHD_Space.log
GOTO:EOF
语句暗示命令解释器将在执行关联的子进程/命令/等之前存储脚本的当前执行行及其状态。当子进程/命令/等...完成时,命令解释器将脚本的执行恢复到具有恢复上下文的下一行。这避免了 for 循环上下文的松散。