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; }
}
}
}