Hey, Scripting Guy! How Can I List and Delete Scheduled Jobs?

Hey, Scripting Guy! How Can I List and Delete Scheduled Jobs?

  • Comments 1
  • Likes

Hey, Scripting Guy! Question

Hey, Scripting Guy! We had this guy a while back who went around and created all kinds of goofy scheduled tasks using the AT command. He did not document anything, and many of the scheduled jobs do not work anyway. And we are not sure what the ones that do work are supposed to do. Needless to say, that clueless individual is no longer with us, but we are stuck with the aftermath. I need a way to be able to remotely list and delete scheduled jobs from our computers.

- AF

SpacerHey, Scripting Guy! Answer

Hi AF,

Wait a minute. It's Susie Q by the Rolling Stones on our Zune. We like their 1964 version much better than the one covered by CCR. At less than 2 minutes in length (compared to the marathon version recorded by CCR), the Stones version appears like a melodic sprint that quickly fades, leaving you wanting more. It was so popular; they recorded an additional version a year later. I saw the Stones at Olympic Stadium in Munich a couple years ago. I was there working with premier customers on Windows PowerShell and my host happened to get some tickets. It was a completely different experience than when I saw them in Cleveland, Ohio, USA (Cleveland Rocks!). So…you want to be able to list and to delete scheduled tasks? How about the DeleteScheduledTask.ps1 script?

This week we are talking about scheduled tasks. There are at least three different ways that you can work with scheduled tasks. This “Hey, Scripting Guy!” article provides an example of working with scheduled tasks via WMI. This script lists scheduled tasks created via WMI. We also have a variety of scheduled task scripts from the Community-Submitted Scripts Center. The Schedule.Service API is discussed in two articles. The first article talks about creating a task and setting the trigger. The second article discusses organizing tasks. This article discusses executing scheduled tasks via the Schedule.Service API. And the task scheduler is documented on MSDN.

The DeleteScheduledTask.ps1 script can be used to list all scheduled jobs on a local or remote computer. It is limited to scheduled jobs that were created via WMI or via the AT command. This is the legacy job scheduler. The DeleteScheduledTask.ps1 script is seen here (see also a VBScript version of this script):

param(
      $computer=$env:computername,
      $jobID,
      [switch]$list,
      [switch]$help
      ) #end param

# Begin Functions

function Help()
{
 $descriptionText= `
@"
 NAME: DeleteScheduledTask.ps1
 DESCRIPTION:
 Deletes a scheduled task on a local or remote machine. 
 NOTE: this script must run with administrator rights

 PARAMETERS: 
 -computer computer upon which to run the command
 -jobID the scheduled job or jobs id to delete
 -list produces a list of jobID and commands
 -help prints help description and parameters file

"@ #end descriptionText

$examplesText= `
@"

 SYNTAX:
 DeleteScheduledTask.ps1 

 Displays an error missing parameter, and calls help

 DeleteScheduledTask.ps1 -list

 Displays a list of jobID's and their associated command

 DeleteScheduledTask.ps1 -computer "Berlin" -jobID 2

 Deletes jobID 2 on a remote computer named Berlin 

 DeleteScheduledTask.ps1 -jobID 2,3

 Deletes jobID 2 and jobID 3 on the local computer

 DeleteScheduledTask.ps1 -help

 Prints the help topic for the script

"@ #end examplesText

  $descriptionText; $examplesText
} #end funHelp function



Function listJob()
{
 "Listing scheduled jobs on the $computer computer"
 $list = get-wmiobject -class win32_scheduledjob -computername $computer
 $convertTime = [wmiclass]"win32_scheduledjob"
 foreach($job in $list)
  {
   Format-table -inputobject $job -property jobID, command, jobstatus,
   @{ Label = "Start time" ; expression = { $convertTime.ConvertToDateTime($job.startTime)} } -autosize
  } 
} #end list

