Unable to resume a workflow via task scheduler - powershell

In a powershell window I run the following workflow:
workflow foo { Suspend-Workflow; "hello world" | Out-File c:\users\weijgerss\desktop\foo.txt }
Then to resume the workflow, I have the following scheduled via task scheduler triggered to run at startup:
Import-Module PSWorkflow
$jobs = Get-Job -state Suspended
$jobs > c:\users\weijgerss\desktop\zqqfff.txt
$resumedJobs = $jobs | resume-job -wait
$resumedJobs | wait-job
# Task scheduler action: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Normal -NoLogo -NoProfile -Command "&'c:\users\weijgerss\desktop\resume.ps1'"
The workflow does not get resumed neither at startup, nor if I manually trigger it via Task Scheduler. The contents of zqqfff.txt indicates that the task scheduler activated powershell cannot see the workflow. A regular powershell window can see the workflow when I run Get-Job.
(Both the normal powershell window and the task scheduler powershell instance run as same user.)
I used procmon to see what's going on and I can see from this that when powershell normally vs taskscheduler it's looking at different workflow persistence paths, namely:
C:\Users\weijgerss\AppData\Local\microsoft\windows\PowerShell\WF\PS\default\S-1-5-21-3519956147-933941082-741972881-500_EL (a normal powershell window uses this folder)
C:\Users\weijgerss\AppData\Local\microsoft\windows\PowerShell\WF\PS\default\S-1-5-21-3519956147-933941082-741972881-500_EL_NI (a task scheduler activated powershell instance uses this folder)
I'm totally stumped. How can I get a task scheduler activated powershell instance to see the same workflows as normal powershell window can?

