Downloads
140368.zip

The Task Scheduler service in Windows is a very useful automation tool. Starting with Windows Vista and Windows Server 2008, the Task Scheduler service got an overhaul. It has new trigger types, actions, and task folders. It also has a built-in scriptable object interface for managing scheduled tasks. (Microsoft provided a scriptable object interface for the Task Scheduler in earlier Windows versions, but it was a separate download.) Figure 1 shows the updated Task Scheduler window on a Windows 7 computer.

Figure 1: Windows 7 Task Scheduler
Figure 1: Windows 7 Task Scheduler

In Windows Server 2003, Windows XP, and Windows 2000, scheduled tasks are .job files found in the computer's \%SystemRoot%\Tasks folder. In these OS versions, renaming a task is easy: Press F2 when the task is highlighted in Windows Explorer or right-click the task in Task Scheduler and select Rename. In Windows 7, Vista, and Server 2008, Task Scheduler tasks are no longer stored as .job files in the Tasks folder, so you can’t rename a scheduled task after you create it.

I don't know the reasons for the omission of this seemingly simple feature, but there is a workaround: Export the task as an XML file, import the task to create a new task with the new name, then delete the old task. This seemed like an unnecessary amount of extra work, so I wrote a PowerShell script, Rename-ScheduledTask.ps1, to make renaming a task easier.

To download Rename-ScheduledTask.ps1, click the 140368.zip hotlink at the top of the article. The script works on only Windows 7, Vista, and Server 2008 for two reasons. First, this script isn’t needed in earlier OS versions. Second, the script object interface it uses isn't present in earlier OS versions. You can use the script to rename tasks on the local machine and remote computers. If you want to rename a task on the local computer, you must run the script from an elevated PowerShell window (i.e., right-click the PowerShell shortcut and choose Run as administrator). 

How to Use the Script

The script's command-line syntax is as follows:

Rename ScheduledTask

  [ TaskName]

  [ NewName]

  [ ComputerName ]

  [ ConnectionCredential ]

  [ TaskCredential ]

The only required parameters are -TaskName and -NewName, which you use to specify the task's current name and new name, respectively. Because the -TaskName and -NewName parameters must be the first and second parameters on the script's command line, including the parameters' names (-TaskName and -NewName) is optional.

The overhauled Task Scheduler service supports task folders. If you specify a task name without a task folder name, the script assumes the task is in the root tasks folder ("\"). You can relocate a task to a different task folder by specifying the task folder's name as a part of the task's new name. The task folder will be created if it doesn't exist. For example, the command

Rename ScheduledTask

  "My Task"

  "\User Tasks\User Task 1"

renames the task named \My Task to \User Tasks\User Task 1. The \User Tasks folder will be created if it doesn't exist.

You use the -ComputerName parameter to specify the computer where the task to be renamed is stored. You can't move tasks between computers, so the renamed task will also be stored on that computer. If you omit the -ComputerName parameter, the script assumes the task to be renamed is on the current computer.

The -ConnectionCredential parameter specifies a PSCredential object for connecting to the Task Scheduler service on the computer (which is the local computer if you omit the -ComputerName parameter). Note that Rename-ScheduledTask.ps1 renames a task by copying the original task to a new task, then deleting the original task. This means that if the original task has saved credentials, they can't be copied because credentials are stored securely. So, before you use the -ConnectionCredential parameter, you should check the task's properties to see whether the task has saved credentials. As Figure 2 shows, when the Run whether user is logged on or not option is selected and the Do not store password option isn't selected, the credentials are saved. Thus, the credentials must be re-created when the new task is created.

Figure 2: Task properties
Figure 2: Task properties

If the original task has saved credentials, Rename-ScheduledTask.ps1 will prompt you for credentials when creating the copy. If you don't want the script to prompt you for credentials, you can include the -TaskCredential parameter, which requires a PSCredential object as its argument. (See the sidebar "Clarifying Credential Confusion" for more information about the -ConnectionCredential and -TaskCredential parameters.)

Aside from the inability to copy credentials, there is one other notable side-effect of copying a task: The new copy of the task won't have the original task's history of events, which appear on the History tab of the properties page. If the task's event history is important, save the task's history to a file before renaming it.

The script's online help provides a comprehensive list of sample commands. To view the sample commands, run the following code at a PowerShell prompt:

Get-Help Rename ScheduledTask -full | more

Inside the Script

Rename-ScheduledTask.ps1 uses the Schedule.Service programmatic identifier (ProgID) to create the TaskService object, which provides access to the Task Scheduler service for managing registered tasks. The TaskService object doesn't exist on Windows versions prior to Vista and Server 2008. See the "Task Scheduler Scripting Objects" web page  for more information about the TaskService object and its associated objects.

Next, the script uses the TaskService object's Connect method to try to connect to the Task Scheduler service. If the -ConnectionCredential parameter exists on the command line, the script uses the get-plaintextpwd function, shown in Listing 1, to return the PSCredential object's Password property as a plain-text string. The script does this because the TaskService object's Connect method doesn't support PSCredential objects.

After connecting to the Task Scheduler service, the script checks the HighestVersion property of the TaskService object. This property is a 32-bit unsigned integer that contains the internal version number of the Task Scheduler service. The most significant 16 bits represent the major version number, and the least significant 16 bits represent the minor version. Internally, the Task Scheduler version in Windows 7, Vista, and Server 2008 is 1.2 (65538), so the script checks that the HighestVersion property is at least this version before continuing. If the service's version is too old, the script throws an error and exits.

If the Task Scheduler service version is recent enough, the script uses the TaskService object's GetFolder method to get the root tasks folder. The script then uses the get-taskname function, shown in Listing 2, to retrieve a list of all task names from all task folders. It uses the list of task names to check the validity of the -TaskName and -NewName parameters.

Next, Rename-ScheduledTask.ps1 retrieves the TaskDefinition object for the task named with the
-TaskName parameter. The TaskDefinition object defines all the components of the task. If the task has stored credentials, the script checks whether the -TaskCredential parameter was specified. If it wasn't specified, the script uses the Get-Credential cmdlet to prompt for credentials. (Canceling this prompt throws an error and ends the script.) If -TaskCredential was specified, the script uses the get-plaintextpwd function to convert the PSCredential object's Password property to plain text.

Finally, the script uses the RegisterTaskDefinition method to create a copy of the task. Note that if the task requires credentials but the supplied credentials aren't valid, the task won't be created and the script will throw an error. If the script creates the new task successfully, it uses the DeleteTask method of the original task's TaskFolder object to delete the original task.

Make the Rename Restriction Less Annoying

The overhauled Task Scheduler service includes many improvements over earlier versions, but the inability to rename a scheduled task is an annoying limitation. However, with the Rename-ScheduledTask.ps1 script in hand, it's a nuisance you're no longer forced to live with.

Listing 1: The get-plaintextpwd Function

 

function get-plaintextpwd($credential) {

  $credential.GetNetworkCredential().Password

}

 

Listing 2: The get-taskname Function

 

function get-taskname($taskFolder) {

  $tasks = $taskFolder.GetTasks(0)

  $tasks | foreach-object { $_.Path }

  $taskFolders = $taskFolder.GetFolders(0)

  $taskFolders | foreach-object { get-taskname $_ }

}