Function deleteJob()
{ 
 foreach($sJobID in $jobID)
  {
   "Deleting job ID $sJobID on $computer"
   $job = get-wmiobject -class win32_scheduledjob -computername $computer `
          -filter "jobID = $sjobID"
   $errRTN = $job.delete()
   $errRTN
  } #end foreach job
} #end deleteJob

# Entry Point

if($help)      { help ; exit}
if($list)      { listJob ; exit }
if($jobID)     { deleteJob }
if(!$jobID)    { "missing jobID" ; help ; exit}

We begin the script by defining the command-line parameters. These parameters are similar to the ones we discussed yesterday.

param(
      $computer=$env:computername,
      $jobID,
      [switch]$list,
      [switch]$help
      ) #end param

Now we create the help function. The help function begins with the function keyword and the name of the function. It then uses two here-strings to hold the text that is displayed when the script is run with the –help switch. This technique was discussed in depth yesterday, and therefore we will forgo an extended discussion today. The first here-string is used to hold the description of the script. This is seen here:

function Help()
{
 $descriptionText= `
@"
 NAME: DeleteScheduledTask.ps1
 DESCRIPTION:
 Deletes a scheduled task on a local or remote machine. 
 NOTE: this script must run with administrator rights
 PARAMETERS: 
 -computer computer upon which to run the command
 -jobID the scheduled job or jobs id to delete
 -list produces a list of jobID and commands
 -help prints help description and parameters file
"@ #end descriptionText

The second here-string is used to contain the examples of syntax use. It is important when creating the examples that you use examples that actually work on your system. This will make testing much easier in the future. Also, each parameter the script accepts should also be demonstrated in your examples. This is seen here:

$examplesText= `
@"
 SYNTAX:
 DeleteScheduledTask.ps1
 Displays an error missing parameter, and calls help
 DeleteScheduledTask.ps1 -list
 Displays a list of jobID's and their associated command
 DeleteScheduledTask.ps1 -computer "Berlin" -jobID 2
 Deletes jobID 2 on a remote computer named Berlin 
 DeleteScheduledTask.ps1 -jobID 2,3
 Deletes jobID 2 and jobID 3 on the local computer
 DeleteScheduledTask.ps1 -help
 Prints the help topic for the script
"@ #end examplesText

The last thing the help function does is print out both here-strings:

$descriptionText; $examplesText
} #end funHelp function

It is time to create the listJob function. We use the function keyword and supply the name of the function to do this. There are no input parameters required for this function. This is seen here:

Function listJob()
{

We first print out a message that we are listing the scheduled jobs on the computer name that is stored in the $computer variable:

"Listing scheduled jobs on the $computer computer"

We then use the Get-WmiObject cmdlet to query the Win32_ScheduledJob WMI class. (You can find additional WMI information on the WMI scripting hub.) We specify the computer we wish to connect to and store the resulting WMI object in the $list variable. This command is shown here:

$list = get-wmiobject -class win32_scheduledjob -computername $computer

We will need to be able to convert the time into something that is easier to read. The date value is returned as a UTC date time object. We can use the WbemScripting.SwbemDateTimeObject we may have used when working with VBScript, or we can use the ConvertToDateTime method that gets added to WMI classes in Windows PowerShell. This is much easier to use. To do this, we use the [wmiclass] type accelerator to retrieve a copy of the management class, and we store it in a variable named $convertTime:

$convertTime = [wmiclass]"win32_scheduledjob"

We use the ForEach statement to walk through the collection of scheduled job objects. Unlike VBScript, we can use ForEach to walk through a collection of one or more objects. VBScript will throw an error if a collection has only a single item in it. Inside the ForEach loop, we use the Format-Table cmdlet to format a nice output for our information:

ForEach($job in $list)
  {
   Format-table -inputobject $job -property jobID, command, jobstatus,

We want to change the way the Format-Table cmdlet displays information. This is where things get a bit complicated. To change the start time value that is displayed, we create a custom display for the table. We use a Windows PowerShell hash table to create a custom label and value for the table. The label we want to use is called "Start Time" and we want to calculate the expression by using the ConvertToDateTime method from the Win32_ScheduledJob WMI class:

@{ Label = "Start time" ; expression = { $convertTime.ConvertToDateTime($job.startTime)} } -autosize
  } 
} #end list

When we run the script, the scheduled jobs are displayed as shown here:

Image of the scheduled jobs

 

Next we need to create the DeleteJob function. The DeleteJob function begins by using the function keyword and the name of the function:

Function DeleteJob()
{

To make the script more useful, we accept an array of job IDs instead of only working with a single job ID. To do this, we use the ForEach statement. The collection of job IDs is stored in the $jobID variable, and inside the loop each individual job ID is known as $sJobID. This is seen here:

foreach($sJobID in $jobID)
  {

We now print out a status message to provide feedback to the user as to which job ID is being deleted on which computer:

"Deleting job ID $sJobID on $computer"

Now we use the Get-WmiObject cmdlet to retrieve the specific scheduled job that is represented by the job ID. The –filter parameter is used to return the specific scheduled job. As used here, it takes the place of the where clause normally used with the WMI Query Language (WQL):

$job = get-wmiobject -class win32_scheduledjob -computername $computer `
          -filter "jobID = $sjobID"

We then call the delete method. Just like any other method in Windows PowerShell, it must be followed by a set of parentheses:

$errRTN = $job.delete()
   $errRTN
  } #end foreach job
} #end deleteJob

When we call the script with a single job ID parameter, the scheduled job is deleted:

Image of the scheduled job being deleted

 

The command line that is used to delete the first scheduled job when the script is run is seen here:

DeleteScheduledTask.ps1 –JobID 1

If you need to delete multiple scheduled jobs, you can separate them by commas at the command line when you call the script. As seen in the previous example, you do not need to supply the entire parameter name if you do not wish to do so. You can use a partial parameter:

DeleteScheduledTask.ps1 –J 2,3

When we run the script, we are greeted with the output seen here:

Image of the script's output

 

Next it is time to evaluate the command-line parameters. If the script was run with the –help parameter, we call the help function and exit the script. If the script was called with the –list parameter, we call the listJob function and exit. If the –jobID parameter is present, we call the deleteJob function. If the –jobID parameter is not present and neither the –help nor the –list parameters are present, we print a message about a missing parameter and call the help function and exit. This section of the script is seen here:

if($help)      { help ; exit}
if($list)      { listJob ; exit }
if($jobID)     { deleteJob }
if(!$jobID)    { "missing jobID" ; help ; exit }

Well, AF, "They Call It Stormy Monday" by Elmore James playing now. I guess a classic blues song is appropriate for characterizing the feeling of sadness that overcomes us when we must bring the article to a conclusion. But cheer up, there is always tomorrow when Scheduled Tasks Week continues. Until then, take care.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Great idea. It runs as Administrator, but I get no output from the list (even though there are jobs there)