Contents
The Guadagno Task Scheduler is a Windows Service application that allows you to create tasks that can be scheduled to run in a variety of different times and patterns. The tasks are .NET v2.0 assemblies that inherit from the ITaskPlugin
interface. For more information on the ITaskPlugin
interface, please visit the CodeProject article at http://www.codeproject.com/KB/macros/TaskPlugin.aspx or the project homepage on SourceForge at http://taskplugin.sourceforge.net. This project has been released to the community. Visit the CodePlex project at http://www.codeplex.com/taskservice.
The Guadagno Task Scheduler will look for tasks (plug-ins) to execute by searching the directory specified in the PluginPath configuration section (see the Configuration section). If this value is not found, the default directory of Plugins folder beneath the root of the installation will be used.
Folder | | |
Installation directory | | Contains the task scheduler and support files. |
\Logs | | Contains the log files for the task scheduler and plug-ins. |
\Plugins | | Contains the plug-ins (the default directory that the task scheduler looks in for plug-ins). |
The Guadagno Task Scheduler does not use the typical .NET configuration file; the application uses an XML file for configuration that derives from the Guadagno.Utilities.Configuration.ConfigurationBase
class. Look for an article on this class in the near future. This class allows for you to dynamically change the configuration or provide different configuration parameters depending on the name of the machine the application is running on.
<application.settings stage="auto">
<hosts>
<host name="uatMachinename" stage="uat" comment="" />
<host name="prodMachinename" stage="prod" comment="" />
</hosts>
<stage name="default">
</stage>
<stage name="uat">
</stage>
<stage name="prod">
</stage>
</application.settings>
The root element of the configuration file is the <application.settings>
element. <application.settings>
has 2+ child nodes: <hosts>
and <stage>
. <application.settings>
has an attribute named stage
which indicates which stage
element to load. The <stage>
attribute can contain one of the following values:
<application.settings stage="Value">
auto | | A value of auto reads the machine name; that is the service is running on and looks in the <hosts> section for the appropriate stage to load. |
stage name | | Explicitly loads the stage. |
The default stage is always read and used to provide the default values for the properties of the application. After the default section is read, the configuration class will load the configuration based on the stage
attribute for the <application.settings>
element.
This property is used to instruct the Guadagno Task Scheduler the directory you wish to use. This property overrides the default directory of \Plugins underneath the installation directory.
This property is used to provide the log4net configuration for the Guadagno Task Scheduler. The basic configuration provides a number of different log4net appenders, rolling file, Telnet, and SMTP.
Creating a plug-in or task is as easy as implementing the ITaskPlugin
interface. This interface is provided in the .NET assembly TaskPluginInterface.dll.

A sample implementation of the ITaskPlugin
interface. For a more complete example, please refer to the article: 'A Flexible .NET Plug-in Architecture, by Joseph Guadagno'.
[TaskPluginInterface.Plugin(PluginType.Unknown)]
public class PluginShell : ITaskPlugin
{
#region ITaskPlugin Members
#region ITaskPlugin Properties
public string Name
{
get { return "My sample Task"; }
}
public string Description
{
get { return "My first test plug-in"; }
}
public string Extension
{
get { return "The extension that this plug-in handles (not implemented)"; }
}
public string ExtensionDescription
{
get { return "A description of the extension (not implemented)"; }
}
public string Version
{
get { return "1.0.0.1"; }
}
public string Author
{
get { return "Joseph Guadagno"; }
}
public List<ischeduleditem> Schedule
{
get { return m_Schedule; }
}
#endregion ITaskPlugin Properties
#region ITaskPlugin Methods
public ExecuteResult Execute()
{
try
{
m_Progress.TotalTasks = 1;
m_Progress.TotalItems = 1;
m_Progress.CurrentTask = 0;
m_Progress.CurrentItem = 0;
m_Cancel = false;
m_Log.Debug(Properties.Resources.Execute_Started);
if (EventStart != null)
EventStart(this, new PluginEventArgs(m_Progress,
"Starting the task.", null));
DoWork();
if (EventEnd != null)
{
if (m_Cancel)
{
EventEnd(this, new PluginEventArgs(m_Progress,
"Task execution was cancelled.", null));
}
else
{
EventEnd(this, new PluginEventArgs(m_Progress,
"Task execution is complete.", null));
}
}
if (m_Cancel)
{
m_Log.DebugFormat(Properties.Resources.Execute_Ended,
ExecuteResult.Cancelled);
return ExecuteResult.Cancelled;
}
else
{
m_Log.DebugFormat(Properties.Resources.Execute_Ended,
ExecuteResult.Ok);
return ExecuteResult.Ok;
}
}
catch (Exception ex)
{
if (EventExceptionOccurred != null)
EventExceptionOccurred(this, new PluginEventArgs(m_Progress,
"", ex));
return ExecuteResult.Exception;
}
}
public bool Cancel()
{
m_Log.Debug(Properties.Resources.CancelMethodExecuted);
m_Cancel = true;
return true;
}
#endregion ITaskPlugin Methods
#region ITaskPlugin Events
public event OnStart EventStart;
public event OnEnd EventEnd;
public event OnProcessing EventProcessing;
public event OnExceptionOccurred EventExceptionOccurred;
#endregion ITaskPlugin Events
#endregion
#region Private Methods
private ExecuteResult DoWork()
{
int longLoop = 120;
m_Progress.CurrentItem = 0;
m_Progress.TotalItems = longLoop;
m_Log.Debug(Properties.Resources.StartingToDoWork);
for (int x = 1; x < longLoop; x++)
{
System.Threading.Thread.Sleep(50);
m_Log.DebugFormat(Properties.Resources.WorkingOn, x);
m_Progress.CurrentItem = x;
if (EventProcessing != null)
{
PluginEventArgs evt = new PluginEventArgs(m_Progress,
"Working", null);
EventProcessing(this, evt);
if (evt.Cancel == true)
{
m_Log.Debug(Properties.Resources.CancelRequestRecieved);
m_Cancel = true;
break;
}
}
}
if (m_Cancel)
return ExecuteResult.Cancelled;
else
{
m_Progress.CurrentTask++;
return ExecuteResult.Ok;
}
}
#endregion Private Methods
}
The schedule for each task is provided by the task itself. Once the Task Scheduler "discovers" a task within its plug-in directory, it will retrieve the schedule by examining the schedule
property. The scheduling component uses the .NET scheduled timer library written by Andrew Brummer (see reference below).
The plug-in can "hard code" the schedule, which is not recommended, or load it from a configuration file. To make it easier for placing the schedule in a configuration file, I encapsulated the different schedule types (IScheduledItem
) available from the .NET scheduled timer library into an XML file and provided a utility function, TaskPluginInterface.ScheduleConfig.Load()
, to parse the configuration.
An example configuration file:
<Schedule>
<ScheduledTime Base="ByMinute" Offset="1,0" />
<SimpleInterval StartTime="1/7/08" Interval="5" EndTime="1/15/08"/>
<SimpleInterval StartTime="1/1/08" Interval="15" />
<SimpleInterval StartTime="1/2/08" Interval="20" Count="5"/>
<SingleEvent EventTime="1/15/08" />
<EventQueue>
<ScheduledTime Base="ByMinute" Offset="15,0" />
<ScheduledTime Base="ByMinute" Offset="30,0" />
</EventQueue>
<BlockWrapper Base="Daily" BeginOffset="6:00 AM" EndOffset="5:00 PM">
<ScheduledTime Base="ByMinute" Offset="15,0" />
</BlockWrapper>
</Schedule>
For more details on TaskPluginInterface
, please checkout the CodeProject article at http://www.codeproject.com/KB/macros/TaskPlugin.aspx or the project page at http://taskplugin.sourceforge.net.
- Refresh / reload the plug-ins when there are directory changes
- Enable the plug-ins to have / use their own log files
Version | Date | What was done |
1.0.0.1 | 5/14/07 | Created the initial release of the file. |