SOLVED

Externally trigger a .ps1 to exit

%3CLINGO-SUB%20id%3D%22lingo-sub-3114371%22%20slang%3D%22en-US%22%3EExternally%20trigger%20a%20.ps1%20to%20exit%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3114371%22%20slang%3D%22en-US%22%3E%3CP%3EI'm%20running%20a%20.ps1%20from%20Task%20Scheduler.%20If%20I%20stop%20the%20script%20from%20the%20Task%20Scheduler%20console%20with%20the%20End%20command%2C%20does%20that%20generate%20an%20event%2Ftrigger%20that%20the%20script%20can%20react%20to%3F%20(I'd%20like%20the%20script%20to%20shut%20down%20gracefully.)%26nbsp%3B%20If%20I%20can't%20do%20that%20from%20the%20Task%20Scheduler%20console%2C%20is%20there%20another%20way%20to%20do%20it%3F%26nbsp%3B%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-3114371%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EPowerShell%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-3115771%22%20slang%3D%22en-US%22%3ERe%3A%20Externally%20trigger%20a%20.ps1%20to%20exit%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3115771%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F1296685%22%20target%3D%22_blank%22%3E%40Mark_Block%3C%2FA%3E%26nbsp%3B%3C%2FP%3E%3CP%3Ethe%20ps1%20that%20is%20stopped%20will%20exit%20with%20a%20non-success%20error%20but%20as%20you%20are%20not%20launching%20that%20script%20from%20a%20process%20that%20can%20handle%20that%20error%20code%20then%20you%20have%20no%20way%20to%20check%20the%20code%20and%20take%20any%20action.%20Also%2C%20you%20are%20ending%20the%20task%20and%20not%20the%20actual%20script%20itself%20so%20you%20don't%20have%20the%20separation%20needed%20-%20the%20task%20doesnt%20continue%20processing%20at%20all%20to%20handle%20the%20exit%20code.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3Eif%20you%20start%20a%20cmd%20session%20and%20then%20type%20%3CSTRONG%3Epowershell%3C%2FSTRONG%3E%20you%20will%20be%20running%20a%20powershell%20session%20in%20a%20command%20prompt%20session.%3C%2FP%3E%3CP%3EIf%20you%20now%20type%20%3CSTRONG%3Eexit%2020%3C%2FSTRONG%3E%20at%20the%20PS%26gt%3B%20prompt%20you%20will%20intentionally%20exit%20the%20powershell%20session%20with%20exit%20code%2020%20and%20revert%20to%20the%20command%20prompt%20session%3C%2FP%3E%3CP%3EAt%20the%20prompt%20run%20the%20command%20%3CSTRONG%3Eecho%20%25errorlevel%25%3C%2FSTRONG%3E.%20The%20result%20will%20be%2020%20-%20the%20powershell%20session%20exit%20value.%20You%20can%20consume%20this%20in%20whatever%20logic%20you%20have%20in%20the%20calling%20process...%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3Ethis%20value%20is%20passed%20between%20the%20sessions%20as%20the%20'inner'%20powershell%20session%20closed%20gracefully%20with%20an%20exit%20code.%20the%20same%20isnt%20true%20for%20when%20notepad.exe%20is%20closed%20with%20Stop-Process.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3Eeven%20if%20you%20have%20a%20cmd%2Fbat%20script%20launch%20your%20ps1%2C%20if%20you%20end%20the%20task%20then%20there%20is%20nothing%20running%20to%20handle%20any%20onward%20actions.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EI%20guess%20we%20have%20reached%20the%20point%20to%20ask%20what%20you%20are%20actually%20doing%20and%20trying%20to%20achieve%20so%20that%20we%20can%20provide%20a%20better%20option%20for%20you%20rather%20than%20proceed%20down%20the%20rabbit%20hole%20of%20process%20launching%20and%20exiting.%26nbsp%3B%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E
New Contributor

