您如何等待任务计划程序任务在批处理文件或C#中完成?

时间:2013-11-28 09:01:01

标签: c# windows batch-file azure scheduled-tasks

我正在尝试编写一个包含两件事的批处理文件:

  1. 首先启动安装程序(install.exe),安装程序(program.exe)。
  2. 其次,它启动已安装程序的一个实例(program.exe)。必须在安装完成后执行此操作。
  3. 除了安装程序需要管理员权限并且必须在用户上下文中运行之外,这将是相对简单的。即使有这些限制,这仍然相对简单,除了我在Azure Worker Role上运行它,这意味着两件事:

    1. Elevated batch files must be run from a startup task.
    2. There is no user context for startup tasks in Azure worker roles.
    3. 因此,解决方案似乎是run the installer as a Task Scheduler task in a real user context。但是,这需要注意我需要在启动program.exe之前等待此任务完成。

      因此,我的问题是:我如何等待任务计划程序任务完成批处理文件?

      或者,我可以在单个任务计划程序任务中以菊花链方式链接我的批处理文件中的两个调用(任务计划程序在一个任务中最多支持16个连续事件[需要引证])。

      但是,如果我采用这种方法,我的批处理文件将在任务计划时立即终止,而不是在完成后立即终止。不幸的是,我必须等到它才能完成我的工作者角色中的任何逻辑。但是,如果我可以检查任务计划程序任务是否已完成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调用来完成的,因为批处理没有sleep命令。脚本完成睡眠后,它将重新启动此序列。

3 个答案:

答案 0 :(得分:10)

从批处理文件中查询任务状态,如果正在运行,请继续查询

: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
    )
)

答案 1 :(得分:4)

您还可以使用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
    )
)

答案 2 :(得分:0)

谢谢!确认在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