{"id":54073,"date":"2009-03-31T21:29:00","date_gmt":"2009-03-31T21:29:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/03\/31\/hey-scripting-guy-how-can-i-list-and-delete-scheduled-jobs\/"},"modified":"2009-03-31T21:29:00","modified_gmt":"2009-03-31T21:29:00","slug":"hey-scripting-guy-how-can-i-list-and-delete-scheduled-jobs","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-list-and-delete-scheduled-jobs\/","title":{"rendered":"Hey, Scripting Guy! How Can I List and Delete Scheduled Jobs?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> <\/H2>\n<P>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. <BR><BR>&#8211; AF<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hi AF,<\/P>\n<P>Wait a minute. It&#8217;s <A href=\"http:\/\/en.wikipedia.org\/wiki\/Susie_Q_(song)\" target=\"_blank\">Susie Q<\/A> by the Rolling Stones on our Zune. We like their 1964 version much better than the one covered by <A href=\"http:\/\/en.wikipedia.org\/wiki\/Creedence_Clearwater_Revival\" target=\"_blank\">CCR<\/A>. 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 <A href=\"http:\/\/en.wikipedia.org\/wiki\/Olympic_Stadium_%28Munich%29\" target=\"_blank\">Olympic Stadium in Munich<\/A> 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 <A href=\"http:\/\/en.wikipedia.org\/wiki\/Cleveland\" target=\"_blank\">Cleveland, Ohio, USA<\/A> (<A href=\"http:\/\/en.wikipedia.org\/wiki\/Cleveland_Rocks\" target=\"_blank\">Cleveland Rocks!<\/A>). So\u2026you want to be able to list and to delete scheduled tasks? How about the <B>DeleteScheduledTask.ps1<\/B> script?<\/P>\n<TABLE id=\"EPD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"class\">\n<P class=\"lastInCell\">This week we are talking about scheduled tasks. There are at least three different ways that you can work with scheduled tasks. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept04\/hey0922.mspx\" target=\"_blank\">This \u201cHey, Scripting Guy!\u201d article<\/A> provides an example of working with scheduled tasks via WMI. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/msh\/os\/tasks\/ostkms04.mspx\" target=\"_blank\">This script<\/A> lists scheduled tasks created via WMI. We also have <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/csc\/scripts\/os\/tasks\/index.mspx\" target=\"_blank\">a variety of scheduled task scripts<\/A> from the Community-Submitted Scripts Center. The <B>Schedule.Service<\/B> API is discussed in two articles. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/vista\/tasks1.mspx\" target=\"_blank\">first article<\/A> talks about creating a task and setting the trigger. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/vista\/tasks2.mspx\" target=\"_blank\">second article<\/A> discusses organizing tasks. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/aug07\/hey0830.mspx\" target=\"_blank\">This article<\/A> discusses executing scheduled tasks via the <B>Schedule.Service<\/B> API. And the task scheduler is documented <A href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa383614.aspx\" target=\"_blank\">on MSDN<\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>The <B>DeleteScheduledTask.ps1<\/B> 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 <B>DeleteScheduledTask.ps1<\/B> script is seen here (see also <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/os\/tasks\/ostkvb02.mspx\" target=\"_blank\">a VBScript version of this script<\/A>):<\/P><PRE class=\"codeSample\">param(\n      $computer=$env:computername,\n      $jobID,\n      [switch]$list,\n      [switch]$help\n      ) #end param<\/p>\n<p># Begin Functions<\/p>\n<p>function Help()\n{\n $descriptionText= `\n@&#8221;\n NAME: DeleteScheduledTask.ps1\n DESCRIPTION:\n Deletes a scheduled task on a local or remote machine. \n NOTE: this script must run with administrator rights<\/p>\n<p> PARAMETERS: \n -computer computer upon which to run the command\n -jobID the scheduled job or jobs id to delete\n -list produces a list of jobID and commands\n -help prints help description and parameters file<\/p>\n<p>&#8220;@ #end descriptionText<\/p>\n<p>$examplesText= `\n@&#8221;<\/p>\n<p> SYNTAX:\n DeleteScheduledTask.ps1 <\/p>\n<p> Displays an error missing parameter, and calls help<\/p>\n<p> DeleteScheduledTask.ps1 -list<\/p>\n<p> Displays a list of jobID&#8217;s and their associated command<\/p>\n<p> DeleteScheduledTask.ps1 -computer &#8220;Berlin&#8221; -jobID 2<\/p>\n<p> Deletes jobID 2 on a remote computer named Berlin <\/p>\n<p> DeleteScheduledTask.ps1 -jobID 2,3<\/p>\n<p> Deletes jobID 2 and jobID 3 on the local computer<\/p>\n<p> DeleteScheduledTask.ps1 -help<\/p>\n<p> Prints the help topic for the script<\/p>\n<p>&#8220;@ #end examplesText<\/p>\n<p>  $descriptionText; $examplesText\n} #end funHelp function<\/p>\n<p>Function listJob()\n{\n &#8220;Listing scheduled jobs on the $computer computer&#8221;\n $list = get-wmiobject -class win32_scheduledjob -computername $computer\n $convertTime = [wmiclass]&#8221;win32_scheduledjob&#8221;\n foreach($job in $list)\n  {\n   Format-table -inputobject $job -property jobID, command, jobstatus,\n   @{ Label = &#8220;Start time&#8221; ; expression = { $convertTime.ConvertToDateTime($job.startTime)} } -autosize\n  } \n} #end list<\/p>\n<p>Function deleteJob()\n{ \n foreach($sJobID in $jobID)\n  {\n   &#8220;Deleting job ID $sJobID on $computer&#8221;\n   $job = get-wmiobject -class win32_scheduledjob -computername $computer `\n          -filter &#8220;jobID = $sjobID&#8221;\n   $errRTN = $job.delete()\n   $errRTN\n  } #end foreach job\n} #end deleteJob<\/p>\n<p># Entry Point<\/p>\n<p>if($help)      { help ; exit}\nif($list)      { listJob ; exit }\nif($jobID)     { deleteJob }\nif(!$jobID)    { &#8220;missing jobID&#8221; ; help ; exit}\n<\/PRE>\n<P>We begin the script by defining the command-line parameters. These parameters are similar to the ones we discussed <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/mar09\/hey0330.mspx\" target=\"_blank\">yesterday<\/A>.<\/P><PRE class=\"codeSample\">param(\n      $computer=$env:computername,\n      $jobID,\n      [switch]$list,\n      [switch]$help\n      ) #end param\n<\/PRE>\n<P>Now we create the <B>help<\/B> function. The <B>help<\/B> function begins with the <B>function<\/B> keyword and the name of the function. It then uses two <B>here-strings<\/B> to hold the text that is displayed when the script is run with the <B>\u2013help<\/B> switch. This technique was discussed in depth yesterday, and therefore we will forgo an extended discussion today. The first <B>here-string<\/B> is used to hold the description of the script. This is seen here:<\/P><PRE class=\"codeSample\">function Help()\n{\n $descriptionText= `\n@&#8221;\n NAME: DeleteScheduledTask.ps1\n DESCRIPTION:\n Deletes a scheduled task on a local or remote machine. \n NOTE: this script must run with administrator rights\n PARAMETERS: \n -computer computer upon which to run the command\n -jobID the scheduled job or jobs id to delete\n -list produces a list of jobID and commands\n -help prints help description and parameters file\n&#8220;@ #end descriptionText\n<\/PRE>\n<P>The second <B>here-string<\/B> 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:<\/P><PRE class=\"codeSample\">$examplesText= `\n@&#8221;\n SYNTAX:\n DeleteScheduledTask.ps1\n Displays an error missing parameter, and calls help\n DeleteScheduledTask.ps1 -list\n Displays a list of jobID&#8217;s and their associated command\n DeleteScheduledTask.ps1 -computer &#8220;Berlin&#8221; -jobID 2\n Deletes jobID 2 on a remote computer named Berlin \n DeleteScheduledTask.ps1 -jobID 2,3\n Deletes jobID 2 and jobID 3 on the local computer\n DeleteScheduledTask.ps1 -help\n Prints the help topic for the script\n&#8220;@ #end examplesText\n<\/PRE>\n<P>The last thing the <B>help<\/B> function does is print out both <B>here-strings<\/B>: <\/P><PRE class=\"codeSample\">$descriptionText; $examplesText\n} #end funHelp function\n<\/PRE>\n<P>It is time to create the <B>listJob<\/B> function. We use the <B>function<\/B> keyword and supply the name of the function to do this. There are no input parameters required for this function. This is seen here:<\/P><PRE class=\"codeSample\">Function listJob()\n{\n<\/PRE>\n<P>We first print out a message that we are listing the scheduled jobs on the computer name that is stored in the <B>$computer<\/B> variable:<\/P><PRE class=\"codeSample\">&#8220;Listing scheduled jobs on the $computer computer&#8221;<\/PRE>\n<P>We then use the <B>Get-WmiObject<\/B> cmdlet to query the <B>Win32_ScheduledJob<\/B> WMI class. (You can find additional WMI information on the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/wmi.mspx\" target=\"_blank\">WMI scripting hub<\/A>.) We specify the computer we wish to connect to and store the resulting WMI object in the <B>$list<\/B> variable. This command is shown here:<\/P><PRE class=\"codeSample\">$list = get-wmiobject -class win32_scheduledjob -computername $computer<\/PRE>\n<P>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 <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/jul06\/hey0721.mspx\" target=\"_blank\">WbemScripting.SwbemDateTimeObject<\/A> we may have used when working with VBScript, or we can use the <B>ConvertToDateTime<\/B> method that gets added to WMI classes in Windows PowerShell. This is much easier to use. To do this, we use the <B>[wmiclass]<\/B> type accelerator to retrieve a copy of the management class, and we store it in a variable named <B>$convertTime<\/B>:<\/P><PRE class=\"codeSample\">$convertTime = [wmiclass]&#8221;win32_scheduledjob&#8221;<\/PRE>\n<P>We use the <B>ForEach<\/B> statement to walk through the collection of scheduled job objects. Unlike VBScript, we can use <B>ForEach<\/B> 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 <B>ForEach<\/B> loop, we use the <B>Format-Table<\/B> cmdlet to format a nice output for our information:<\/P><PRE class=\"codeSample\">ForEach($job in $list)\n  {\n   Format-table -inputobject $job -property jobID, command, jobstatus,\n<\/PRE>\n<P>We want to change the way the <B>Format-Table<\/B> 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 &#8220;Start Time&#8221; and we want to calculate the expression by using the <B>ConvertToDateTime<\/B> method from the <B>Win32_ScheduledJob<\/B> WMI class:<\/P><PRE class=\"codeSample\">@{ Label = &#8220;Start time&#8221; ; expression = { $convertTime.ConvertToDateTime($job.startTime)} } -autosize\n  } \n} #end list\n<\/PRE>\n<P>When we run the script, the scheduled jobs are displayed as shown here:<\/P><IMG border=\"0\" alt=\"Image of the scheduled jobs\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0331\/hsg-03-31-09-01.jpg\" width=\"500\" height=\"248\"> \n<P>&nbsp;<\/P>\n<P>Next we need to create the <B>DeleteJob<\/B> function. The <B>DeleteJob<\/B> function begins by using the <B>function<\/B> keyword and the name of the function:<\/P><PRE class=\"codeSample\">Function DeleteJob()\n{\n<\/PRE>\n<P>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 <B>ForEach<\/B> statement. The collection of job IDs is stored in the <B>$jobID<\/B> variable, and inside the loop each individual job ID is known as <B>$sJobID<\/B>. This is seen here:<\/P><PRE class=\"codeSample\">foreach($sJobID in $jobID)\n  {\n<\/PRE>\n<P>We now print out a status message to provide feedback to the user as to which job ID is being deleted on which computer:<\/P><PRE class=\"codeSample\">&#8220;Deleting job ID $sJobID on $computer&#8221;\n<\/PRE>\n<P>Now we use the <B>Get-WmiObject<\/B> cmdlet to retrieve the specific scheduled job that is represented by the job ID. The <B>\u2013filter<\/B> parameter is used to return the specific scheduled job. As used here, it takes the place of the <B>where<\/B> clause normally used with the WMI Query Language (WQL):<\/P><PRE class=\"codeSample\">$job = get-wmiobject -class win32_scheduledjob -computername $computer `\n          -filter &#8220;jobID = $sjobID&#8221;\n<\/PRE>\n<P>We then call the <B>delete<\/B> method. Just like any other method in Windows PowerShell, it must be followed by a set of parentheses:<\/P><PRE class=\"codeSample\">$errRTN = $job.delete()\n   $errRTN\n  } #end foreach job\n} #end deleteJob\n<\/PRE>\n<P>When we call the script with a single <B>job ID<\/B> parameter, the scheduled job is deleted:<\/P><IMG border=\"0\" alt=\"Image of the scheduled job being deleted\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0331\/hsg-03-31-09-02.jpg\" width=\"500\" height=\"95\"> \n<P>&nbsp;<\/P>\n<P>The command line that is used to delete the first scheduled job when the script is run is seen here:<\/P><PRE class=\"codeSample\">DeleteScheduledTask.ps1 \u2013JobID 1<\/PRE>\n<P>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:<\/P><PRE class=\"codeSample\">DeleteScheduledTask.ps1 \u2013J 2,3<\/PRE>\n<P>When we run the script, we are greeted with the output seen here:<\/P><IMG border=\"0\" alt=\"Image of the script's output\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0331\/hsg-03-31-09-03.jpg\" width=\"500\" height=\"104\"> \n<P>&nbsp;<\/P>\n<P>Next it is time to evaluate the command-line parameters. If the script was run with the <B>\u2013help<\/B> parameter, we call the <B>help<\/B> function and exit the script. If the script was called with the <B>\u2013list<\/B> parameter, we call the <B>listJob<\/B> function and exit. If the <B>\u2013jobID<\/B> parameter is present, we call the <B>deleteJob<\/B> function. If the <B>\u2013jobID<\/B> parameter is not present and neither the <B>\u2013help<\/B> nor the <B>\u2013list<\/B> parameters are present, we print a message about a missing parameter and call the <B>help<\/B> function and exit. This section of the script is seen here:<\/P><PRE class=\"codeSample\">if($help)      { help ; exit}\nif($list)      { listJob ; exit }\nif($jobID)     { deleteJob }\nif(!$jobID)    { &#8220;missing jobID&#8221; ; help ; exit }\n<\/PRE>\n<P>Well, AF, &#8220;They Call It Stormy Monday&#8221; by <A href=\"http:\/\/encarta.msn.com\/encyclopedia_762506052\/Elmore_James.html\" target=\"_blank\">Elmore James<\/A> 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.<\/P>\n<P>&nbsp;<\/P>\n<P><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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. [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,32,3,45],"class_list":["post-54073","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-operating-system","tag-scheduled-tasks","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>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. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54073","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54073"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54073\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54073"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54073"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54073"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}