22.07.2009

Планировщик заданий (Task Scheduler 1.0) Windows: программный доступ

Введение



Планировщик заданий является сервисом Windows, который умеет по расписанию запускать различные приложения. Windows-интерфейс для него обычно располагается в папке %WINDIR%\TASKS. Кроме того можно всю работу с ним организовать из командной строки путем вызова команды schtasks с необходимыми параметрами. Для программистов существует хорошо документированный Com-интерфейс, но в .Net нет обертки для него. Далее будет описано, как на C# организовать работу с планировщиком заданий.

Классы


На диаграмме представлена полная иерархия классов, необходимых для любой настройки планировщика, однако, программист, на свое усмотрение, может помять эту схему в зависимости от полноты использования функциональности планировщика.


ScheduledTasks

Как вы уже догадались планировщик заданий содержит список заданий, которые в свою очередь содержат список триггеров (условий выполнения задания). Каждое задание хранится на жестком диске в файле с расширением .job.

Класс ScheduledTasks является отображением системной папки того компьютера (локального или в сети), где хранятся все файлы с заданиями.

// создаем объект ScheduledTasks для машины с именем
//"DALLAS"

ScheduledTasks st = new ScheduledTasks(@"\\DALLAS");
С помощью этого объекта можно получить доступ к любой задаче для конкретного планировщика по имени задачи, которое равно имени файла задачи без расширения. Кроме того, можно получить все имена задач для данного планировщика:

// получение списка имен задач
string[] taskNames = st.GetTaskNames();
Т.к. этот класс оборачивает СОМ-ресурсов, то после использования его необходимо вызвать метод Dispose() для освобождения этого интерфейса.

Task

Этот класс оборачивает отдельное задание с предоставлением доступа к его параметрам (какое приложение необходимо запускать, время выполнения и др. параметры, которые можно увидеть в Windows-интерфейсе). Кроме этого у класса есть еще один параметр TriggerList, о котором будет рассказано ниже.
После содания, открытия и изменения необходимо сохранить задание в его файл с помощью функции Save(). Функция Save(string name) работает как и Windows-функция "Сохранить как". Данный класс не имеет public конструктора. Все процедуры по созданию, открытию выполняются с помощью класса ScheduledTasks посредсвтом вызова его методов Open() или Create().

// открываем задание с именем "foo" локальной машины
ScheduledTasks st = new ScheduledTasks();
Task t = st.OpenTask("foo");
Для освобождения СОМ-ресурсов используем функцию Close().

// закрываем задание для освобождения COM ресурса.
t.Close();

TriggerList

Каждое задание имеет одно или несколько временных или иных условий выполнения (запуска его программы). TriggerList является классом, представляющий список этих условий (триггеров). Класс нельзя самостоятельно создать, т.к. он не имеет public конструктора. Экземпляр класса создается при инициализации экземпляра класса Task и доступ к нему возможен только из класса Task.

// получение триггеров локального задания "foo".
ScheduledTasks st = new ScheduledTasks();
Task t = st.OpenTask("foo");
TriggerList tl = t.Triggers;
После закрытия задания данный список становится неактуальным.

Trigger

Триггер представляет собой условие, необходимое для выполнения задания. В Windows-интерфейсе они отображаются в виде списка. Существует несколько видов триггеров с различными параметрами (например те, которые запускаются один раз, и те, которые могут выполняться с некоторой периодичностью). Поэтому класс Trigger является абстрактным. Его наследуют конкретные классы-реализации различных типов триггеров. Каждый из наследников имеет свой уникальный конструктор и свои уникальные параметры настройки времени выполнения задания. Для создания триггера необходимо определиться с его типом и создать посредством его конструктора, затем добавить его в список триггеров задания:

// добавление триггера для задания "foo", чтобы оно
//выполнялось в 16:30 каждый день