The below scripts give you a solution that automatically resumes powershell workflows after a reboot/crash using task scheduler at system start up:
resume-workflows.ps1: (the first line below fixes the _NI issue mentioned in the question)
[System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager = $true
Import-Module PSWorkflow
Get-Job -State Suspended | Resume-Job -Wait| Wait-Job
resume-workflows.cmd: (works around a windows 8/server 2012 task scheduler bug)
#rem This is a workaround for task scheduler bug
#rem See: http://support.microsoft.com/kb/2968540
set "USERPROFILE=%USERPROFILE%\..\%USERNAME%"
set "APPDATA=%USERPROFILE%\AppData\Roaming"
set "LOCALAPPDATA=%USERPROFILE%\AppData\Local"
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NonInteractive -WindowStyle Normal -NoLogo -NoProfile -Command "&'c:\path\to\resume-workflows.ps1'"
To put it all together use the following powershell script to shedule resume-workflows.cmd to run at system start up:
$trigger = New-ScheduledTaskTrigger -AtStartup
$action = New-ScheduledTaskAction -Execute "c:\path\to\resume-workflows.cmd"
$currentuser = ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
Register-ScheduledTask -TaskName "Resume $($currentuser.Replace('\', '-'))'s Powershell Workflows" `
-Trigger $trigger -Action $action -RunLevel Highest -User $currentuser `
-Password (Read-Host "Enter password for $currentuser")
Enjoy!
(ILSpy, sysinternal's procmon, plenty of google and a dash of windbg were all instrumental in bringing the above answer to you)

Related

Powershell scheduled script is not running properly

I have a short Powershell script which backup desktop items to D drive
$now = [datetime]::now.ToString('yyyy-MM-dd')
$trigger=new-scheduledtasktrigger -daily -at("08:00am")
$action = new-scheduledtaskaction 'copy "C:\USERS\ADMIN\DESKTOP" "D:\$now" -recurse'
Register-scheduledtask -Action $action -Trigger $trigger -Taskname "dailybackup" -Description "Daily backup"
The code seems valid and scheduled is registered well in scheduler
Get-scheduledtask "dailybackup"
But the task havent executed once but dont know why
anyone knows the solution?
New-ScheduledTaskAction executes commands in the old CMD shell by default. The command you're running doesn't error out because COPY is an ancient CMD built-in. It doesn't actually have the ability to recurse though, so it's not what you want.
To run powershell commands, the task action should execute PowerShell.exe, then have the powershell commands themselves added as arguments like below.
It looks like you want to use the run time date as the folder name $now, so you'll need to re-calculate the date every time it runs,
I also suggest adding -Force to create the target directory as needed,
I'm using here-string formatting #' '# to make quotes and things simpler to handle:
$Action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument #'
-Command Copy-Item -Recurse -Force -Path 'C:\USERS\ADMIN\DESKTOP' -Destination "D:\$([datetime]::Now.ToString('yyyy-MM-dd'))"
'#

Is there a way for powershell to get the output from a console app and save it in a text file? [duplicate]

I have a Java program which I would like to launch as a background process from a PowerShell script, similar to the way a daemon runs on Linux. The PowerShell script needs to do a couple of things:
Run the program as a separate and detached process in the background, meaning the parent window can be closed and the process keeps running.
Redirect the program's standard output and standard error to files.
Save the PID of the background process to a file so it can be terminated later by another script.
I have a shell script on Linux which starts the program like so:
$ java -jar MyProgram.jar >console.out 2>console.err &
I'm hoping to replicate the same behavior on Windows using a PowerShell script. I have tried using Start-Process with various combinations of options, as well as creating System.Diagnostics.ProcessStartInfo and System.Diagnostics.Process objects, but so far I am not having any luck. PowerShell starts the program as a background process, but the program abruptly terminates when the DOS window which started the PowerShell session is closed. I would like it to start in the background and be independent of the command window which started it.
The output redirection has also been troublesome, as it seems that the output and error streams can only be redirected in the process is being run in the same window (e.g., using -NoNewWindow).
Is this sort of thing possible in PowerShell?
Use jobs for this:
Start-Job -ScriptBlock {
& java -jar MyProgram.jar >console.out 2>console.err
}
Another option would be Start-Process:
Start-Process java -ArgumentList '-jar', 'MyProgram.jar' `
-RedirectStandardOutput '.\console.out' -RedirectStandardError '.\console.err'
Consider using the task scheduler for this. Define a task and set it without any triggers. That will allow you to simply "Run" (manually trigger) the task.
You can set up and/or trigger scheduled tasks using the ScheduledTasks powershell module, or you can use the GUI.
This is an old post but since I have it working fine thought it might help to share. Its the call to 'java' instead of 'javaw' that is likely your issue. Ran it out myself using my JEdit java program through powershell to launch it.
#Requires -Version 3.0
$MyDriveRoot = (Get-Location).Drive.Root
$JEditDir = $($mydriveroot + "jEdit") ;# Should be C:\jEdit or wherever you want. JEdit is a sub-directory.
$jEdit = $($JEditDir + "\jedit.jar" )
$jEditSettings = $($JEditDir + "\settings")
$JEditLogs = $($JEditDir + "\logs")
Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$JEditSettings"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"
Which you can turn into a little function and then an alias to make it easy to launch in Powershell.
If ( ( Test-Path $jedit) ) {
Function Start-JEdit() {
Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$($mydriveroot + "jEdit\settings")"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"
}
New-Alias -Name jedit -Force Start-JEdit -Description "Start JEdit programmers text editor"
}
Try this with PowerShell:
Start-Process cmd -Args /c,"java -jar MyProgram.jar" `
-WindowStyle Hidden -RSI console.out -RSE console.err
OR
Start-Process cmd -Args /c,"java -jar MyProgram.jar >console.out 2>console.err" `
-WindowStyle Hidden
This will start a detached cmd window that is hidden, and will redirect the std streams accordingly.
Old question, but since I had the same goal, I used answer from #use to acheive it.
So here is my code :)
$NAME_TASK = "myTask"
$NAME_TASKPATH = "\myPath\"
if ($args[0] -eq "-task") {
# Code to be run "detached" here...
Unregister-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Confirm:$False
Exit
}
$Task = (Get-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -ErrorAction 'SilentlyContinue')
if ($Task) {
Write-Host "ERR: Task already in progress"
Exit 1
}
$A = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy bypass -NoProfile -Command ""$PSCommandPath -task $args"""
Register-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Action $A | Start-ScheduledTask
The solution is to combine Start-Process with nohup:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-7.3#example-9-create-a-detached-process-on-linux
(Note: This is NOT for Windows.)

Powershell Script started by Task Scheduler not working

So I´ve got a powershell script that checks if a folder was created in a specific directory and then does stuff with that folder
Code:
echo "$(Get-Date -Format g) - Script started" >> C:\bitlocker.log
$folder = 'C:\Path\To\Check'
$filter = '*.*'
$fsw = New-Object IO.FileSystemWatcher $folder, $filter
$fsw.IncludeSubdirectories = $false
$fsw.NotifyFilter = [IO.NotifyFilters]'DirectoryName'
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
$folderNow = $($EventArgs.FullPath)
<do stuff now>
}
Starting this script manually works perfect but running it with the Task Scheduler is not working.
First I tried starting the script directly which shows that the script was successfully started but nothing that happens -Action { ... } gets executed.
I then tried to make a batch that starts the powershell script which gets started by the Task (as suggested here How to run a PowerShell script from a batch file)
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""C:\PathtoScript\Script.ps1""' -Verb RunAs}"
but the problem still is the same.
The script starts (Wrote some Output to a file to check that) but nothing inside -Action { ... } gets executed.
Edit: Task Schedular is set to run the script as a user with admin privileges as the actions that do not work need those, writing to C:\ works perfectly fine
Scheduled task action:
Program Script (Use the full path):
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Add arguments ([NOT]optional):
-NoProfile -NonInteractive -ExecutionPolicy Bypass -File "C:\PathtoScript\Script.ps1" -Any 'other' -arguments 'you need' -should follow
Ok I found my mistake
As #PetSerAl suggested I forgot that the FileSystemWatcher Acts only in scope of that one specific process of the script. The Script has started the Job successfully but after closing the process of the script (aka. the window I started the script in) the Job broke down because it could not refer to FileSystemWatcher anymore.
Adding something simple like:
Do{
$JobExist = Get-Job
} while($JobExist -ne '')
worked perfectly fine

How do I execute a PowerShell script automatically using Windows task scheduler?

I have one PowerShell script which sends emails. I want to execute that script automatically, every 1 minute. How can I do it, using task scheduler?
Currently I have created a task and provided the path of my script. But that scheduler opens my script, instead of executing.
I am using Windows 7 Professional and PowerShell version 2.0.5.
Create the scheduled task and set the action to:
Program/Script: Powershell.exe
Arguments: -File "C:\Users\MyUser\Documents\ThisisMyFile.ps1"
Here is an example using PowerShell 3.0 or 4.0 for -RepeatIndefinitely and up:
# Trigger
$middayTrigger = New-JobTrigger -Daily -At "12:40 AM"
$midNightTrigger = New-JobTrigger -Daily -At "12:00 PM"
$atStartupeveryFiveMinutesTrigger = New-JobTrigger -once -At $(get-date) -RepetitionInterval $([timespan]::FromMinutes("1")) -RepeatIndefinitely
# Options
$option1 = New-ScheduledJobOption –StartIfIdle
$scriptPath1 = 'C:\Path and file name 1.PS1'
$scriptPath2 = "C:\Path and file name 2.PS1"
Register-ScheduledJob -Name ResetProdCache -FilePath $scriptPath1 -Trigger $middayTrigger,$midNightTrigger -ScheduledJobOption $option1
Register-ScheduledJob -Name TestProdPing -FilePath $scriptPath2 -Trigger $atStartupeveryFiveMinutesTrigger
Instead of only using the path to your script in the task scheduler, you should start PowerShell with your script in the task scheduler, e.g.
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NonInteractive -File "C:\Path\To\Your\PS1File.ps1"
See powershell /? for an explanation of those switches.
If you still get problems you should read this question.
In my case, my script has parameters, so I set:
Arguments: -Command "& C:\scripts\myscript.ps1 myParam1 myParam2"
After several hours of test and research over the Internet, I've finally found how to start my PowerShell script with task scheduler, thanks to the
video Scheduling a PowerShell Script using Windows Task Scheduler by Jack Fruh #sharepointjack.
Program/script -> put full path through powershell.exe
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe
Add arguments -> Full path to the script, and the script, without any " ".
Start in (optional) -> The directory where your script resides, without any " ".
You can use the Unblock-File cmdlet to unblock the execution of this specific script. This prevents you doing any permanent policy changes which you may not want due to security concerns.
Unblock-File path_to_your_script
Source: Unblock-File
None of posted solutions worked for me.
Workaround, which worked:
create a run.bat and put inside
powershell.exe -file "C:\...\script.ps1"
then set Action to Program/Script: "C:\...\run.bat"

running powershell scripts as scheduled tasks

I got a couple of scripts which perform mailboxes moves to the cloud on office 365. The scripts sometimes fails and others not, I don't have any clue on why it
fails but I guess it is because the service is not available when the task is executed, anyways, the point is that these scripts are running as scheduled tasks and one must be
executed before of other, how I could detect if the first tasks failed and if so then reschedule the second task.
The tasks are running powershell v2 cmdlets on windows 2008 r2 so I'm using Task Scheduler.
I wonder if I should save some entries into a text file, to use a different task scheduler or maybe run each job using powershell, in the following way:
foreach ($script in $scripts)
{
#check status in a text file
$job = start-job -Filepath c:\myscript.ps1 -AsJob
Wait-Job $job -Timeout 180
}
What would be the best approach?
Thanks,
You can use schtasks.exe to query / enable or reschedule your tasks. Or you can use the COM object of the scheduler (beware schtasks output is language dependant). With one or other method check the lastTaskResult and reschedule or not your other task.
Examples:
Get all tasks of the root folder using COM object
icm -AsJob -JobName getTasks -ComputerName $computername -ScriptBlock{
$Schedule = new-object -com("Schedule.Service")
$Schedule.connect($env:computername)
$Tasks = $Schedule.getfolder("\").gettasks(0)
$Tasks | Select-Object Name,Path,State,Enabled,LastRunTime,LastTaskResult
}
Get a particular task with schtasks
schtasks /query /TN "\Microsoft\Windows\Autochk\Proxy" /v /fo csv |ConvertFrom-Csv