I'm running a .ps1 from Task Scheduler. If I stop the script from the Task Scheduler console with the End command, does that generate an event/trigger that the script can react to? (I'd like the script to shut down gracefully.)  If I can't do that from the Task Scheduler console, is there another way to do it?  

6 Replies

@Mark_Block 

the ps1 that is stopped will exit with a non-success error but as you are not launching that script from a process that can handle that error code then you have no way to check the code and take any action. Also, you are ending the task and not the actual script itself so you don't have the separation needed - the task doesnt continue processing at all to handle the exit code.

 

if you start a cmd session and then type powershell you will be running a powershell session in a command prompt session.

If you now type exit 20 at the PS> prompt you will intentionally exit the powershell session with exit code 20 and revert to the command prompt session

At the prompt run the command echo %errorlevel%. The result will be 20 - the powershell session exit value. You can consume this in whatever logic you have in the calling process...

 

this value is passed between the sessions as the 'inner' powershell session closed gracefully with an exit code. the same isnt true for when notepad.exe is closed with Stop-Process.

 

even if you have a cmd/bat script launch your ps1, if you end the task then there is nothing running to handle any onward actions.

 

I guess we have reached the point to ask what you are actually doing and trying to achieve so that we can provide a better option for you rather than proceed down the rabbit hole of process launching and exiting. 

 

@Jonathan_Allen 

 

Thanks for the quick response.  Here's more detail.

 

I have a script in a .ps1 file. I run PowerShell.exe from a scheduled task and provide the .ps1 as a PowerShell command-line argument. The script is moving files with Get-ChildItem | ForEach-Object and may run for days.  The script generates status messages via Write-Output. When the script has moved all the files, it provides a final message with stats and exits.  If we need to stop the script before all files are moved, we lose the final statistics. I considered a "brute force" semaphore such as creating a file that the script checks for that signals it to shut down. Is there a more elegant solution? Environment variable? Some other sort of system trigger?

 

I'm not married to running the script from the Task Scheduler. (I just need the script to run without a logged-in session.)  

 

Thanks in advance for you help.

@Mark_Block 

OK, some thoughts:
- You say the script 'may run for days' is this because there are lots of files or they are large files or you have slow network ... etc? Can you set the job to run for a fixed length of time and just trigger it more frequently? This way you know it will more often stop gracefully?
- You are using Write-Output to add updates to the session as (i assume) files are moved. Why not switch this to writing your progress to a static file with Add-Content?

$Date = "{0:yyyymmdd_HHmm}" -f (Get-Date)
$Logfile = "[MySecurePathLocation]\FileMoverJob\$Date`_Process.txt"

$Logfile
$Msg = "{0:yyyymmdd_HHmmss}`tProcess starting." -f (Get-Date)
$Msg | add-Content $Logfile

#[getchilditem loop I assume]

$Msg = "{0:yyyymmdd_HHmmss}`tMoving $ThisFile." -f (Get-Date)
$Msg | add-Content $Logfile

##end of loop

$Msg = "{0:yyyymmdd_HHmmss}`tProcess complete." -f (Get-Date)
$Msg | add-Content $Logfile

 This way if the process stops unexpectedly you will have a file with a log of what has been completed and the times it occurred...

It seems I'm explaining this badly. I'm not losing the output written by Write-Output. Also, running the script more frequently won't solve the problem. The problem is that the script doesn't know it's being shut down. (BTW, I solved the problem using an external semaphore file that the script checks but I'm still wondering if there's a more "elegant"). I'll try to explain again.

When the script is shut down by an external action, like hitting End from Task Scheduler, the script has no idea it's being shut down. I need a method that allows the script, from inside the script, to know it's being shut down.
best response confirmed by Mark_Block (New Contributor)
Solution
taking action within the script when an external action has stopped the scheduled job - no, this isnt possible.
OK. That was my conclusion as well. Thanks for your help.