【问题标题】:Waiting for Process to terminate on a remote PC using for loop使用 for 循环等待进程在远程 PC 上终止
【发布时间】:2021-08-03 01:11:47
【问题描述】:

应该能够对此进行排序,但我正在兜圈子。我知道这与 setlocal 有关 EnableDelayedExpansion,但我错过了一些东西。

目标: 在远程机器上执行 windows (cleanmgr.exe) 脚本,等到 Cleanmgr.exe 关闭然后有 启动脚本从远程“输入”生成的日志文件(通过清理脚本生成) 系统在 CMD 窗口中。

什么有效: 在远程机器上运行的脚本运行良好,它将 C: free drive space 回显到日志文件中, 然后清理PC,然后重新运行磁盘空间报告并将结果回显到同一日志文件中, 因此用户可以通过前后结果看到(/具有透明度)回收空间。

什么是坏的: 在目标 PC 上检查 Cleanmgr.exe 的 WMIC 命令仅在等待重试时有效 包含主机名的变量已被清除。我可以通过回显来查看行为 变回。

修复尝试: 我有一种预感,这与 if 语句在 括号。我尝试了很多选项,但它们的行为都相同。我试过跳 使用 %1 而不是 %%i 处理在原始代码之外循环,但不能完全到达那里。

感谢您的改进。

@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

【问题讨论】:

  • 你不能在 for 循环中使用标签。
  • @Compo IIRC,在更早的时候(DOS 3.0/3.2..),我们有一个非常基本的 FOR 命令,我们可以用它执行多个带有 & 但没有括号块的语句。然后认为GOTO 命令无条件分支,然后退出FOR 循环。我猜 MS 一直保持这样,即使 括号内以保持与旧脚本的兼容性。
  • 您也可以在父子批处理文件中使用WaitFor 命令相互通信。
  • 对于任何感兴趣的人,有一个 IBM PC-DOS 的 Web 实现(也有 3.2 和许多其他版本)here。我还记得如何使用SYSTEM 命令退出IBM BASIC... 这不公平,几年只会带来经验和痛苦...无论如何,FOR 命令就像我记得的那样工作:FOR %I IN (A B C) DO ECHO %I 没问题,但是@987654330 @ 也没有 CALL 在 3.2 中不存在..(因为 CALL 的 3.3,我猜 & 是 W95)

标签: for-loop batch-file cmd parentheses wmic


【解决方案1】:

至少有两点可看。

  1. 您的 running 变量一旦设置,就永远不会重置,从而触发无限循环
  2. 您在括号内的goto 语句会驱动命令解释器 (cmd.exe) 停止评估该块,因此您的脚本会松开 %%i 并离开 for 循环,因此在终止 :loop 时循环您的脚本将离开 for 循环而不循环到 hostnames.txt 中的其他值。

要解决这个问题,请将您的流程代码放入以CALL 调用的子例程中,并在每个:loop 循环中重置running 变量:

@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

说明:CALL 语句意味着命令解释器将在执行关联的子进程/命令/等之前存储脚本的当前执行行及其状态。当子进程/命令/等完成时,命令解释器使用恢复的上下文继续执行脚本到下一行。这避免了 for 循环上下文的松散。

【讨论】:

  • 完美,谢谢。也很有价值的解释。欣赏它。
猜你喜欢
  • 1970-01-01
  • 2020-09-09
  • 1970-01-01
  • 2019-04-28
  • 2020-04-21
  • 2016-07-22
  • 1970-01-01
  • 2013-05-11
  • 2013-12-26
相关资源
最近更新 更多