PowerShell batch script Timeout ERROR: Input redirection is not supported, exiting the process immediately
Asked Answered
P

3

9

I need to have a timeout in powershell code where I'm running batch file, in case the batch file runs for a longer time or gets stuck. I also have a timeout in the batch script timeout 300> nul from which I seem to be getting this error and it is just skipping through the timeout and executing next lines. I do not get this error if I remove the timeout from batch script. But I need timeouts at both places, how do I resolve this ? Error- ERROR: Input redirection is not supported, exiting the process immediately.

PS Code-

$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

batch script is something like this

cmd1
cmd2
timeout 300> nul
cmd3
Pulsation answered 18/12, 2022 at 16:35 Comment(4)
First of all you should use %SystemRoot%\System32\timeout.exe /T 300 /NoBreak 1>NUL. Second, it would certainly help if you actually show us the commands you've replaced with cmd1, cmd2 and cmd3. Additionally I do not understand why you're changing directory using the cd alias as opposed to Set-Location or one of its less confusing aliases, sl, for instance.Meant
It is likely that at least cmd2 would need to be start "" "cmd2" or similar.Meant
@Meant actually I will be modifying this to run a remote conputer so I used cd to navigate to the dir, I will check out Set-Location. The command in batch script are for service restarting and killing some tasks so I am putting a timeout in between the steps.Pulsation
As an aside: There's no need to use cmd /c in order to execute a batch file - simply invoke it directly, though note that PowerShell - by security-minded design - requires prefix .\ in order to execute a batch file in the current directory, in order to signal the intent to target an executable there explicitly. Thus, replace cmd.exe /c "mybatchfile.bat" with .\mybatchfile.batVivi
V
5
  • Whenever timeout.exe detects that its stdin input stream is redirected (not attached to a console), it aborts with the error message you saw.

  • Because of how background jobs launched with Start-Job are implemented, whatever child processes you run from the job's script block invariably see stdin as redirected, so you won't be able to call timeout.exe directly.[1]

There are two workarounds:

  • Call timeout.exe via cmd.exe's internal start command:

    • However, this requires calling start without /B in order to execute the timeout.exe in a new window, whose stdin input by definition isn't redirected.

    • In turn, because start lacks a way to hide such a window, the closest you can come is to use /MIN in order to minimize it; a minimal example:

      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
      
  • Preferably, use thread-based background jobs, where this problem doesn't arise:

    • Start-ThreadJob runs your script block in a separate thread in the same process, and stdin redirection isn't involved; also, because no new PowerShell (child) process must be started, thread jobs are faster to create and require fewer resources.

      • Start-ThreadJob is part of the ThreadJob module, which comes with PowerShell (Core) 7+, and can be installed on demand in Windows PowerShell (e.g., with Install-Module -Scope CurrentUser ThreadJob)
    • Since Start-ThreadJob also integrates with PowerShell's job-management infrastructure and shares the core parameter syntax with Start-Job, all that should be necessary is to replace Start-Job with Start-ThreadJob in your code.


[1] Unless there is a way to reattach stdin to the console in a timeout.exe call - I'm not aware of such a feature, however (<CON creates an Access denied error).

Vivi answered 18/12, 2022 at 19:52 Comment(2)
Mixing Start-ThreadJob with timeout seems like it could be redundant in a world that has Wait-Event?Junto
@RussellHorwood: The premise of the question that a preexisting batch file that happens to contain a timeout.exe call must be run from a PowerShell job. You're thinking of a different, possibly complementary use case, where you wait a fixed amount of time outside of the job (as also shown in the question).Vivi
C
3

You might be interested to add a delay in another way. One alternative is to wait with:

REM # waits a delay before refresh status of service
ping localhost

Indeed I had similar remote PowerShell issue in a scenario with a GitLab agent install script on remote server. By replacing timeout with ping, the script does not finish anymore with an error.

Candi answered 9/1, 2023 at 8:52 Comment(2)
So how do you control the length of this delay? Note that the initial post tries to use 300 seconds - i.e. 5 minutes. By contrast, it looks like your solution is hard-coded to 3 seconds (plus change), due to ping.exe defaulting to 4 tries.Vivi
You can add parameters to ping to retry, number of count maybe - n 300Bemba
A
0

ping localhost works great but that is still 4 seconds

Just pipeline after:

powershell.exe -command "Start-Sleep 2" | [cmd script]

also try:

TIMEOUT /T [NUMBER] & [cmd script]

makes it more specific with time :-)

Aundrea answered 11/8, 2024 at 12:54 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Acrodrome

© 2022 - 2025 — McMap. All rights reserved.