In "Scripting Solutions with WSH and COM: Scheduling Automated Tasks," March 2002, InstantDoc ID 23935, I introduced you to the power of scheduling your scripts in Windows XP and Windows 2000. I also showed you the basic methods for scheduling tasks. Now I want to show you some advanced methods that enhance the usefulness of task scheduling. Specifically, I want to show you how to use Task Scheduler with Windows Script Host's (WSH's) CScript engine, how to perform many activities with just one task, and how to automate task scheduling with Windows Management Instrumentation (WMI) scripts.
In my March column, I showed you how to schedule scripts by having Task Scheduler run them directly. For WSH scripts, you can use other methods to get the code to run. My preference is to use WSH's CScript engine to call the script. That way, the script and its parameters are all arguments to the CScript call, which prevents the WScript engine (the default script engine) from attempting to open any unattended windows. (However, using CScript doesn't stop VBScript's MsgBox function from opening windows, which is why you should always use WSH's WScript::Echo method rather than MsgBox in your scripts.) Another reason why I prefer using CScript is that it makes working with parameters easier.
Let's take a look at how to launch scripts with CScript. First, you need a test script. Listing 1, page 2, contains a good test script called WakeOnePC.vbs. You might recognize this code. WakeOnePC.vbs is a modified version of the SendMagicPacket.vbs script that I introduced in "Scripting Solutions with WSH and COM: Give Your PCs a Wake-Up Call," February 2002, InstantDoc ID 23602, and showed you how to launch with the Scheduled Task Wizard (without CScript) in my March column.
Next, you need to create a scheduled task to run WakeOnePC.vbs. You can use the Scheduled Task Wizard, or you can create the task manually.
If you want to use the Scheduled Task Wizard, you first need to set up a task to run CScript, then modify that task later to include the launching of the .vbs file. Start by opening the Scheduled Tasks folder and double-clicking Add Scheduled Task. When the Scheduled Task Wizard opens, click Next to obtain the dialog box that Figure 1, page 2, shows. Cscript.exe isn't typically in the list, so click Browse. In the Select Program to Schedule window, navigate to cscript.exe, which is typically in the \%systemroot%\system32 directory, and click Open. Rename your task from the default name of cscript, set the appropriate scheduling parameters, and click Finish. From the Scheduled Tasks window, you can modify the task by double-clicking it or by right-clicking it and selecting Properties.
As an administrator, I rarely use wizards, and scheduled tasks are no exception. Thus, I create tasks manually. From the Scheduled Tasks window, right-click an empty part of the window or choose File, New, Scheduled Task. Both actions immediately create a blank task and open the name of that task for editing, as Figure 2 shows. After you change the task's name, double-click the task to open its Properties dialog box.
As I described in my March column, the Properties dialog box has three tabs: Task, Schedule, and Settings. No data will be entered in the task, so you have to enter all the necessary data on the three tabs. You basically fill in the same data as you would for launching a script without CScript, except for the data in the Run text box on the Task tab. When you launch a script with CScript, you need to enter CScript's path before the script's path in the Run text box. After the script's path, you can include parameters. If a path or parameter has embedded spaces, you must enclose the path or parameter in quotes, such as
C:\windows\system32\cscript.exe "C:\my scripts\wakeonepc.vbs" param1 "this is param2" param3
For best results, I suggest that you specify the script's home directory in the Start in text box, as Figure 3 shows. Setting the home directory provides easier reference to the script and any other files associated with that script. In addition, setting the home directory lets you simplify the Run line to
C:\windows\system32\cscript.exe WakeOnePC.vbs param1 "this is param2" param3
After you fill in the rest of the information on the Task, Schedule, and Settings tabs, your task is completed.
Whether you want to manually create a task or use the Scheduled Task Wizard is up to you. Using the manual method is faster than using the Scheduled Task Wizard. However, when you manually create a task, it's easy to forget to enter items because the wizard isn't around to ensure that you've entered all the necessary data.
One Task to Rule Them All
As part of your job, I expect that you regularly need to update hundreds or thousands of clients across a network with patches and changes or to schedule downtime for maintenance. These tasks can be arduous. One way you can ease your burden is to create one task to rule them all. For example, on each client, you can use Task Scheduler to create one task that runs every 5 minutes. This task tells the client to check a particular central share for a certain file. The file uses a special syntax that you've created to tell the client whether it's one of the named machines that has an activity to perform (e.g., installing a DLL, changing a registry entry). If the client is to perform an activity, the file provides the client with a path. The path leads to a script that the client runs to perform the activity. When you need to perform a different activity on several clients, you simply modify the file on the central share to specify which clients should run which scripts. Many variations of this type of setup are possible.
You have several options for placing the original task on the clients. Assuming that you're using a central account that's in the client's local Administrators group, you can use an Administrator-equivalent account to access the client's Tasks folder on the ADMIN$ share (C:\windows, by default). Then, you can copy a task directly into the client's Tasks folder. Alternatively, you can use an ActiveX COM interface to connect to each client and add a task to that client. Task Scheduler is built on COM, so you can interface with Task Scheduler as easily as you can with many other systems administration functions. (I'll talk about how to use an ActiveX COM interface in a future article.)
Automating Task Scheduling
Now let's take a look at how to use WMI to automate task scheduling. If you want to develop standalone code rather than a script, you can use the Task Scheduler APIs to directly interface with some of the Task Scheduler's functions. You can learn about the Task Scheduler APIs from the Microsoft Developer Network (MSDN) Library at http://msdn.microsoft.com/library/en-us/taskschd/ts_portal_690l.asp.
The Task Scheduler APIs, however, aren't exposed as automation objects. Thus, from a scripting perspective, you can automate Task Scheduler in only one way: through WMI. WMI provides interfaces with which you can access and manage many system resources, devices, and applications. In this case, you use WMI to access the NetSchedule APIs that the AT service uses. (Before Task Scheduler, administrators used the At command with the Schedule service to schedule tasks, so they commonly refer to the service as AT.) The most important difference between the Task Scheduler APIs and the WMI interfaces is that the WMI interfaces work only on AT-scheduled jobs.
After you use WMI to transform an AT-scheduled job into a full-blown Task Scheduler job, WMI can't see the task anymore. Thus, you can't access the task through a script anymore; you need to access the task through the GUI. However, the WMI solution is simple to use and lets you practice scripting tasks, so let's take a closer look at it. After you've mastered task scheduling through WMI, you can explore the Task Scheduler APIs if you're interested in developing standalone code to interface with Task Scheduler.
Using WMI to View and Delete Tasks
I want to show you how to use WMI to view and delete one scheduled task or all scheduled tasks on a given client. My discussion won't cover WMI basics. If you're unfamiliar with WMI, you should first learn about this technology by reading the articles listed in Ethan Wilansky's Web-exclusive sidebar "Resources for the Script's Technologies," InstantDoc ID 22146. Although Wilansky wrote this sidebar for the article "Create Home Directories and Set NTFS Permissions with a Web Script," September 2001, InstantDoc ID 22048, the sidebar's WMI resources are helpful for anyone who wants to learn about this technology.
First, you need to create a few AT scripts to use as the targets for the scripts that follow. Open a command prompt window by using cmd.exe, then type the following line three times (a number I arbitrarily picked) to create three AT jobs numbered 1, 2, and 3:
At 00:10 /every:Sunday "C:\my scripts\myscript.vbs"
In these lines, replace the path to MyScript.vbs with the path to the correct script on your machine.
Listing 2 contains a script called ViewAllTasks.vbs that displays the currently scheduled tasks on a given machine. To use this script, you need to replace the strClientName variable's value (i.e., localhost) with the valid name of the machine to which you want to connect. The machine can't be the computer on which you're running the script.
In ViewAllTasks.vbs, I use the WMI class Win32_ScheduledJob to connect to the task (aka job) scheduling service on the specified client. Specifically, I use a valid connection string (which strClientName holds) with the "winmgmts://" programmatic identifier (ProgID) as a parameter to VBScript's GetObject function to connect to the target machine. I then use WMI's SWbemServices::InstancesOf method to connect to the collection of objects representing the scheduled tasks on that machine. As usual with a collection, I use VBScript's For Each...Next statement to iterate through the collection and the objTask variable to reference each task. For each task, I first use WMI's SWbemObject::Path_ property to obtain the full path to the task object, which looks like
where CLIENT1234 is the client's name and xxx is the task's ID number (e.g., 1, 2). I set this path to the strOut variable. Then, in another For Each...Next loop, I use WMI's SWbemObject::Properties_ property to obtain the Name and Value properties for each task and add this data to strOut. Finally, after iterating through the last task in the collection, I use the WScript::Echo method to display all the data in strOut.
ViewOneTask.vbs, which Listing 3 shows, is similar to ViewAllTasks.vbs. However, as the script's name suggests, ViewOneTask.vbs displays the path, name, and value of only one task. To single out one task, I use the SWbemServices object's ExecQuery method instead of its InstancesOf method. I pass the ExecQuery method a SELECT statement to specify the task in which I'm interested. For purposes of this script, I place the SELECT statement in the strSelectTask variable, as the code at callout A in Listing 3 shows. This SELECT statement specifies that I'm interested in task number 1. If you're interested in task number 12, you simply change JobId=1 to JobId=12. The rest of ViewOneTask.vbs executes the same way as ViewAllTasks.vbs.
When you know the number of a specific task, deleting that task is quite easy, as the script DeleteTask.vbs in Listing 4 shows. DeleteTask.vbs is a modified version of ViewOneTask.vbs. I simply use the SWbemServices::Delete method on the specified task. In this case, the For Each...Next loop is a bit unnecessary because the collection contains only one item—the specific task that you selected. DeleteAllTasks.vbs, which Listing 5 shows, takes the scripting examples full circle. This script deletes all existing tasks on the specified machine by combining the code from ViewAllTasks.vbs and DeleteTask.vbs.
Using WMI to Create Tasks
Using WMI to create tasks isn't hard, but the explanation would take up more space than I have left. So, I recommend that you explore Mark Castle's SK Automated Task Scheduler Scripts, which contain a Windows Script Components (WSC) component that automates Task Scheduler. In the component, Castle uses WMI to create a scheduled task.
You can download this freeware from the Code Library on the Windows Scripting Solutions Web site (http://www.winscriptingsolutions.com). The SK_Automated_Task_Scheduler_Scripts.zip file that you download includes the docs.html file, which contains the WSC component's documentation. In the documentation, you'll learn how to use the component's methods and properties, which include the Create method (creates tasks), the View method (views tasks), and the Delete method (deletes tasks).
Learn, Then Experiment
I've given you a lot of information to grasp, so take your time to learn the material, then try your hand at task scheduling. If you come up with some great ways to use and automate task scheduling, send them to me and I'll share them with everyone in a future column.