using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Xml.Serialization; namespace Microsoft.Win32.TaskScheduler { /// /// Provides the methods that are used to add to, remove from, and get the triggers of a task. /// [XmlRoot("Triggers", Namespace = TaskDefinition.tns, IsNullable = false)] public sealed class TriggerCollection : IList, IDisposable, IXmlSerializable { private V1Interop.ITask v1Task = null; private V2Interop.ITaskDefinition v2Def = null; private V2Interop.ITriggerCollection v2Coll = null; internal TriggerCollection(V1Interop.ITask iTask) { v1Task = iTask; } internal TriggerCollection(V2Interop.ITaskDefinition iTaskDef) { v2Def = iTaskDef; v2Coll = v2Def.Triggers; } /// /// Releases all resources used by this class. /// public void Dispose() { if (v2Coll != null) Marshal.ReleaseComObject(v2Coll); v2Def = null; v1Task = null; } /// /// Gets the collection enumerator for this collection. /// /// The for this collection. public IEnumerator GetEnumerator() { if (v1Task != null) return new V1TriggerEnumerator(v1Task); return new V2TriggerEnumerator(v2Coll, v2Def); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } internal sealed class V1TriggerEnumerator : IEnumerator { private V1Interop.ITask iTask; private short curItem = -1; internal V1TriggerEnumerator(V1Interop.ITask task) { iTask = task; } public Trigger Current { get { return Trigger.CreateTrigger(iTask.GetTrigger((ushort)curItem)); } } /// /// Releases all resources used by this class. /// public void Dispose() { iTask = null; } object System.Collections.IEnumerator.Current { get { return this.Current; } } public bool MoveNext() { if (++curItem >= iTask.GetTriggerCount()) return false; return true; } public void Reset() { curItem = -1; } } internal sealed class V2TriggerEnumerator : IEnumerator { private System.Collections.IEnumerator iEnum; private V2Interop.ITaskDefinition v2Def = null; internal V2TriggerEnumerator(V2Interop.ITriggerCollection iColl, V2Interop.ITaskDefinition iDef) { iEnum = iColl.GetEnumerator(); v2Def = iDef; } #region IEnumerator Members public Trigger Current { get { return Trigger.CreateTrigger((V2Interop.ITrigger)iEnum.Current, v2Def); } } #endregion #region IDisposable Members /// /// Releases all resources used by this class. /// public void Dispose() { iEnum = null; } #endregion #region IEnumerator Members object System.Collections.IEnumerator.Current { get { return this.Current; } } public bool MoveNext() { return iEnum.MoveNext(); } public void Reset() { iEnum.Reset(); } #endregion } /// /// Gets the number of triggers in the collection. /// public int Count { get { if (v2Coll != null) return v2Coll.Count; return (int)v1Task.GetTriggerCount(); } } /// /// Add an unbound to the task. /// /// derivative to add to the task. /// Bound trigger. /// unboundTrigger is null. public Trigger Add(Trigger unboundTrigger) { if (unboundTrigger == null) throw new ArgumentNullException("unboundTrigger"); if (v2Def != null) unboundTrigger.Bind(v2Def); else unboundTrigger.Bind(v1Task); return unboundTrigger; } /// /// Add a new trigger to the collections of triggers for the task. /// /// The type of trigger to create. /// A instance of the specified type. public Trigger AddNew(TaskTriggerType taskTriggerType) { if (v1Task != null) { ushort idx; return Trigger.CreateTrigger(v1Task.CreateTrigger(out idx), Trigger.ConvertToV1TriggerType(taskTriggerType)); } return Trigger.CreateTrigger(v2Coll.Create(taskTriggerType)); } /// /// Adds a collection of unbound triggers to the end of the . /// /// The triggers to be added to the end of the . The collection itself cannot be null and cannot contain null elements. /// triggers is null. public void AddRange(IEnumerable triggers) { if (triggers == null) throw new ArgumentNullException("triggers"); foreach (var item in triggers) this.Add(item); } internal void Bind() { foreach (Trigger t in this) t.SetV1TriggerData(); } /// /// Clears all triggers from the task. /// public void Clear() { if (v2Coll != null) v2Coll.Clear(); else { for (int i = this.Count - 1; i >= 0; i--) RemoveAt(i); } } /// /// Determines whether the contains a specific value. /// /// The object to locate in the . /// /// true if is found in the ; otherwise, false. /// public bool Contains(Trigger item) { return IndexOf(item) >= 0; } /// /// Determines whether the specified trigger type is contained in this collection. /// /// Type of the trigger. /// /// true if the specified trigger type is contained in this collection; otherwise, false. /// public bool ContainsType(Type triggerType) { foreach (Trigger t in this) if (t.GetType() == triggerType) return true; return false; } /// /// Copies the elements of the to an , starting at a particular index. /// /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. /// The zero-based index in at which copying begins. /// is null. /// is less than 0. /// The number of elements in the source is greater than the available space from to the end of the destination . public void CopyTo(Trigger[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException(); if (arrayIndex < 0) throw new ArgumentOutOfRangeException(); if (this.Count > (array.Length - arrayIndex)) throw new ArgumentException(); for (int i = 0; i < this.Count; i++) array[arrayIndex + i] = (Trigger)this[i].Clone(); } /// /// Gets a specified trigger from the collection. /// /// The index of the trigger to be retrieved. /// Specialized instance. public Trigger this[int index] { get { if (v2Coll != null) return Trigger.CreateTrigger(v2Coll[++index]); return Trigger.CreateTrigger(v1Task.GetTrigger((ushort)index)); } set { if (this.Count <= index) throw new ArgumentOutOfRangeException("index", index, "Index is not a valid index in the TriggerCollection"); RemoveAt(index); Insert(index, value); } } /// /// Gets or sets a specified trigger from the collection. /// /// /// The . /// /// The id () of the trigger to be retrieved. /// /// Specialized instance. /// /// /// /// /// Mismatching Id for trigger and lookup. public Trigger this[string triggerId] { get { if (string.IsNullOrEmpty(triggerId)) throw new ArgumentNullException(triggerId); foreach (Trigger t in this) if (string.Equals(t.Id, triggerId)) return t; throw new ArgumentOutOfRangeException(triggerId); } set { if (value == null) throw new NullReferenceException(); if (string.IsNullOrEmpty(triggerId)) throw new ArgumentNullException(triggerId); if (triggerId != value.Id) throw new InvalidOperationException("Mismatching Id for trigger and lookup."); int index = IndexOf(triggerId); if (index >= 0) { RemoveAt(index); Insert(index, value); } else Add(value); } } /// /// Determines the index of a specific item in the . /// /// The object to locate in the . /// /// The index of if found in the list; otherwise, -1. /// public int IndexOf(Trigger item) { for (int i = 0; i < this.Count; i++) { if (this[i].Equals(item)) return i; } return -1; } /// /// Determines the index of a specific item in the . /// /// The id () of the trigger to be retrieved. /// /// The index of if found in the list; otherwise, -1. /// public int IndexOf(string triggerId) { if (string.IsNullOrEmpty(triggerId)) throw new ArgumentNullException(triggerId); for (int i = 0; i < this.Count; i++) { if (string.Equals(this[i].Id, triggerId)) return i; } return -1; } /// /// Inserts an trigger at the specified index. /// /// The zero-based index at which trigger should be inserted. /// The trigger to insert into the list. public void Insert(int index, Trigger trigger) { Trigger[] pushItems = new Trigger[this.Count - index]; for (int i = index; i < this.Count; i++) pushItems[i - index] = (Trigger)this[i].Clone(); for (int j = this.Count - 1; j >= index; j--) RemoveAt(j); Add(trigger); for (int k = 0; k < pushItems.Length; k++) Add(pushItems[k]); } /// /// Removes the first occurrence of a specific object from the . /// /// The object to remove from the . /// /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . /// public bool Remove(Trigger item) { int idx = IndexOf(item); if (idx != -1) { try { RemoveAt(idx); return true; } catch { } } return false; } /// /// Removes the trigger at a specified index. /// /// Index of trigger to remove. /// Index out of range. public void RemoveAt(int index) { if (index >= this.Count) throw new ArgumentOutOfRangeException("index", index, "Failed to remove Trigger. Index out of range."); if (v2Coll != null) v2Coll.Remove(++index); else v1Task.DeleteTrigger((ushort)index); //Remove the trigger from the Task Scheduler } /// /// Returns a that represents the triggers in this collection. /// /// /// A that represents the triggers in this collection. /// public override string ToString() { if (this.Count == 1) return this[0].ToString(); if (this.Count > 1) return Properties.Resources.MultipleTriggers; return string.Empty; } System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() { return null; } void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) { reader.ReadStartElement("Triggers", TaskDefinition.tns); while (reader.MoveToContent() == System.Xml.XmlNodeType.Element) { switch (reader.LocalName) { case "BootTrigger": XmlSerializationHelper.ReadObject(reader, this.AddNew(TaskTriggerType.Boot)); break; case "IdleTrigger": XmlSerializationHelper.ReadObject(reader, this.AddNew(TaskTriggerType.Idle)); break; case "TimeTrigger": XmlSerializationHelper.ReadObject(reader, this.AddNew(TaskTriggerType.Time)); break; case "LogonTrigger": XmlSerializationHelper.ReadObject(reader, this.AddNew(TaskTriggerType.Logon)); break; case "CalendarTrigger": this.Add(CalendarTrigger.GetTriggerFromXml(reader)); break; default: reader.Skip(); break; } } reader.ReadEndElement(); } void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) { foreach (var t in this) XmlSerializationHelper.WriteObject(writer, t); } void ICollection.Add(Trigger item) { this.Add(item); } bool ICollection.IsReadOnly { get { return false; } } } }