PowerShell批处理脚本超时错误:不支持输入重定向,立即退出进程

HAH*_*HAH 5 powershell batch-file

我需要在运行批处理文件的 powershell 代码中设置超时,以防批处理文件运行较长时间或卡住。我在批处理脚本中也有一个超时timeout 300> nul,我似乎从中收到此错误,它只是跳过超时并执行下一行。如果我从批处理脚本中删除超时,则不会收到此错误。但我在两个地方都需要超时,我该如何解决这个问题?错误- ERROR:不支持输入重定向,立即退出进程。

PS代码-

$bs={
cd D:\files\ 
cmd.exe /c "mybatchfile.bat"
}
$timeoutseconds=800
$j=Start-Job -Scriptblock $bs
if(wait-Job $j -Timeout $timeoutseconds) {Receive-Job $j}
Remove-Job -force $j
Run Code Online (Sandbox Code Playgroud)

批处理脚本是这样的

cmd1
cmd2
timeout 300> nul
cmd3
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 3

  • 每当timeout.exe检测到其stdin输入流被重定向(未附加到控制台)时,它都会中止s并显示您看到的错误消息。

  • 由于后台作业启动的Start-Job实现方式,您从作业脚本块运行的任何子进程总是将 stdin 视为重定向,因此您将无法timeout.exe 直接调用。[1]

有两种解决方法

  • timeout.exe通过cmd.exe内部start命令调用

    • 但是,这需要调用start without /B才能timeout.exe新窗口中执行,根据定义,该窗口的标准输入输入不会被重定向。

    • 反过来,由于缺乏隐藏start此类窗口的方法,因此您可以使用的最接近方法是将其最小化;一个最小的例子:/MIN

      Start-Job {
        # Simulate calling a batch file (cmd /c)
        # inside of which the `start` call is made,
        # waiting for 5 seconds in this example.
        cmd /c start /min timeout.exe 5
      } | Receive-Job -Wait -AutoRemoveJob
      
      Run Code Online (Sandbox Code Playgroud)
  • 最好使用基于线程的后台作业,这样就不会出现此问题

    • Start-ThreadJob在同一进程的单独线程中运行脚本块,并且不涉及 stdin 重定向;此外,由于无需启动新的 PowerShell(子)进程,因此线程作业的创建速度更快,并且需要的资源更少。

      • Start-ThreadJobThreadJob是模块的一部分, PowerShell (Core) 7+一起提供,并且可以在Windows PowerShell中按需安装(例如,使用)Install-Module -Scope CurrentUser ThreadJob
    • 由于Start-ThreadJob还与 PowerShell 的作业管理基础架构集成并与 共享核心参数语法Start-Job,因此所需要做的就是在代码中替换Start-Job为。Start-ThreadJob


[1] 除非有办法在调用中将标准输入重新连接到控制台timeout.exe- 但是我不知道有这样的功能(<CON会产生Access denied错误)。