Scheduling Jobs with the Windows PowerShell API
You can use the objects exposed by the N:Microsoft.PowerShell.ScheduledJob namespace to create a scheduled job, define when it runs, and get results about the completed job after it has run.
Triggering the Job
The first step in creating a scheduled job is specifying when the job should run. Do this by creating and configuring a T:Microsoft.PowerShell.ScheduledJob.ScheduledJobTrigger object. The following code creates a trigger that schedules a job to run a single time 20 seconds in the future.
ScheduledJobTrigger jobTrigger = ScheduledJobTrigger.CreateOnceTrigger(
DateTime.Now.AddSeconds(20), // Create trigger to start job 20 seconds after now.
TimeSpan.Zero, // No random delay
null, // No repetition interval time
null, // No repetition interval duration
1, // Trigger Id
true); // Create trigger enabled
Defining the Job
You define a Windows PowerShell job by creating a parameter dictionary. The following parameters are supported.
Parameter Name | Description |
---|---|
Name | The name of the job. |
ScriptBock | A Windows PowerShell script block that specifies what the job does. |
FilePath | A path to a file that contains Windows PowerShell script block that specifies what the job does. |
InitializationScript | A Windows PowerShell script block that initializes the job. |
ArgumentList | An array of objects that specify arguments that the job takes. |
RunAs32 | A boolean value that specifies whether to run the job in a 32-bit process. |
The following code creates a parameter dictionary object and sets the Name and ScriptBlock parameters.
string schedJobDefName = "MySampleSchedJob";
Dictionary<string, object> jobDefParameters = new Dictionary<string, object>();
jobDefParameters.Add("Name", schedJobDefName); // Unique name is required.
ScriptBlock scriptBlock = ScriptBlock.Create(@"1..5 | foreach {sleep 1; ""SchedJobOutput $_""}");
jobDefParameters.Add("ScriptBlock", scriptBlock); // A scriptblock or script FilePath
// is required.
Creating the Invocation and Job Definition Objects
You then create ScheduledJobInvocationInfo and ScheduledJobDefinition objects to run the job. The following code demonstrates this.
ScheduledJobInvocationInfo jobInvocationInfo = new ScheduledJobInvocationInfo(
nw JobDefinition(typeof(ScheduledJobSourceAdapter), scriptBlock.ToString(), schedJobDefName),
jobDefParameters);
schedJobDefinition = new ScheduledJobDefinition(
jobInvocationInfo, // Defines the PowerShell job to run.
new ScheduledJobTrigger[1] { jobTrigger }, // Defines when to run the PowerShell job.
null, // No custom options. We accept default.
null); // No credentials. PowerShell job is run
// in default Task Scheduler process, account.
Registering the Job with the Task Scheduler
The following code registers the job with the Windows Task Scheduler.
schedJobDefinition.Register();
registrationSucceeded = true;
Console.WriteLine("Scheduled job has been registered. Waiting 30 seconds for it to be started and run.");
Complete Code Example
The following is the complete code example from which the previous snippets were taken.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Management.Automation; // Windows PowerShell namespace.
using Microsoft.PowerShell.ScheduledJob; // Windows PowerShell ScheduledJob namespace.
namespace Microsoft.Samples.PowerShell.ScheduledJob
{
/// <summary>
/// This class contains the Main entry point for the application.
/// </summary>
public class ScheduledJobSample
{
/// <summary>
/// This sample shows how to use the PowerShell ScheduledJob API to create
/// a simple PowerShell scheduled job, register it with a trigger object
/// that defines when the job will run and retrieve job run results from
/// the job file store.
/// </summary>
/// <param name="args"></param>
public static void Main(string[] args)
{
// ScheduledJobDefinition contains all elements of a PowerShell scheduled
// job including the PowerShell job script or script file path, scheduling
// triggers, and scheduling options.
ScheduledJobDefinition schedJobDefinition = null;
bool registrationSucceeded = false;
try
{
// First create a scheduled job trigger object. This object will
// define when the PowerShell job is scheduled to run. For this
// example we will create a trigger to run the job just one time
// 20 seconds after the trigger object is created.
// Note: If you are stepping through this code in a debugger you
// may want to increase the 20 seconds value so that the trigger time
// remains in the future once you register the scheduled job.
ScheduledJobTrigger jobTrigger = ScheduledJobTrigger.CreateOnceTrigger(
DateTime.Now.AddSeconds(20), // Create trigger to start job 20 seconds after now.
TimeSpan.Zero, // No random delay
null, // No repetition interval time
null, // No repetition interval duration
1, // Trigger Id
true); // Create trigger enabled
// Create a parameter dictionary that defines the PowerShell job.
// For this example we will create a simple script that runs for
// 5 seconds generating output.
// Here are the parameters supported to define the PowerShell job.
// Name - Job name string.
// ScriptBlock - PowerShell ScriptBlock type.
// FilePath - PowerShell script file path string.
// InitializationScript - PowerShell Scriptblock type.
// ArgumentList - object[] type.
// RunAs32 - Switch (boolean type).
string schedJobDefName = "MySampleSchedJob";
Dictionary<string, object> jobDefParameters = new Dictionary<string, object>();
jobDefParameters.Add("Name", schedJobDefName); // Unique name is required.
ScriptBlock scriptBlock = ScriptBlock.Create(@"1..5 | foreach {sleep 1; ""SchedJobOutput $_""}");
jobDefParameters.Add("ScriptBlock", scriptBlock); // A scriptblock or script FilePath
// is required.
// Now create a JobInvocation object that contains all information about
// the PowerShell job to run.
ScheduledJobInvocationInfo jobInvocationInfo = new ScheduledJobInvocationInfo(
new JobDefinition(typeof(ScheduledJobSourceAdapter), scriptBlock.ToString(), schedJobDefName),
jobDefParameters);
// Finally create the scheduled job definition object that pulls all
// of this information together.
schedJobDefinition = new ScheduledJobDefinition(
jobInvocationInfo, // Defines the PowerShell job to run.
new ScheduledJobTrigger[1] { jobTrigger }, // Defines when to run the PowerShell job.
null, // No custom options. We accept default.
null); // No credentials. PowerShell job is run
// in default Task Scheduler process, account.
// Next we register this scheduled job object with Windows Task Scheduler.
// The Task Scheduler will run the PowerShell script based on the provided job trigger.
schedJobDefinition.Register();
registrationSucceeded = true;
Console.WriteLine("Scheduled job has been registered. Waiting 30 seconds for it to be started and run.");
// You can see this PowerShell job task registered in the Task Scheduler UI.
// Look under path: Task Scheduler Library\Microsoft\Windows\PowerShell\ScheduledJobs
// Wait for Task Scheduler to run the PowerShell job. This should happen in 20 seconds
// and then the job will take about 5 seconds to run. If PowerShell job task doesn't
// run try increasing the trigger time in the ScheduledJobTrigger object. You can also
// run this task manually from the Task Scheduler UI.
for (int count = 1; count < 31; ++count)
{
Thread.Sleep(1000);
Console.WriteLine(count + " seconds elapsed");
}
Console.WriteLine();
Console.WriteLine("Job run results.");
Console.WriteLine();
// Since the PowerShell job runs in a non-interactive Task Scheduler
// process the job status and output data is written to a file based
// job store and the directory location is the current user local app
// data ($env:LOCALAPPDATA).
// This job store can be accessed through the ScheduledJobSourceAdapter class.
ScheduledJobSourceAdapter schedJobSourceAdapter = new ScheduledJobSourceAdapter();
IList<Job2> jobRuns = schedJobSourceAdapter.GetJobs();
foreach (var jobRun in jobRuns)
{
// Check for jobs in finished state.
// Note that job data is not written to the job store until the job
// has reached a finished state.
JobState jobState = jobRun.JobStateInfo.State;
if (jobState == JobState.Completed ||
jobState == JobState.Stopped ||
jobState == JobState.Failed)
{
// Write job run finished state.
Console.WriteLine("Job Status: " + jobRun.JobStateInfo.State);
Console.WriteLine();
Console.WriteLine("Job Data");
// Write output data.
foreach (var item in jobRun.Output)
{
Console.WriteLine(item.ToString());
}
// Write any errors.
foreach (var item in jobRun.Error)
{
Console.WriteLine(item.ToString());
}
}
}
Console.WriteLine();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
catch (ScheduledJobException e)
{
Console.WriteLine("Error: " + e.Message);
}
finally
{
// Unregister this scheduled job or an error will be thrown when
// running this sample code again (scheduled job already exists.)
// because all registered scheduled jobs must have a unique name.
if (registrationSucceeded)
{
schedJobDefinition.Remove(true);
}
}
}
}
}