Trigger tg = new DailyTrigger(16, 30); // часы и минуты
ScheduledTasks st = new ScheduledTasks();
Task t = st.OpenTask("foo");
t.Triggers.Add(tg);
t.Save();
Классы-наследники Trigger :
  1. RunOnceTrigger - выполнять однажды
  2. DailyTrigger - выполнять ежедневно
  3. WeeklyTrigger - выполнять еженедельно
  4. MonthlyDOWTrigger - выполнять ежемесячно с учетом дней в недели и самих недель
  5. MonthlyTrigger - выполнять ежемесячно с учетом дней с месяце
  6. OnIdleTrigger - выполнять при простое системы
  7. OnSystemStartTrigger - выполнять при старте системы
  8. OnLogonTrigger - выполнять при входе пользователя в систему
Созданный триггер непривязан ни к какому заданию, поэтому не занимает СОМ-ресурсов. Для привязки его необходимо включить в список TriggerList нужного задания. Освобождать его ресурсы нет необходимости, т.к. они автоматически освобождаюся при закрытии задания. Следующия правила позволят вам избежать некоторых ошибок при программировании планировщика заданий:
  • Конкретный экземпляр триггера может единыжды содержаться в списке триггеров задания. Невозможно добавить триггер в список, если он там уже присутствует (т.е. в списке должна быть только одна ссылка на этот объект). Для создания такого же триггера в другом списке необходимо воспользоваться функцией Clone() для создания непривязанного триггера и только потом добавить его в новый список.
  • Привязанный триггер невозможно использовать, если родительское задание закрыто.

Примеры использования

1. Получение списка заданий с удаленного компьютера (для этого пользователь, запустивший программу должен имет права администратора на удаленном компьютере):


// получение ScheduledTasks для компьютера "DALLAS"
ScheduledTasks st = new ScheduledTasks(@"\\DALLAS");

// полученеи списка имен заданий
string[] taskNames = st.GetTaskNames();

// получение каждого задания и вывод его описания
foreach (string name in taskNames) {
Task t = st.OpenTask(name);
Console.WriteLine(" " + t.ToString());
t.Close();
}

// освобождаем COM - ресурсы.
st.Dispose();

2. Создание нового задания
//получение ScheduledTasks локального компьютера.
ScheduledTasks st = new ScheduledTasks();

// Создание задания с именем "D checker"
Task t;
try
{
t = st.CreateTask("D checker");
}
catch
(ArgumentException)
{
Console.WriteLine("Задание с таким именем уже
существует"
);
return;
}

// Заполнение информации о программе для запуска
t.ApplicationName = "chkdsk.exe";
t.Parameters = "d: /f";
t.Comment = "Проверка диска D:";

// установка аккаунта, под которым будет
//происходить выполнение.

t.SetAccountInformation(@"THEDOMAIN\TheUser",
"
HisPasswd");

// Говорим системе ожидать 10 мин перед запуском
//программы

t.IdleWaitMinutes = 10;

// позволяем заданию выполняться не более 2 часов,
//30 минут.

t.MaxRunTime = new TimeSpan(2, 30, 0);

// говорим системе запускать задание только при
//простое.

t.Priority = System.Diagnostics.ProcessPriorityClass.Idle;

// создаем триггер для запуска каждое воскресенье
//в 6:30.

t.Triggers.Add(new WeeklyTrigger(6, 30,
DaysOfTheWeek.Sunday));

// Сохраняемся
t.Save();
// освобождаем все ресурсы.
t.Close();
// освобождаем ресурсы.
st.Dispose();

3. Меняем время выполнения задания

//получение ScheduledTasks локального компьютера.
ScheduledTasks st = new ScheduledTasks();

// открываем задание, которое было добавлено
Task task = st.OpenTask("D checker");

// удостоверяемся, что оно есть
if (task != null) {
// пробегаем по всем триггерам
foreach (Trigger tr in task.Triggers)
{
// если триггер имеет время начала выполнения задания,
// меняем на 4:15.

if (tr is StartableTrigger)
{
(tr as StartableTrigger).StartHour = 4;
(tr as StartableTrigger).StartMinute = 15;
}
}
task.Save();
task.Close();
}
st.Dispose();



Приведенные примеры частично взяты с:
http://www.codeproject.com/KB/cs/tsnewlib/TSNewLib_src.zip
из статьи:
http://www.codeproject.com/KB/cs/tsnewlib.aspx

Комментариев нет: