using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Xml.Serialization;
namespace Microsoft.Win32.TaskScheduler
{
///
/// Defines the type of actions a task can perform.
///
/// The action type is defined when the action is created and cannot be changed later. See .
public enum TaskActionType
{
/// This action fires a handler.
ComHandler = 5,
/// This action performs a command-line operation. For example, the action can run a script, launch an executable, or, if the name of a document is provided, find its associated application and launch the application with the document.
Execute = 0,
/// This action sends and e-mail.
SendEmail = 6,
/// This action shows a message box.
ShowMessage = 7
}
///
/// Abstract base class that provides the common properties that are inherited by all action objects. An action object is created by the method.
///
public abstract class Action : IDisposable, ICloneable, IEquatable
{
internal V2Interop.IAction iAction = null;
/// List of unbound values when working with Actions not associated with a registered task.
protected Dictionary unboundValues = new Dictionary();
internal virtual bool Bound { get { return this.iAction != null; } }
internal virtual void Bind(V1Interop.ITask iTask)
{
}
internal virtual void Bind(V2Interop.ITaskDefinition iTaskDef)
{
V2Interop.IActionCollection iActions = iTaskDef.Actions;
switch (this.GetType().Name)
{
case "ComHandlerAction":
iAction = iActions.Create(TaskActionType.ComHandler);
break;
case "ExecAction":
iAction = iActions.Create(TaskActionType.Execute);
break;
case "EmailAction":
iAction = iActions.Create(TaskActionType.SendEmail);
break;
case "ShowMessageAction":
iAction = iActions.Create(TaskActionType.ShowMessage);
break;
default:
throw new ArgumentException();
}
Marshal.ReleaseComObject(iActions);
foreach (string key in unboundValues.Keys)
{
try
{
iAction.GetType().InvokeMember(key, System.Reflection.BindingFlags.SetProperty, null, iAction, new object[] { unboundValues[key] });
}
catch (System.Reflection.TargetInvocationException tie) { throw tie.InnerException; }
catch { }
}
unboundValues.Clear();
}
///
/// Creates a new object that is a copy of the current instance.
///
///
/// A new object that is a copy of this instance.
///
public object Clone()
{
Action ret = CreateAction(this.ActionType);
ret.CopyProperties(this);
return ret;
}
///
/// Copies the properties from another the current instance.
///
/// The source .
protected virtual void CopyProperties(Action sourceAction)
{
this.Id = sourceAction.Id;
}
///
/// Releases all resources used by this class.
///
public virtual void Dispose()
{
if (iAction != null)
Marshal.ReleaseComObject(iAction);
}
///
/// Determines whether the specified , is equal to this instance.
///
/// The to compare with this instance.
///
/// true if the specified is equal to this instance; otherwise, false.
///
public override bool Equals(object obj)
{
if (obj is Action)
return this.Equals((Action)obj);
return base.Equals(obj);
}
///
/// Indicates whether the current object is equal to another object of the same type.
///
/// An object to compare with this object.
///
/// true if the current object is equal to the parameter; otherwise, false.
///
public virtual bool Equals(Action other)
{
return this.ActionType == other.ActionType && this.Id == other.Id;
}
///
/// Returns a hash code for this instance.
///
///
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
///
public override int GetHashCode()
{
return new { A = this.ActionType, B = this.Id }.GetHashCode();
}
///
/// Gets the type of the action.
///
/// The type of the action.
[XmlIgnore]
public TaskActionType ActionType
{
get
{
if (iAction != null)
return iAction.Type;
if (this is ComHandlerAction)
return TaskActionType.ComHandler;
if (this is ShowMessageAction)
return TaskActionType.ShowMessage;
if (this is EmailAction)
return TaskActionType.SendEmail;
return TaskActionType.Execute;
}
}
///
/// Gets or sets the identifier of the action.
///
[DefaultValue(null)]
[XmlAttribute(AttributeName = "id", DataType = "ID")]
public virtual string Id
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Id") ? (string)unboundValues["Id"] : null) : this.iAction.Id; }
set { if (iAction == null) unboundValues["Id"] = value; else this.iAction.Id = value; }
}
///
/// Returns the action Id.
///
/// String representation of action.
public override string ToString()
{
return this.Id;
}
///
/// Returns a that represents this action.
///
/// The culture.
/// String representation of action.
public virtual string ToString(System.Globalization.CultureInfo culture)
{
using (new CultureSwitcher(culture))
return this.ToString();
}
///
/// Creates a specialized class from a defined interface.
///
/// Version 2.0 Action interface.
/// Specialized action class
internal static Action CreateAction(V2Interop.IAction iAction)
{
switch (iAction.Type)
{
case TaskActionType.ComHandler:
return new ComHandlerAction((V2Interop.IComHandlerAction)iAction);
case TaskActionType.SendEmail:
return new EmailAction((V2Interop.IEmailAction)iAction);
case TaskActionType.ShowMessage:
return new ShowMessageAction((V2Interop.IShowMessageAction)iAction);
case TaskActionType.Execute:
default:
return new ExecAction((V2Interop.IExecAction)iAction);
}
}
///
/// Creates the specified action.
///
/// Type of the action to instantiate.
/// of specified type.
public static Action CreateAction(TaskActionType actionType)
{
switch (actionType)
{
case TaskActionType.ComHandler:
return new ComHandlerAction();
case TaskActionType.SendEmail:
return new EmailAction();
case TaskActionType.ShowMessage:
return new ShowMessageAction();
case TaskActionType.Execute:
default:
return new ExecAction();
}
}
}
///
/// Represents an action that fires a handler. Only available on Task Scheduler 2.0.
///
[XmlType(IncludeInSchema = false)]
[XmlRoot("ComHandler", Namespace = TaskDefinition.tns, IsNullable = false)]
public sealed class ComHandlerAction : Action
{
///
/// Creates an unbound instance of .
///
public ComHandlerAction()
{
}
///
/// Creates an unbound instance of .
///
/// Identifier of the handler class.
/// Addition data associated with the handler.
public ComHandlerAction(Guid classId, string data)
{
this.ClassId = classId;
this.Data = data;
}
internal ComHandlerAction(V2Interop.IComHandlerAction action)
{
iAction = action;
}
///
/// Gets or sets the identifier of the handler class.
///
public Guid ClassId
{
get { return (iAction == null) ? (unboundValues.ContainsKey("ClassId") ? (Guid)unboundValues["ClassId"] : Guid.Empty) : new Guid(((V2Interop.IComHandlerAction)iAction).ClassId); }
set { if (iAction == null) unboundValues["ClassId"] = value.ToString(); else ((V2Interop.IComHandlerAction)iAction).ClassId = value.ToString(); }
}
///
/// Gets the name of the object referred to by .
///
public string ClassName
{
get { return GetNameForCLSID(this.ClassId); }
}
///
/// Gets or sets additional data that is associated with the handler.
///
[DefaultValue(null)]
public string Data
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Data") ? (string)unboundValues["Data"] : null) : ((V2Interop.IComHandlerAction)iAction).Data; }
set { if (iAction == null) unboundValues["Data"] = value; else ((V2Interop.IComHandlerAction)iAction).Data = value; }
}
///
/// Copies the properties from another the current instance.
///
/// The source .
protected override void CopyProperties(Action sourceAction)
{
if (sourceAction.GetType() == this.GetType())
{
base.CopyProperties(sourceAction);
this.ClassId = ((ComHandlerAction)sourceAction).ClassId;
this.Data = ((ComHandlerAction)sourceAction).Data;
}
}
///
/// Indicates whether the current object is equal to another object of the same type.
///
/// An object to compare with this object.
///
/// true if the current object is equal to the parameter; otherwise, false.
///
public override bool Equals(Action other)
{
return base.Equals(other) && this.ClassId == ((ComHandlerAction)other).ClassId && this.Data == ((ComHandlerAction)other).Data;
}
///
/// Gets a string representation of the .
///
/// String represention this action.
public override string ToString()
{
return string.Format(Properties.Resources.ComHandlerAction, this.ClassId, this.Data, this.Id, this.ClassName);
}
///
/// Gets the name for CLSID.
///
/// The unique identifier.
///
internal static string GetNameForCLSID(Guid guid)
{
using (RegistryKey k = Registry.ClassesRoot.OpenSubKey("CLSID", false))
{
if (k != null)
{
using (RegistryKey k2 = k.OpenSubKey(guid.ToString("B"), false))
return k2 != null ? k2.GetValue(null) as string : null;
}
}
return null;
}
}
///
/// Represents an action that executes a command-line operation.
///
[XmlRoot("Exec", Namespace = TaskDefinition.tns, IsNullable = false)]
public sealed class ExecAction : Action
{
private V1Interop.ITask v1Task;
///
/// Creates a new instance of an that can be added to .
///
public ExecAction() { }
///
/// Creates a new instance of an that can be added to .
///
/// Path to an executable file.
/// Arguments associated with the command-line operation. This value can be null.
/// Directory that contains either the executable file or the files that are used by the executable file. This value can be null.
public ExecAction(string path, string arguments = null, string workingDirectory = null)
{
this.Path = path;
this.Arguments = arguments;
this.WorkingDirectory = workingDirectory;
}
internal ExecAction(V1Interop.ITask task)
{
v1Task = task;
}
internal ExecAction(V2Interop.IExecAction action)
{
iAction = action;
}
internal override bool Bound
{
get
{
if (v1Task != null)
return true;
return base.Bound;
}
}
internal override void Bind(V1Interop.ITask v1Task)
{
object o = null;
unboundValues.TryGetValue("Path", out o);
v1Task.SetApplicationName(o == null ? string.Empty : o.ToString());
o = null;
unboundValues.TryGetValue("Arguments", out o);
v1Task.SetParameters(o == null ? string.Empty : o.ToString());
o = null;
unboundValues.TryGetValue("WorkingDirectory", out o);
v1Task.SetWorkingDirectory(o == null ? string.Empty : o.ToString());
}
///
/// Gets or sets the identifier of the action.
///
/// Not supported under Task Scheduler 1.0.
[DefaultValue(null)]
[XmlAttribute(AttributeName = "id", DataType = "ID")]
[XmlIgnore]
public override string Id
{
get
{
if (v1Task != null)
return System.IO.Path.GetFileNameWithoutExtension(Task.GetV1Path(v1Task)) + "_Action";
return base.Id;
}
set
{
if (v1Task != null)
throw new NotV1SupportedException();
base.Id = value;
}
}
///
/// Gets or sets the path to an executable file.
///
[XmlElement("Command")]
public string Path
{
get
{
if (v1Task != null)
return v1Task.GetApplicationName();
if (iAction != null)
return ((V2Interop.IExecAction)iAction).Path;
return unboundValues.ContainsKey("Path") ? (string)unboundValues["Path"] : null;
}
set
{
if (v1Task != null)
v1Task.SetApplicationName(value);
else if (iAction != null)
((V2Interop.IExecAction)iAction).Path = value;
else
unboundValues["Path"] = value;
}
}
///
/// Gets or sets the arguments associated with the command-line operation.
///
[DefaultValue("")]
public string Arguments
{
get
{
if (v1Task != null)
return v1Task.GetParameters();
if (iAction != null)
return ((V2Interop.IExecAction)iAction).Arguments;
return unboundValues.ContainsKey("Arguments") ? (string)unboundValues["Arguments"] : null;
}
set
{
if (v1Task != null)
v1Task.SetParameters(value);
else if (iAction != null)
((V2Interop.IExecAction)iAction).Arguments = value;
else
unboundValues["Arguments"] = value;
}
}
///
/// Gets or sets the directory that contains either the executable file or the files that are used by the executable file.
///
[DefaultValue("")]
public string WorkingDirectory
{
get
{
if (v1Task != null)
return v1Task.GetWorkingDirectory();
if (iAction != null)
return ((V2Interop.IExecAction)iAction).WorkingDirectory;
return unboundValues.ContainsKey("WorkingDirectory") ? (string)unboundValues["WorkingDirectory"] : null;
}
set
{
if (v1Task != null)
v1Task.SetWorkingDirectory(value);
else if (iAction != null)
((V2Interop.IExecAction)iAction).WorkingDirectory = value;
else
unboundValues["WorkingDirectory"] = value;
}
}
///
/// Copies the properties from another the current instance.
///
/// The source .
protected override void CopyProperties(Action sourceAction)
{
if (sourceAction.GetType() == this.GetType())
{
base.CopyProperties(sourceAction);
this.Path = ((ExecAction)sourceAction).Path;
this.Arguments = ((ExecAction)sourceAction).Arguments;
this.WorkingDirectory = ((ExecAction)sourceAction).WorkingDirectory;
}
}
///
/// Indicates whether the current object is equal to another object of the same type.
///
/// An object to compare with this object.
///
/// true if the current object is equal to the parameter; otherwise, false.
///
public override bool Equals(Action other)
{
return base.Equals(other) && this.Path == ((ExecAction)other).Path && this.Arguments == ((ExecAction)other).Arguments && this.WorkingDirectory == ((ExecAction)other).WorkingDirectory;
}
///
/// Gets a string representation of the .
///
/// String represention this action.
public override string ToString()
{
return string.Format(Properties.Resources.ExecAction, this.Path, this.Arguments, this.WorkingDirectory, this.Id);
}
}
///
/// An interface that exposes the ability to convert an actions functionality to a PowerShell script.
///
public interface IBindAsExecAction
{
///
/// Gets the PowerShell script for an action.
///
/// Single line PowerShell script string.
string GetPowerShellCommand();
}
///
/// Represents an action that sends an e-mail.
///
[XmlType(IncludeInSchema = false)]
[XmlRoot("SendEmail", Namespace = TaskDefinition.tns, IsNullable = false)]
public sealed class EmailAction : Action, IBindAsExecAction
{
///
/// Creates an unbound instance of .
///
public EmailAction()
{
}
///
/// Creates an unbound instance of .
///
/// Subject of the e-mail.
/// E-mail address that you want to send the e-mail from.
/// E-mail address or addresses that you want to send the e-mail to.
/// Body of the e-mail that contains the e-mail message.
/// Name of the server that you use to send e-mail from.
public EmailAction(string subject, string from, string to, string body, string mailServer)
{
this.Subject = subject;
this.From = from;
this.To = to;
this.Body = body;
this.Server = mailServer;
}
internal EmailAction(V2Interop.IEmailAction action)
{
iAction = action;
}
internal override void Bind(Microsoft.Win32.TaskScheduler.V2Interop.ITaskDefinition iTaskDef)
{
base.Bind(iTaskDef);
if (nvc != null)
nvc.Bind(((V2Interop.IEmailAction)iAction).HeaderFields);
}
///
/// Gets or sets the name of the server that you use to send e-mail from.
///
public string Server
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Server") ? (string)unboundValues["Server"] : null) : ((V2Interop.IEmailAction)iAction).Server; }
set { if (iAction == null) unboundValues["Server"] = value; else ((V2Interop.IEmailAction)iAction).Server = value; }
}
///
/// Gets or sets the subject of the e-mail.
///
[DefaultValue(null)]
public string Subject
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Subject") ? (string)unboundValues["Subject"] : null) : ((V2Interop.IEmailAction)iAction).Subject; }
set { if (iAction == null) unboundValues["Subject"] = value; else ((V2Interop.IEmailAction)iAction).Subject = value; }
}
///
/// Gets or sets the e-mail address or addresses that you want to send the e-mail to.
///
[DefaultValue(null)]
public string To
{
get { return (iAction == null) ? (unboundValues.ContainsKey("To") ? (string)unboundValues["To"] : null) : ((V2Interop.IEmailAction)iAction).To; }
set { if (iAction == null) unboundValues["To"] = value; else ((V2Interop.IEmailAction)iAction).To = value; }
}
///
/// Gets or sets the e-mail address or addresses that you want to Cc in the e-mail.
///
[DefaultValue(null)]
public string Cc
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Cc") ? (string)unboundValues["Cc"] : null) : ((V2Interop.IEmailAction)iAction).Cc; }
set { if (iAction == null) unboundValues["Cc"] = value; else ((V2Interop.IEmailAction)iAction).Cc = value; }
}
///
/// Gets or sets the e-mail address or addresses that you want to Bcc in the e-mail.
///
[DefaultValue(null)]
public string Bcc
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Bcc") ? (string)unboundValues["Bcc"] : null) : ((V2Interop.IEmailAction)iAction).Bcc; }
set { if (iAction == null) unboundValues["Bcc"] = value; else ((V2Interop.IEmailAction)iAction).Bcc = value; }
}
///
/// Gets or sets the e-mail address that you want to reply to.
///
[DefaultValue(null)]
public string ReplyTo
{
get { return (iAction == null) ? (unboundValues.ContainsKey("ReplyTo") ? (string)unboundValues["ReplyTo"] : null) : ((V2Interop.IEmailAction)iAction).ReplyTo; }
set { if (iAction == null) unboundValues["ReplyTo"] = value; else ((V2Interop.IEmailAction)iAction).ReplyTo = value; }
}
///
/// Gets or sets the e-mail address that you want to send the e-mail from.
///
[DefaultValue(null)]
public string From
{
get { return (iAction == null) ? (unboundValues.ContainsKey("From") ? (string)unboundValues["From"] : null) : ((V2Interop.IEmailAction)iAction).From; }
set { if (iAction == null) unboundValues["From"] = value; else ((V2Interop.IEmailAction)iAction).From = value; }
}
private NamedValueCollection nvc = null;
///
/// Gets or sets the header information in the e-mail message to send.
///
[XmlArray]
[XmlArrayItem("HeaderField", typeof(NameValuePair))]
public NamedValueCollection HeaderFields
{
get
{
if (nvc == null)
{
if (iAction != null)
nvc = new NamedValueCollection(((V2Interop.IEmailAction)iAction).HeaderFields);
else
nvc = new NamedValueCollection();
}
return nvc;
}
}
///
/// Gets or sets the body of the e-mail that contains the e-mail message.
///
[DefaultValue(null)]
public string Body
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Body") ? (string)unboundValues["Body"] : null) : ((V2Interop.IEmailAction)iAction).Body; }
set { if (iAction == null) unboundValues["Body"] = value; else ((V2Interop.IEmailAction)iAction).Body = value; }
}
///
/// Gets or sets an array of file paths to be sent as attachments with the e-mail. Each item must be a value containing a path to file.
///
[XmlArray("Attachments", IsNullable=true)]
[XmlArrayItem(typeof(string), ElementName = "File")]
public object[] Attachments
{
get { return (iAction == null) ? (unboundValues.ContainsKey("Attachments") ? (object[])unboundValues["Attachments"] : null) : ((V2Interop.IEmailAction)iAction).Attachments; }
set
{
if (value != null)
{
if (value.Length > 8)
throw new ArgumentOutOfRangeException("Attachments", "Attachments array cannot contain more than 8 items.");
foreach (var o in value)
if (!(o is string) || !System.IO.File.Exists((string)o))
throw new ArgumentException("Each value of the array must contain a valid file reference.", "Attachments");
}
if (iAction == null)
{
if (value == null || value.Length == 0)
unboundValues.Remove("Attachments");
else
unboundValues["Attachments"] = value;
}
else
((V2Interop.IEmailAction)iAction).Attachments = value;
}
}
///
/// Copies the properties from another the current instance.
///
/// The source .
protected override void CopyProperties(Action sourceAction)
{
if (sourceAction.GetType() == this.GetType())
{
base.CopyProperties(sourceAction);
if (((EmailAction)sourceAction).Attachments != null)
this.Attachments = (object[])((EmailAction)sourceAction).Attachments.Clone();
this.Bcc = ((EmailAction)sourceAction).Bcc;
this.Body = ((EmailAction)sourceAction).Body;
this.Cc = ((EmailAction)sourceAction).Cc;
this.From = ((EmailAction)sourceAction).From;
if (((EmailAction)sourceAction).nvc != null)
((EmailAction)sourceAction).HeaderFields.CopyTo(this.HeaderFields);
this.ReplyTo = ((EmailAction)sourceAction).ReplyTo;
this.Server = ((EmailAction)sourceAction).Server;
this.Subject = ((EmailAction)sourceAction).Subject;
this.To = ((EmailAction)sourceAction).To;
}
}
///
/// Indicates whether the current object is equal to another object of the same type.
///
/// An object to compare with this object.
///
/// true if the current object is equal to the parameter; otherwise, false.
///
public override bool Equals(Action other)
{
return base.Equals(other) && (this as IBindAsExecAction).GetPowerShellCommand() == (other as IBindAsExecAction).GetPowerShellCommand();
}
///
/// Gets a string representation of the .
///
/// String represention this action.
public override string ToString()
{
return string.Format(Properties.Resources.EmailAction, this.Subject, this.To, this.Cc, this.Bcc, this.From, this.ReplyTo, this.Body, this.Server, this.Id);
}
private static string FromUTF8(string s)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
return System.Text.Encoding.Default.GetString(bytes);
}
private static string ToUTF8(string s)
{
byte[] bytes = System.Text.Encoding.Default.GetBytes(s);
return System.Text.Encoding.UTF8.GetString(bytes);
}
string IBindAsExecAction.GetPowerShellCommand()
{
// Send-MailMessage [-To] [-Subject] [[-Body] ] [[-SmtpServer] ] -From [-Attachments ]
// [-Bcc ] [-BodyAsHtml] [-Cc ] [-Credential ] [-DeliveryNotificationOption ]
// [-Encoding ] [-Port ] [-Priority ] [-UseSsl] [ ]
bool bodyIsHtml = this.Body != null && this.Body.Trim().StartsWith("<") && this.Body.Trim().EndsWith(">");
var sb = new System.Text.StringBuilder();
sb.AppendFormat("Send-MailMessage -From '{0}' -Subject '{1}' -SmtpServer '{2}' -Encoding UTF8", Prep(this.From), ToUTF8(Prep(this.Subject)), Prep(this.Server));
if (!string.IsNullOrEmpty(this.To))
sb.AppendFormat(" -To {0}", ToPS(this.To));
if (!string.IsNullOrEmpty(this.Cc))
sb.AppendFormat(" -Cc {0}", ToPS(this.Cc));
if (!string.IsNullOrEmpty(this.Bcc))
sb.AppendFormat(" -Bcc {0}", ToPS(this.Bcc));
if (bodyIsHtml)
sb.Append(" -BodyAsHtml");
if (!string.IsNullOrEmpty(this.Body))
sb.AppendFormat(" -Body '{0}'", ToUTF8(Prep(this.Body)));
if (this.Attachments != null && this.Attachments.Length > 0)
sb.AppendFormat(" -Attachments {0}", ToPS(Array.ConvertAll