|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionTask Scheduler is the Windows service that schedules and automatically starts programs. Windows Explorer presents a user interface to the service when you browse the %WINDIR%\TASKS folder, typically from the shortcut in the control panel. From the command line, the Note: Since this library was created, Microsoft has introduced a new task scheduler (Task Scheduler 2.0) for Windows Vista. This library is a wrapper for the Task Scheduler 1.0 interface, which is still available in Vista and is compatible with Windows XP, Windows Server 2003 and Windows 2000. The library is an expanded version of a package written by CodeProject.com member David Hall. See his article. In the original work, David demonstrated how a collection of COM interfaces could be tamed into a logical class library in the .NET style. This new version offers many improvements, including the elimination of COM memory leaks. Fixing the memory leak problem required the adoption of an incompatible class hierarchy, but, for clients in transition, the original hierarchy remains available as a kind of differently organized view of the same objects. It is deprecated, however, because of the leaks. A later section on compatibility gives more detail. Documentation is contained in an HTML help file, MSDN-style, which is downloaded along with the library. The documentation is intended to be self-contained and sufficient for any client to use the library. MSDN documents the COM interface on which the library is based. It is worth consulting when the library's documentation lacks. The second download contains the source code for the library and for a C# test application that also serves as sample code. The test application is a trivial command line interpreter that operates on scheduled tasks. It can easily be modified to insert whatever tests you may want to make. This article introduces the library's class hierarchy and also describes some of the changes that were made from the original version. Contents
ClassesThe complete class hierarchy is illustrated by the following diagram, drawn to the standard David Hall set in his article. The abstract class
ScheduledTasksA // Get a ScheduledTasks object for the computer named "DALLAS"
ScheduledTasks st = new ScheduledTasks(@"\\DALLAS");
You use a // Get an array of all the task names
string[] taskNames = st.GetTaskNames();
A // Dispose the ScheduledTasks object to release COM resources.
st.Dispose();
TaskA // Open a task named "foo" from the local computer's scheduled tasks
ScheduledTasks st = new ScheduledTasks();
Task t = st.OpenTask("foo");
A // Close the Task object to release COM resources.
t.Close();
TriggerListA // Get the triggers for the local task "foo".
ScheduledTasks st = new ScheduledTasks();
Task t = st.OpenTask("foo");
TriggerList tl = t.Triggers;
A Trigger
// Add a trigger to run task "foo" at 4:30 pm every day
Trigger tg = new DailyTrigger(16, 30); // hour and minute
ScheduledTasks st = new ScheduledTasks();
Task t = st.OpenTask("foo");
t.Triggers.Add(tg);
t.Save();
When a new
Sample CodeSeveral examples should suffice to give the flavor of interaction with the Task Scheduler. See the accompanying MSDN-style help file for complete documentation of the classes. Listing the Scheduled Tasks from a ComputerThis example connects to a computer named "DALLAS" and prints a summary of its scheduled tasks on the console. If DALLAS could not be accessed or the user account running the code does not have administrator privileges on DALLAS, then the constructor will throw an exception. Such exceptions aren't handled in the sample code. // Get a ScheduledTasks object for the computer named "DALLAS"
ScheduledTasks st = new ScheduledTasks(@"\\DALLAS");
// Get an array of all the task names
string[] taskNames = st.GetTaskNames();
// Open each task, write a descriptive string to the console
foreach (string name in taskNames) {
Task t = st.OpenTask(name);
Console.WriteLine(" " + t.ToString());
t.Close();
}
// Dispose the ScheduledTasks object to release COM resources.
st.Dispose();
Scheduling a New Task to be RunCreate a new task named "D checker" that runs chkdsk on the D: drive. //Get a ScheduledTasks object for the local computer.
ScheduledTasks st = new ScheduledTasks();
// Create a task
Task t;
try {
t = st.CreateTask("D checker");
} catch (ArgumentException) {
Console.WriteLine("Task name already exists");
return;
}
// Fill in the program info
t.ApplicationName = "chkdsk.exe";
t.Parameters = "d: /f";
t.Comment = "Checks and fixes errors on D: drive";
// Set the account under which the task should run.
t.SetAccountInformation(@"THEDOMAIN\TheUser", "HisPasswd");
// Declare that the system must have been idle for ten minutes before
// the task will start
t.IdleWaitMinutes = 10;
// Allow the task to run for no more than 2 hours, 30 minutes.
t.MaxRunTime = new TimeSpan(2, 30, 0);
// Set priority to only run when system is idle.
t.Priority = System.Diagnostics.ProcessPriorityClass.Idle;
// Create a trigger to start the task every Sunday at 6:30 AM.
t.Triggers.Add(new WeeklyTrigger(6, 30, DaysOfTheWeek.Sunday));
// Save the changes that have been made.
t.Save();
// Close the task to release its COM resources.
t.Close();
// Dispose the ScheduledTasks to release its COM resources.
st.Dispose();
Change the Time that a Task will be RunThis code opens a particular task and then updates any trigger with a start time, changing the time to 4:15 am. This makes use of the // Get a ScheduledTasks object for the local computer.
ScheduledTasks st = new ScheduledTasks();
// Open a task we're interested in
Task task = st.OpenTask("D checker");
// Be sure the task was found before proceeding
if (task != null) {
// Enumerate each trigger in the TriggerList of this task
foreach (Trigger tr in task.Triggers) {
// If this trigger has a start time, change it to 4:15 AM.
if (tr is StartableTrigger) {
(tr as StartableTrigger).StartHour = 4;
(tr as StartableTrigger).StartMinute = 15;
}
}
task.Save();
task.Close();
}
st.Dispose();
Frequently Asked QuestionsWhy am I getting access exceptions? This problem usually comes up for clients who want to use the Task Scheduler from ASP.NET code. Ordinarily, such code runs in the ASPNET account which has rather low privilege and can't use the Task Scheduler. The solution to this is to set your code to run in another, more privileged account. This is called impersonation, and you can set it up in your web.config file. The Task Scheduler doesn't require the client to run with administrative privilege, but if it's not, there will be restrictions on what can be done. I haven't found these to be well-documented. However, until recently it seemed that non-administrators could see and manipulate the tasks they created, but no others. In Windows XP SP2, there seems to be some generalization. In the Explorer, there is a new Security tab on the task Properties dialog box. There is also do a little documentation explaining that the file permissions on the task will govern what other users can do with them. Must I have an account and password for a task? A scheduled task must be given a specific account in which to run or it may be set to run in the local system account. The local system account is a pseudo-account used by many of the standard services. It has broad access to the local system, but it cannot always interact with the user directly and it has no network privileges. To set a task to run in the local system account, the client must be already running in that account or in an administrator account. If the task will need to interact with the user, you need to set a specific user account and the task will only interact with that user. If your client runs in different accounts depending on who is using it, you can have it schedule tasks without actually knowing the user's password. To this, you set a specific task flag, Why am I getting access denied on a remote machine? You must be running in an account that has sufficient privileges, both on your local machine and the remote machine. If there is no domain controller, you will need to be running in an account that is set up with the same name and same password on both machines. There are lots of ways this can go wrong, but you can work on correcting it by trying to access private files across the two machines and make that work first. I am opening the Scheduled Tasks on a remote machine, but it contains no tasks. This is generally because you named the machine without including two backslashes at the beginning. For some reason, the Task Scheduler will find the machine and seem to have opened it, but it will have no tasks. How to set the maximum runtime to be unlimited? The underlying service requires a special value be passed as the How did you make the cool documentation? The MSDN-like help file was built with Microsoft's Sandcastle (preview version) and Eric Woodruff's GUI front end, Sandcastle Help File Builder. Does the library work in Vista? Vista has introduced a new Task Scheduler with a new program interface, 2.0. This library accesses the old 1.0 interface so the same code can run in Vista, XP, Server 2003 or Windows 2000. The price of compatibility is that you don't get any of the features of the new Task Scheduler. I've tried the library on Vista and it seems to work fine. I have not figured out all the privilege requirements, though, so beware. Vista's user account control (UAC) means that you may have difficulty with even the test application included in the package. The task scheduler will allow you to do some things with only user privileges, but others require you to be running as an administrator. In the 2007 update to the project, I modified the test application so that it automatically runs with administrator privilege. You have to okay it, of course. This was done by adding a manifest file to the project and performing an automated post-build step to add the manifest to the executable. This uses the mt.exe tool, so that has to be in your path somewhere. My mt.exe is in the Windows SDK. If you use Visual Studio 2008, you can add the manifest without resorting to a post-build step. Just add it to the TestApp project. Changes from Version 1The primary aim of this new library was to provide control over COM resources. That required a change to the access model so clients could clearly tell when resources were allocated and freed. The new model is like a document application. Clients open and close tasks, and there are the equivalents of save and save-as that make changes permanent. When a Another goal was expansion of the XML documentation and therefore the help file. I learned a lot about the Task Scheduler while testing the library and I tried to include what I learned. Many other improvements were made, but the following are most noteworthy:
Compatibility with Version 1As noted above, the original classes from David Hall's library are still available for transitional use, so the library is essentially "plug-compatible." There are a couple of other minor issues that might affect a few users:
InternalsThe source files are fairly easy to browse and are written to a high standard of readability. Well, readability is in the eye of the beholder. I can only claim that I tried to write and document everything well. Open the solution in Visual Studio and browse around. There is a lot to be learned in reading any code, but one thing I can recommend the library for is learning how to write a wrapper for a COM interface. There are lots of design decisions, but the really messy stuff comes in how you actually interface with COM from C#. If you have to do it, this code might be interesting, especially from the aspect of resource allocation and deallocation. String properties returned by the COM interfaces for the Task Scheduler are generally allocated in COM task memory and a pointer to the string is returned. If the marshalling handles the conversion of the pointer to a History06/10/02
06/17/02
08/09/02
08/20/02
10/25/02
9/8/04
11/30/07
| ||||||||||||||||||||