您如何等待任务计划程序任务在批处理文件或 C# 中完成?
Posted
技术标签:
【中文标题】您如何等待任务计划程序任务在批处理文件或 C# 中完成?【英文标题】:How do you wait on a Task Scheduler task to finish in a batch file or C#? 【发布时间】:2013-12-14 05:26:07 【问题描述】:我正在尝试编写一个执行两件事的批处理文件:
-
首先它会启动一个安装程序 (install.exe),该安装程序会安装一个程序 (program.exe)。
其次,它启动已安装程序 (program.exe) 的实例。这必须在安装完成后执行。
这相对简单,只是安装程序需要管理员权限并且必须在用户上下文中运行。即使有这些限制,这仍然相对简单,除了我在 Azure Worker Role 上运行它,这意味着两件事:
-
Elevated batch files must be run from a startup task.
There is no user context for startup tasks in Azure worker roles.
因此,解决方案似乎是run the installer as a Task Scheduler task in a real user context。但是,需要注意的是,我需要等待此任务完成,然后才能启动 program.exe。
因此,我的问题是:如何等待任务计划程序任务在批处理文件中完成?
或者,我可以将批处理文件中的两个调用以菊花链形式连接到单个任务计划程序任务中(任务计划程序在单个任务中支持多达 16 个顺序事件 [需要引用])。
但是,如果我采用这种方法,我的批处理文件将在任务计划后立即终止,而不是在它完成后立即终止。不幸的是,我必须等待它完成,然后才能在我的 Worker Role 中执行任何逻辑。但是,如果我可以检查任务计划程序任务是否已从 C# 完成(没有管理员权限),那么我可以在那里等待。
因此,第二个可行的答案是以下问题:如何检查任务计划程序任务是否已从 C# 完成?
编辑:我想我会稍微澄清一下 MC ND 的以下答案:
从高层来看,这个命令检查任务是否正在运行,如果是,它就休眠并循环。
:loop
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn yourTaskName /fo list ^| find "Status:"' ) do (
if "%%f"=="Running" (
ping -n 6 localhost >nul 2>nul
goto loop
)
)
调用schtasks /query /tn yourTaskName /fo list
输出如下内容:
Folder: \
HostName: 1234567890
TaskName: \yourTaskName
Next Run Time: 11/27/2030 11:40:00 PM
Status: Ready
Logon Mode: Interactive/Background
for 命令循环输出中的每一行。每行使用分隔符“:”分成两个标记。如果找到以“Status”开头的行,则该行中分隔符之后的标记将存储在变量 f 中(在上面的示例输出中为“Ready”)。
然后检查变量 f 以查看它是否与状态“正在运行”匹配。如果状态不是“正在运行”,则假定任务已完成或失败,并且循环退出。如果状态为“正在运行”,则任务仍在运行,批处理脚本会暂停一小段时间,然后再次检查。这是通过发出 ping 调用来完成的,因为批处理没有睡眠命令。一旦脚本完成睡眠,它就会重新启动这个序列。
【问题讨论】:
【参考方案1】:从批处理文件中,查询任务状态,如果正在运行,继续查询
:loop
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn yourTaskName /fo list ^| find "Status:"' ) do (
if "%%f"=="Running" (
ping -n 6 localhost >nul 2>nul
goto loop
)
)
【讨论】:
像魅力一样工作。虽然我交换了:ping -n 1 -w 1000 192.0.2.2 >nul 2>nul
作为我的暂停命令。我觉得以这种方式进行调试以确保其正常工作会更容易一些。
我经常收到“错误:无效的参数/选项 - 'list'。输入“SCHTASKS /QUERY /?”以了解用法。”循环内。但是,当我在 shell 中手动执行 for chek(没有 ^)时,它可以工作。知道如何摆脱它吗?【参考方案2】:
您还可以使用timeout
来摆脱hacky ping -n 命令。
这是 MC ND 的答案timeout
。示例中的1
代表1 秒。
:loop
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn yourTaskName /fo list ^| find "Status:"' ) do (
if "%%f"=="Running" (
timeout /T 1 /NOBREAK > nul
goto loop
)
)
【讨论】:
【参考方案3】:谢谢!确认在 Windows 10 cmd 文件上工作。创建多个aysnc任务并将它们同步备份的非常有用的方法。例如,并行 chkdsk 多个驱动器并等待所有作业完成:
C:\Windows\System32\schtasks.exe /RUN /TN "chkdsk_G"
C:\Windows\System32\schtasks.exe /RUN /TN "chkdsk_H"
:loop
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn chkdsk_G /fo list ^| find "Status:"' ) do (
if "%%f"=="Running" (
ping -n 60 localhost >nul 2>nul
goto loop
)
)
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn chkdsk_H /fo list ^| find "Status:"' ) do (
if "%%f"=="Running" (
ping -n 60 localhost >nul 2>nul
goto loop
)
)
:both jobs are now complete
【讨论】:
以上是关于您如何等待任务计划程序任务在批处理文件或 C# 中完成?的主要内容,如果未能解决你的问题,请参考以下文章