PowerShell Layered Script - Passing error codes for dependencies - powershell

I have started using a monitoring system called Cronitor that wraps scheduled task executions in their EXE.
Cronitor.exe exec (UID for monitor) "Path to script/executable".
Adding to that, I am working on synchronizing some of our scheduled tasks that are dependent on each other.
The problem I have is that because the executable wraps scripts/programs/tasks, the error code returned to Windows task scheduler is always 0 because it's not passed in their exe.
My work around is to layer powershell scripts (which I am not super proficient in yet).
So Action 1 calls "StartAction.ps1"
Inside that ps1 script,
Start-Process "Path to cronitor" -ArgumentList "Crontior arguments and path to ps1 that initiates exe for action 1" -Wait
Start-Process "Path to cronitor" -ArgumentList "Crontior arguments and path to ps1 that initiates exe for action 2"
The issue I am running into is the same for trying to stop the scheduled task if the process fails in action 1. I need to pass the error code (1) up through a pipeline to the initiating script so it knows to stop.
Is that even possible, or are there other solutions I am missing?

Related

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

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
Whenever timeout.exe detects that its stdin input 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 external processes you run from the job's script block invariably see stdin as redirected, so you won't be able to call timeout.exe.[1]
Your best bet is to 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).
you might be intersted 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 issue on remote powershell issue in a scenario where gitlab agent install script on remote server. by replacing timeout with ping the script do not finish anymore with an error.
My tech youtube channel in my profile

is there a wait parameter in PowerShell to allow the script to wait until a command is completed

I trying to install a software using Start-Process in PowerShell, I would like for the script to wait until a command is completed before proceeding to the next one. I'm not experienced I tired the script below but it did not work.
Start-Process -Wait -FilePath "C:\Temp\Latitude_5X10_Precision_3550_1.15.0.exe" -ArgumentList "/S" -PassThru
Your Start-Process call is correct, but -Wait invariably only tracks the lifetime of the directly launched process (C:\Temp\Latitude_5X10_Precision_3550_1.15.0.exe in your case).
That is, you're out of luck if the target process itself spawns yet another process in order to perform its task and then returns before that child process has terminated.
Additional work is then needed, if even feasible:
If you know the name of the child process, you can try to find and track it via Get-Process.
Alternatively, if you know of an indirect sign that the task has completed, such as the existence of a directory or a registry entry, look for that.
As an aside: console(-subsystem) applications can be invoked directly for synchronous (blocking) execution (e.g., foo.exe bar baz or & $fooExePath bar baz), which is the preferred method, because it connects the application's output streams to PowerShell's streams.

Powershell script triggers process only when invoked manually. Timing out when triggered via Scheduled Task

On a Windows 2012 R2 server there is a Powershell script that I can manually invoke to start a process on some EXE, this works just fine.
But when trying to trigger it via a scheduled task (invoking the same script) the start-process within the script just doesn't trigger or finish. Causing the task scheduler to terminate the task due to exceeding the timeout threshold.
Here's the core section of the script:
$exe = "c:\some\app.exe"
$arguments = "-user me -pwd secret"
$process = Start-Process $exe -ArgumentList $arguments -PassThru -Wait
return $process
Is there some way I can get some insights into what start-process is doing or why the same script works when invoked manually but not programmatically?
I want to emphasize that the way the script is invoked from the scheduled task is not a problem! The script triggers because the corresponding log file populates.
Any insights or help on this is greatly appreciated!
quick update on this since I found the problem. It turns out, it had nothing to do with either the powershell script or the scheduled task itself...
On the machine the script is running on, there is a network share that is mapped as the z:\ drive. I use it to save logs to. Now apparently that mapping/mounting is handled differently depending on whether the script is invoked interactively or programatically, because in the latter case it appears that the resoultion of the network path \\network\share\folder1 does not succeed, however there is nothing complaining about it, the process just silently does not start. If however, I point the logs to a physical local path or the explicit full network path itself, there is no problem running the script.
Lesson learned, never trust OS' drive mapping of network paths :D
Cheers

command line to wait for input and then process next step

I am writing a batch script to automate some processes.
this process runs a few different tools by stages, those tools creates the input necessary to run the next stage.
In one of the stages basically I open an .exe file and call a powershell file to simulate the "enter key" press, so far so good, it opens the tools and it starts to run run it, however what happens is that command line executes the next stage without waiting for the .exe file to finish, which is a important step thus that process creates the input for the next stage.
the command line I use is:
START /WAIT powershell -command .\bat.ps1
which runs this powershell script
[System.Diagnostics.Process]::Start("C:\folder\file.exe", "C:\temp\TestProject1\TestProject1.pjs /run /exit /SilentMode")
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
$wshell.SendKeys('~')
I would like to know if there is a workaround that makes me wait till the .exe file finish running, and then start the new stage.
thanks for your help
I found a workaround, that partially responds to my question.
I put the START /WAIT command after the powershell command, so while the .exe is running the next stage is on waiting, however I will have to press "y" to continue the process once the .exe file is finished, which is a start.
Thanks once again
Have you tried using the Start-Process cmdlet and including the -Wait parameter in lieu of a direct call to Start()?
From your powershell prompt try help start-process to see if some of the other parameters like -NoNewWindow would also be useful to you.

Automatically execute .cmd file requiring user input

We have a .cmd file we want to be able to execute automatically using Powershell (from TFS Release).
The issue with using start-process in Powershell is that execution gets stuck waiting for user input (Press any key to continue...).
Is there any way that we can pass variables to this call or call it in a different way where we no longer require user input for this .cmd?
Don't use Start-Process.
"`n" | & 'C:\path\to\your.cmd'
Powershell isn't getting stuck, Start-Process is working correctly - it's running the process (assume cmd.exe) and waiting for that process to terminate before continuing.
cmd.exe is prompting for interactive user input (PAUSE) before continuing, again working as you have instructed it to.
The issue is you're running non-interactively, and aren't providing the input required to continue.
You can update the cmd file and add an optional parameter so you can 'skip' the PAUSE when running unattended:
if "%1"=="unattended" goto skippause
pause
:skippause
then run it using unattended:
CMD /c c:\folder\file.cmd unattended