/* NOTICE OF CHANGES: date of change: 6/5/2007 change: Added default constructor for all type of Triggers. date of change: 6/12/2007 Added in custom helper structure and trigger.SetTaskTrigger() overload so that scheduled job serialization can be facilitated. date of change: 6/17/2007 change: Changed the implementation to not throw exception if HasEndDate is set to true date of change: 6/18/2007 change: Made HasEndDate access more safer. */ using System; using System.Runtime.InteropServices; using System.Xml.Serialization; using SMStrings; using TaskSchedulerInterop; namespace TaskScheduler { #region Enums /// /// Valid types of triggers /// public enum TriggerType { /// /// Trigger is set to run the task a single time. /// RunOnce = 0, /// /// Trigger is set to run the task on a daily interval. /// RunDaily = 1, /// /// Trigger is set to run the work item on specific days of a specific week of a specific month. /// RunWeekly = 2, /// /// Trigger is set to run the task on a specific day(s) of the month. /// RunMonthly = 3, /// /// Trigger is set to run the task on specific days, weeks, and months. /// RunMonthlyDOW = 4, /// /// Trigger is set to run the task if the system remains idle for the amount of time specified by the idle wait time of the task. /// OnIdle = 5, /// /// Trigger is set to run the task at system startup. /// OnSystemStart = 6, /// /// Trigger is set to run the task when a user logs on. /// OnLogon = 7 } /// /// Values for days of the week (Monday, Tuesday, etc.) These carry the Flags /// attribute so DaysOfTheWeek and be combined with | (or). /// [Flags] public enum DaysOfTheWeek : short { /// /// Sunday /// Sunday = 0x1, /// /// Monday /// Monday = 0x2, /// /// Tuesday /// Tuesday = 0x4, /// /// Wednesday /// Wednesday = 0x8, /// /// Thursday /// Thursday = 0x10, /// /// Friday /// Friday = 0x20, /// /// Saturday /// Saturday = 0x40 } /// /// Values for week of month (first, second, ..., last) /// public enum WhichWeek : short { /// /// First week of the month /// FirstWeek = 1, /// /// Second week of the month /// SecondWeek = 2, /// /// Third week of the month /// ThirdWeek = 3, /// /// Fourth week of the month /// FourthWeek = 4, /// /// Last week of the month /// LastWeek = 5 } /// /// Values for months of the year (January, February, etc.) These carry the Flags /// attribute so DaysOfTheWeek and be combined with | (or). /// [Flags] public enum MonthsOfTheYear : short { /// /// January /// January = 0x1, /// /// February /// February = 0x2, /// /// March /// March = 0x4, /// /// April /// April = 0x8, /// ///May /// May = 0x10, /// /// June /// June = 0x20, /// /// July /// July = 0x40, /// /// August /// August = 0x80, /// /// September /// September = 0x100, /// /// October /// October = 0x200, /// /// November /// November = 0x400, /// /// December /// December = 0x800 } #endregion /// /// Trigger is a generalization of all the concrete trigger classes, and any actual /// Trigger object is one of those types. When included in the TriggerList of a /// Task, a Trigger determines when a scheduled task will be run. /// /// /// /// Create a concrete trigger for a specific start condition and then call TriggerList.Add /// to include it in a task's TriggerList. /// /// A Trigger that is not yet in a Task's TriggerList is said to be unbound and it holds /// no resources (i.e. COM interfaces). Once it is added to a TriggerList, it is bound and /// holds a COM interface that is only released when the Trigger is removed from the list or /// the corresponding Task is closed. /// /// A Trigger that is already bound cannot be added to a TriggerList. To copy a Trigger from /// one list to another, use to create an unbound copy and then add the /// copy to the new list. To move a Trigger from one list to another, use /// to extract the Trigger from the first list before adding it to the second. /// public abstract class Trigger : ICloneable { #region Enums /// /// Flags for triggers /// [Flags] private enum TaskTriggerFlags { HasEndDate = 0x1, KillAtDurationEnd = 0x2, Disabled = 0x4 } #endregion #region Fields private ITaskTrigger iTaskTrigger; //null for an unbound Trigger internal TaskTrigger taskTrigger; // workaround for serializztion of TaskTrigger object [XmlElement(ElementName = "TASK_TRIGGER")] public SMTaskTrigger smTaskTrigger; #endregion #region Constructors and Initializers /// /// Internal base constructor for an unbound Trigger. /// internal Trigger() { iTaskTrigger = null; taskTrigger = new TaskTrigger(); taskTrigger.TriggerSize = (ushort)Marshal.SizeOf(taskTrigger); taskTrigger.BeginYear = (ushort)DateTime.Today.Year; taskTrigger.BeginMonth = (ushort)DateTime.Today.Month; taskTrigger.BeginDay = (ushort)DateTime.Today.Day; } /// /// Internal constructor which initializes itself from /// from an ITaskTrigger interface. /// /// Instance of ITaskTrigger from system task scheduler. internal Trigger(ITaskTrigger iTrigger) { if (iTrigger == null) throw new ArgumentNullException("iTrigger", SMSharedStringTable.GetString("SMSCHEDULER_ITASKTRIGGERIN_16")); iTaskTrigger = iTrigger; taskTrigger = new TaskTrigger(); taskTrigger.TriggerSize = (ushort)Marshal.SizeOf(taskTrigger); iTrigger.GetTrigger(ref taskTrigger); // workaround for serializztion of TaskTrigger object smTaskTrigger = new SMTaskTrigger(); smTaskTrigger.BeginDay = taskTrigger.BeginDay; smTaskTrigger.BeginMonth = taskTrigger.BeginMonth; smTaskTrigger.BeginYear = taskTrigger.BeginYear; smTaskTrigger.Data = taskTrigger.Data; smTaskTrigger.EndDay = taskTrigger.EndDay; smTaskTrigger.EndMonth = taskTrigger.EndMonth; smTaskTrigger.EndYear = taskTrigger.EndYear; smTaskTrigger.Flags = taskTrigger.Flags; smTaskTrigger.MinutesDuration = taskTrigger.MinutesDuration; smTaskTrigger.MinutesInterval = taskTrigger.MinutesInterval; smTaskTrigger.RandomMinutesInterval = taskTrigger.RandomMinutesInterval; smTaskTrigger.Reserved1 = taskTrigger.Reserved1; smTaskTrigger.Reserved2 = taskTrigger.Reserved2; smTaskTrigger.StartHour = taskTrigger.StartHour; smTaskTrigger.StartMinute = taskTrigger.StartMinute; smTaskTrigger.TriggerSize = taskTrigger.TriggerSize; smTaskTrigger.Type = taskTrigger.Type; } #endregion #region Implement ICloneable /// /// Clone returns an unbound copy of the Trigger object. It can be use /// on either bound or unbound original. /// /// public object Clone() { Trigger newTrigger = (Trigger)this.MemberwiseClone(); newTrigger.iTaskTrigger = null; // The clone is not bound return newTrigger; } #endregion #region Properties /// /// Get whether the Trigger is currently bound /// internal bool Bound { get { return iTaskTrigger != null; } } /// /// Gets/sets the beginning year, month, and day for the trigger. /// public DateTime BeginDate { get { return new DateTime(taskTrigger.BeginYear, taskTrigger.BeginMonth, taskTrigger.BeginDay); } set { taskTrigger.BeginYear = (ushort)value.Year; taskTrigger.BeginMonth = (ushort)value.Month; taskTrigger.BeginDay = (ushort)value.Day; SyncTrigger(); } } /// /// Gets/sets indication that the task uses an EndDate. Returns true if a value has been /// set for the EndDate property. Set can only be used to turn indication off. /// /// Has EndDate becomes true only by setting the EndDate /// property. public bool HasEndDate { get { return ((taskTrigger.Flags & (uint)TaskTriggerFlags.HasEndDate) == (uint)TaskTriggerFlags.HasEndDate); } set { if (value) // throw new ArgumentException("HasEndDate can only be set false"); taskTrigger.Flags |= (uint)TaskTriggerFlags.HasEndDate; else taskTrigger.Flags &= ~(uint)TaskTriggerFlags.HasEndDate; SyncTrigger(); } } /// /// Gets/sets the ending year, month, and day for the trigger. After a value has been set /// with EndDate, HasEndDate becomes true. /// public DateTime EndDate { get { if (taskTrigger.EndYear == 0) return DateTime.MinValue; return new DateTime(taskTrigger.EndYear, taskTrigger.EndMonth, taskTrigger.EndDay); } set { taskTrigger.Flags |= (uint)TaskTriggerFlags.HasEndDate; taskTrigger.EndYear = (ushort)value.Year; taskTrigger.EndMonth = (ushort)value.Month; taskTrigger.EndDay = (ushort)value.Day; SyncTrigger(); } } /// /// Gets/sets the number of minutes after the trigger fires that it remains active. Used /// in conjunction with to run a task repeatedly for a period of time. /// For example, if you want to start a task at 8:00 A.M. repeatedly restart it until 5:00 P.M., /// there would be 540 minutes (9 hours) in the duration. /// Can also be used to terminate a task that is running when the DurationMinutes expire. Use /// to specify that task should be terminated at that time. /// /// Setting must be greater than or equal /// to the IntervalMinutes setting. public int DurationMinutes { get { return (int)taskTrigger.MinutesDuration; } set { if (value < taskTrigger.MinutesInterval) throw new ArgumentOutOfRangeException("DurationMinutes", value, SMSharedStringTable.GetString("SMSCHEDULER_DURATIONMINUTE_8")); taskTrigger.MinutesDuration = (ushort)value; SyncTrigger(); } } /// /// Gets/sets the number of minutes between executions for a task that is to be run repeatedly. /// Repetition continues until the interval specified in expires. /// IntervalMinutes are counted from the start of the previous execution. /// /// Setting must be less than /// to the DurationMinutes setting. public int IntervalMinutes { get { return (int)taskTrigger.MinutesInterval; } set { if (value > taskTrigger.MinutesDuration) throw new ArgumentOutOfRangeException("IntervalMinutes", value, SMSharedStringTable.GetString("SMSCHEDULER_INTERVALMINUTE_13")); taskTrigger.MinutesInterval = (uint)value; SyncTrigger(); } } /// /// Gets/sets whether task will be killed (terminated) when DurationMinutes expires. /// See . /// public bool KillAtDurationEnd { get { return ((taskTrigger.Flags & (uint)TaskTriggerFlags.KillAtDurationEnd) == (uint)TaskTriggerFlags.KillAtDurationEnd); } set { if (value) taskTrigger.Flags |= (uint)TaskTriggerFlags.KillAtDurationEnd; else taskTrigger.Flags &= ~(uint)TaskTriggerFlags.KillAtDurationEnd; SyncTrigger(); } } /// /// Gets/sets whether trigger is disabled. /// public bool Disabled { get { return ((taskTrigger.Flags & (uint)TaskTriggerFlags.Disabled) == (uint)TaskTriggerFlags.Disabled); } set { if (value) taskTrigger.Flags |= (uint)TaskTriggerFlags.Disabled; else taskTrigger.Flags &= ~(uint)TaskTriggerFlags.Disabled; SyncTrigger(); } } #endregion #region Methods /// /// Creates a new, bound Trigger object from an ITaskTrigger interface. The type of the /// concrete object created is determined by the type of ITaskTrigger. /// /// Instance of ITaskTrigger. /// One of the concrete classes derived from Trigger. /// /// Unable to recognize trigger type. internal static Trigger CreateTrigger(ITaskTrigger iTaskTrigger) { if (iTaskTrigger == null) throw new ArgumentNullException("iTaskTrigger", SMSharedStringTable.GetString("SMSCHEDULER_INSTANCEOFITAS_12")); TaskTrigger sTaskTrigger = new TaskTrigger(); sTaskTrigger.TriggerSize = (ushort)Marshal.SizeOf(sTaskTrigger); iTaskTrigger.GetTrigger(ref sTaskTrigger); switch ((TriggerType)sTaskTrigger.Type) { case TriggerType.RunOnce: return new RunOnceTrigger(iTaskTrigger); case TriggerType.RunDaily: return new DailyTrigger(iTaskTrigger); case TriggerType.RunWeekly: return new WeeklyTrigger(iTaskTrigger); case TriggerType.RunMonthlyDOW: return new MonthlyDOWTrigger(iTaskTrigger); case TriggerType.RunMonthly: return new MonthlyTrigger(iTaskTrigger); case TriggerType.OnIdle: return new OnIdleTrigger(iTaskTrigger); case TriggerType.OnSystemStart: return new OnSystemStartTrigger(iTaskTrigger); case TriggerType.OnLogon: return new OnLogonTrigger(iTaskTrigger); default: throw new ArgumentException(SMSharedStringTable.GetString("SMSCHEDULER_UNABLETORECOGN_15"), "iTaskTrigger"); } } /// /// When a bound Trigger is changed, the corresponding trigger in the system /// Task Scheduler is updated to stay in sync with the local structure. /// protected void SyncTrigger() { if (iTaskTrigger!=null) iTaskTrigger.SetTrigger(ref taskTrigger); } /// /// Bind a Trigger object to an ITaskTrigger interface. This causes the Trigger to /// sync itself with the interface and remain in sync whenever it is modified in the future. /// If the Trigger is already bound, an ArgumentException is thrown. /// /// An interface representing a trigger in Task Scheduler. /// Attempt to bind and already bound trigger. internal void Bind(ITaskTrigger iTaskTrigger) { if (this.iTaskTrigger != null) throw new ArgumentException(SMSharedStringTable.GetString("SMSCHEDULER_ATTEMPTTOBINDA_6")); this.iTaskTrigger = iTaskTrigger; iTaskTrigger.SetTrigger(ref taskTrigger); } /// /// Bind a Trigger to the same interface the argument trigger is bound to. /// /// A bound Trigger. internal void Bind(Trigger trigger) { Bind(trigger.iTaskTrigger); } /// /// Break the connection between this Trigger and the system Task Scheduler. This /// releases COM resources used in bound Triggers. /// internal void Unbind() { if (iTaskTrigger != null) { Marshal.ReleaseComObject(iTaskTrigger); iTaskTrigger = null; } } /// /// Gets a string, supplied by the WindowsTask Scheduler, of a bound Trigger. /// For an unbound trigger, returns "Unbound Trigger". /// /// String representation of the trigger. public override string ToString() { if (iTaskTrigger != null) { IntPtr lpwstr; iTaskTrigger.GetTriggerString(out lpwstr); return CoTaskMem.LPWStrToString(lpwstr); } else { return "Unbound " + this.GetType().ToString(); } } /// /// Determines if two triggers are internally equal. Does not consider whether /// the Triggers are bound or not. /// /// Value of trigger to compare. /// true if triggers are equivalent. public override bool Equals(object obj) { return taskTrigger.Equals(((Trigger)obj).taskTrigger); } /// /// Gets a hash code for the current trigger. A Trigger has the same hash /// code whether it is bound or not. /// /// Hash code value. public override int GetHashCode() { return taskTrigger.GetHashCode(); } // workaround for deserialization public void SetTaskTrigger() { taskTrigger.BeginDay = smTaskTrigger.BeginDay; taskTrigger.BeginMonth = smTaskTrigger.BeginMonth; taskTrigger.BeginYear = smTaskTrigger.BeginYear; taskTrigger.Data = smTaskTrigger.Data; taskTrigger.EndDay = smTaskTrigger.EndDay; taskTrigger.EndMonth = smTaskTrigger.EndMonth; taskTrigger.EndYear = smTaskTrigger.EndYear; taskTrigger.Flags = smTaskTrigger.Flags; taskTrigger.MinutesDuration = smTaskTrigger.MinutesDuration; taskTrigger.MinutesInterval = smTaskTrigger.MinutesInterval; taskTrigger.RandomMinutesInterval = smTaskTrigger.RandomMinutesInterval; taskTrigger.Reserved1 = smTaskTrigger.Reserved1; taskTrigger.Reserved2 = smTaskTrigger.Reserved2; taskTrigger.StartHour = smTaskTrigger.StartHour; taskTrigger.StartMinute = smTaskTrigger.StartMinute; taskTrigger.TriggerSize = smTaskTrigger.TriggerSize; taskTrigger.Type = smTaskTrigger.Type; } #endregion } // class Trigger /// /// Generalization of all triggers that have a start time. /// /// StartableTrigger serves as a base class for triggers with a /// start time, but it has little use to clients. public abstract class StartableTrigger : Trigger { /// /// Internal constructor, same as base. /// internal StartableTrigger() : base() { } /// /// Internal constructor from ITaskTrigger interface. /// /// ITaskTrigger from system Task Scheduler. internal StartableTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } /// /// Sets the start time of the trigger. /// /// Hour of the day that the trigger will fire. /// Minute of the hour. /// The hour is not between 0 and 23 or the minute is not between 0 and 59. protected void SetStartTime(ushort hour, ushort minute) { // if (hour < 0 || hour > 23) // throw new ArgumentOutOfRangeException("hour", hour, "hour must be between 0 and 23"); // if (minute < 0 || minute > 59) // throw new ArgumentOutOfRangeException("minute", minute, "minute must be between 0 and 59"); // taskTrigger.StartHour = hour; // taskTrigger.StartMinute = minute; // base.SyncTrigger(); StartHour = (short)hour; StartMinute = (short)minute; } /// /// Gets/sets hour of the day that trigger will fire (24 hour clock). /// public short StartHour { get { return (short)taskTrigger.StartHour; } set { if (value < 0 || value > 23) throw new ArgumentOutOfRangeException("hour", value, SMSharedStringTable.GetString("SMSCHEDULER_HOURMUSTBEBETW_11")); taskTrigger.StartHour = (ushort)value; base.SyncTrigger(); } } /// /// Gets/sets minute of the hour (specified in ) that trigger will fire. /// public short StartMinute { get { return (short)taskTrigger.StartMinute; } set { if (value < 0 || value > 59) throw new ArgumentOutOfRangeException("minute", value, SMSharedStringTable.GetString("SMSCHEDULER_MINUTEMUSTBEBE_17")); taskTrigger.StartMinute = (ushort)value; base.SyncTrigger(); } } } /// /// Trigger that fires once only. /// public class RunOnceTrigger : StartableTrigger { public RunOnceTrigger() { ;} /// /// Create a RunOnceTrigger that fires when specified. /// /// Date and time to fire. public RunOnceTrigger(DateTime runDateTime) : base() { taskTrigger.BeginYear = (ushort)runDateTime.Year; taskTrigger.BeginMonth = (ushort)runDateTime.Month; taskTrigger.BeginDay = (ushort)runDateTime.Day; SetStartTime((ushort)runDateTime.Hour, (ushort)runDateTime.Minute); taskTrigger.Type = TaskTriggerType.TIME_TRIGGER_ONCE; } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// ITaskTrigger from system Task Scheduler. internal RunOnceTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } } /// /// Trigger that fires at a specified time, every so many days. /// public class DailyTrigger : StartableTrigger { public DailyTrigger() { ;} /// /// Creates a DailyTrigger that fires only at an interval of so many days. /// /// Hour of day trigger will fire. /// Minutes of the hour trigger will fire. /// Number of days between task runs. public DailyTrigger(short hour, short minutes, short daysInterval) : base() { SetStartTime((ushort)hour, (ushort)minutes); taskTrigger.Type = TaskTriggerType.TIME_TRIGGER_DAILY; taskTrigger.Data.daily.DaysInterval = (ushort)daysInterval; } /// /// Creates DailyTrigger that fires every day. /// /// Hour of day trigger will fire. /// Minutes of hour (specified in "hour") trigger will fire. public DailyTrigger(short hour, short minutes) : this(hour, minutes, 1) { } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// ITaskTrigger from system Task Scheduler. internal DailyTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } /// /// Gets/sets the number of days between successive firings. /// public short DaysInterval { get { return (short)taskTrigger.Data.daily.DaysInterval; } set { taskTrigger.Data.daily.DaysInterval = (ushort)value; base.SyncTrigger(); } } } /// /// Trigger that fires at a specified time, on specified days of the week, /// every so many weeks. /// public class WeeklyTrigger : StartableTrigger { public WeeklyTrigger() { ;} /// /// Creates a WeeklyTrigger that is eligible to fire only during certain weeks. /// /// Hour of day trigger will fire. /// Minutes of hour (specified in "hour") trigger will fire. /// Days of the week task will run. /// Number of weeks between task runs. public WeeklyTrigger(short hour, short minutes, DaysOfTheWeek daysOfTheWeek, short weeksInterval) : base() { SetStartTime((ushort)hour, (ushort)minutes); taskTrigger.Type = TaskTriggerType.TIME_TRIGGER_WEEKLY; taskTrigger.Data.weekly.WeeksInterval = (ushort)weeksInterval; taskTrigger.Data.weekly.DaysOfTheWeek = (ushort)daysOfTheWeek; } /// /// Creates a WeeklyTrigger that is eligible to fire during any week. /// /// Hour of day trigger will fire. /// Minutes of hour (specified in "hour") trigger will fire. /// Days of the week task will run. public WeeklyTrigger(short hour, short minutes, DaysOfTheWeek daysOfTheWeek) : this(hour, minutes, daysOfTheWeek, 1) { } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// ITaskTrigger interface from system Task Scheduler. internal WeeklyTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } /// /// Gets/sets number of weeks from one eligible week to the next. /// public short WeeksInterval { get { return (short)taskTrigger.Data.weekly.WeeksInterval; } set { taskTrigger.Data.weekly.WeeksInterval = (ushort)value; base.SyncTrigger(); } } /// /// Gets/sets the days of the week on which the trigger fires. /// public DaysOfTheWeek WeekDays { get { return (DaysOfTheWeek)taskTrigger.Data.weekly.DaysOfTheWeek; } set { taskTrigger.Data.weekly.DaysOfTheWeek = (ushort)value; base.SyncTrigger(); } } } /// /// Trigger that fires at a specified time, on specified days of the week, /// in specified weeks of the month, during specified months of the year. /// public class MonthlyDOWTrigger : StartableTrigger { public MonthlyDOWTrigger() { ;} /// /// Creates a MonthlyDOWTrigger that fires every month. /// /// Hour of day trigger will fire. /// Minute of the hour trigger will fire. /// Days of the week trigger will fire. /// Weeks of the month trigger will fire. /// Months of the year trigger will fire. public MonthlyDOWTrigger(short hour, short minutes, DaysOfTheWeek daysOfTheWeek, WhichWeek whichWeeks, MonthsOfTheYear months) : base() { SetStartTime((ushort)hour, (ushort)minutes); taskTrigger.Type = TaskTriggerType.TIME_TRIGGER_MONTHLYDOW; taskTrigger.Data.monthlyDOW.WhichWeek = (ushort)whichWeeks; taskTrigger.Data.monthlyDOW.DaysOfTheWeek = (ushort)daysOfTheWeek; taskTrigger.Data.monthlyDOW.Months = (ushort)months; } /// /// Creates a MonthlyDOWTrigger that fires during specified months only. /// /// Hour of day trigger will fire. /// Minute of the hour trigger will fire. /// Days of the week trigger will fire. /// Weeks of the month trigger will fire. public MonthlyDOWTrigger(short hour, short minutes, DaysOfTheWeek daysOfTheWeek, WhichWeek whichWeeks) : this(hour, minutes, daysOfTheWeek, whichWeeks, MonthsOfTheYear.January|MonthsOfTheYear.February|MonthsOfTheYear.March|MonthsOfTheYear.April|MonthsOfTheYear.May|MonthsOfTheYear.June|MonthsOfTheYear.July|MonthsOfTheYear.August|MonthsOfTheYear.September|MonthsOfTheYear.October|MonthsOfTheYear.November|MonthsOfTheYear.December) { } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// ITaskTrigger from the system Task Scheduler. internal MonthlyDOWTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } /// /// Gets/sets weeks of the month in which trigger will fire. /// public short WhichWeeks { get { return (short)taskTrigger.Data.monthlyDOW.WhichWeek; } set { taskTrigger.Data.monthlyDOW.WhichWeek = (ushort)value; base.SyncTrigger(); } } /// /// Gets/sets days of the week on which trigger will fire. /// public DaysOfTheWeek WeekDays { get { return (DaysOfTheWeek)taskTrigger.Data.monthlyDOW.DaysOfTheWeek; } set { taskTrigger.Data.monthlyDOW.DaysOfTheWeek = (ushort)value; base.SyncTrigger(); } } /// /// Gets/sets months of the year in which trigger will fire. /// public MonthsOfTheYear Months { get { return (MonthsOfTheYear)taskTrigger.Data.monthlyDOW.Months; } set { taskTrigger.Data.monthlyDOW.Months = (ushort)value; base.SyncTrigger(); } } } /// /// Trigger that fires at a specified time, on specified days of themonth, /// on specified months of the year. /// public class MonthlyTrigger : StartableTrigger { public MonthlyTrigger() { ;} /// /// Creates a MonthlyTrigger that fires only during specified months of the year. /// /// Hour of day trigger will fire. /// Minutes of hour (specified in "hour") trigger will fire. /// Days of the month trigger will fire. (See property. /// Months of the year trigger will fire. public MonthlyTrigger(short hour, short minutes, int[] daysOfMonth, MonthsOfTheYear months): base() { SetStartTime((ushort)hour, (ushort)minutes); taskTrigger.Type = TaskTriggerType.TIME_TRIGGER_MONTHLYDATE; taskTrigger.Data.monthlyDate.Months = (ushort)months; taskTrigger.Data.monthlyDate.Days = (uint)IndicesToMask(daysOfMonth); } /// /// Creates a MonthlyTrigger that fires during any month. /// /// Hour of day trigger will fire. /// Minutes of hour (specified in "hour") trigger will fire. /// Days of the month trigger will fire. (See property. public MonthlyTrigger(short hour, short minutes, int[] daysOfMonth) : this(hour, minutes, daysOfMonth, MonthsOfTheYear.January|MonthsOfTheYear.February|MonthsOfTheYear.March|MonthsOfTheYear.April|MonthsOfTheYear.May|MonthsOfTheYear.June|MonthsOfTheYear.July|MonthsOfTheYear.August|MonthsOfTheYear.September|MonthsOfTheYear.October|MonthsOfTheYear.November|MonthsOfTheYear.December) { } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// ITaskTrigger from system Task Scheduler. internal MonthlyTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } /// /// Gets/sets months of the year trigger will fire. /// public MonthsOfTheYear Months { get { return (MonthsOfTheYear)taskTrigger.Data.monthlyDate.Months; } set { taskTrigger.Data.monthlyDOW.Months = (ushort)value; base.SyncTrigger(); } } /// /// Convert an integer representing a mask to an array where each element contains the index /// of a bit that is ON in the mask. Bits are considered to number from 1 to 32. /// /// An interger to be interpreted as a mask. /// An array with an element for each bit of the mask which is ON. private static int[] MaskToIndices(int mask) { //count bits in mask int cnt = 0; for (int i=0; (mask>>i)>0; i++) cnt = cnt + (1 & (mask>>i)); //allocate return array with one entry for each bit int[] indices = new int[cnt]; //fill array with bit indices cnt = 0; for (int i=0; (mask>>i)>0; i++) if ((1 & (mask>>i)) == 1) indices[cnt++] = i+1; return indices; } /// /// Converts an array of bit indices into a mask with bits turned ON at every index /// contained in the array. Indices must be from 1 to 32 and bits are numbered the same. /// /// An array with an element for each bit of the mask which is ON. /// An interger to be interpreted as a mask. private static int IndicesToMask(int[] indices) { int mask = 0; foreach (int index in indices) { if (index<1 || index>31) throw new ArgumentException(SMSharedStringTable.GetString("SMSCHEDULER_DAYSMUSTBEINTH_7")); mask = mask | 1<<(index-1); } return mask; } /// /// Gets/sets days of the month trigger will fire. /// /// An array with one element for each day that the trigger will fire. /// The value of the element is the number of the day, in the range 1..31. public int[] Days { get { return MaskToIndices((int)taskTrigger.Data.monthlyDate.Days); } set { taskTrigger.Data.monthlyDate.Days = (uint)IndicesToMask(value); base.SyncTrigger(); } } } /// /// Trigger that fires when the system is idle for a period of time. /// Length of period set by . /// public class OnIdleTrigger : Trigger { /// /// Creates an OnIdleTrigger. Idle period set separately. /// See inherited property. /// public OnIdleTrigger() : base() { taskTrigger.Type = TaskTriggerType.EVENT_TRIGGER_ON_IDLE; } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// Current base Trigger. internal OnIdleTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } } /// /// Trigger that fires when the system starts. /// public class OnSystemStartTrigger : Trigger { /// /// Creates an OnSystemStartTrigger. /// public OnSystemStartTrigger() : base() { taskTrigger.Type = TaskTriggerType.EVENT_TRIGGER_AT_SYSTEMSTART; } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// ITaskTrigger interface from system Task Scheduler. internal OnSystemStartTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } } /// /// Trigger that fires when a user logs on. /// /// Triggers of this type fire when any user logs on, not just the /// user identified in the account information. public class OnLogonTrigger : Trigger { /// /// Creates an OnLogonTrigger. /// public OnLogonTrigger() : base() { taskTrigger.Type = TaskTriggerType.EVENT_TRIGGER_AT_LOGON; } /// /// Internal constructor to create from existing ITaskTrigger interface. /// /// ITaskTrigger from system Task Scheduler. internal OnLogonTrigger(ITaskTrigger iTrigger) : base(iTrigger) { } } }