diff --git a/Baget/UtilidadesTSL4net.c.nuspec b/Baget/UtilidadesTSL4net.c.nuspec
new file mode 100644
index 0000000..9b197b2
--- /dev/null
+++ b/Baget/UtilidadesTSL4net.c.nuspec
@@ -0,0 +1,18 @@
+
+
+
+ UtilidadesTSL4net.c
+ 1.0.0.0
+ Manuel
+ Tecnosis S.A.
+ false
+ Utilidades c# WPF Tecnosis.
+ UtilidadesTSL4net.c .net48
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Baget/nuget.exe b/Baget/nuget.exe
new file mode 100644
index 0000000..94aada9
Binary files /dev/null and b/Baget/nuget.exe differ
diff --git a/EventStorage.cs b/EventStorage.cs
new file mode 100644
index 0000000..f3b3b4f
--- /dev/null
+++ b/EventStorage.cs
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// Null event strorage disables error recovery by returning now for the last time an event fired.
+ ///
+ public class NullEventStorage : IEventStorage
+ {
+ public NullEventStorage()
+ {
+ }
+
+ public void RecordLastTime(DateTime Time)
+ {
+ }
+
+ public DateTime ReadLastTime()
+ {
+ return DateTime.Now;
+ }
+ }
+
+ ///
+ /// Local event strorage keeps the last time in memory so that skipped events are not recovered.
+ ///
+ public class LocalEventStorage : IEventStorage
+ {
+ public LocalEventStorage()
+ {
+ _LastTime = DateTime.MaxValue;
+ }
+
+ public void RecordLastTime(DateTime Time)
+ {
+ _LastTime = Time;
+ }
+
+ public DateTime ReadLastTime()
+ {
+ if (_LastTime == DateTime.MaxValue)
+ _LastTime = DateTime.Now;
+ return _LastTime;
+ }
+
+ DateTime _LastTime;
+ }
+
+ ///
+ /// FileEventStorage saves the last time in an XmlDocument so that recovery will include periods that the
+ /// process is shutdown.
+ ///
+ public class FileEventStorage : IEventStorage
+ {
+ public FileEventStorage(string FileName, string XPath)
+ {
+ _FileName = FileName;
+ _XPath = XPath;
+ }
+
+ public void RecordLastTime(DateTime Time)
+ {
+ _Doc.SelectSingleNode(_XPath).Value = Time.ToString();
+ _Doc.Save(_FileName);
+ }
+
+ public DateTime ReadLastTime()
+ {
+ _Doc.Load(_FileName);
+ string Value = _Doc.SelectSingleNode(_XPath).Value;
+ if (Value == null || Value == string.Empty)
+ return DateTime.Now;
+ return DateTime.Parse(Value);
+ }
+
+ string _FileName;
+ string _XPath;
+ XmlDocument _Doc = new XmlDocument();
+ }
+}
diff --git a/IScheduledItem.cs b/IScheduledItem.cs
new file mode 100644
index 0000000..bd23e0b
--- /dev/null
+++ b/IScheduledItem.cs
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// IScheduledItem represents a scheduled event. You can query it for the number of events that occur
+ /// in a time interval and for the remaining interval before the next event.
+ ///
+ public interface IScheduledItem
+ {
+ ///
+ /// Returns the times of the events that occur in the given time interval. The interval is closed
+ /// at the start and open at the end so that intervals can be stacked without overlapping.
+ ///
+ /// The beginning of the interval
+ /// The end of the interval
+ /// All events >= Begin and < End
+ void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List);
+
+ ///
+ /// Returns the next run time of the scheduled item. Optionally excludes the starting time.
+ ///
+ /// The starting time of the interval
+ /// if true then the starting time is included in the query false, it is excluded.
+ /// The next execution time either on or after the starting time.
+ DateTime NextRunTime(DateTime time, bool IncludeStartTime);
+ }
+
+}
diff --git a/MethodCall.cs b/MethodCall.cs
new file mode 100644
index 0000000..a0f39b7
--- /dev/null
+++ b/MethodCall.cs
@@ -0,0 +1,332 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// IParameterSetter represents a serialized parameter list. This is used to provide a partial specialized
+ /// method call. This is useful for remote invocation of method calls. For example if you have a method with
+ /// 3 parameters. The first 2 might represent static data such as a report and a storage location. The third
+ /// might be the time that the report is invoked, which is only known when the method is invoked. Using this,
+ /// you just pass the method and the first 2 parameters to a timer object, which supplies the 3rd parameter.
+ /// Without these objects, you would have to generate a custom object type for each method you wished to
+ /// execute in this manner and store the static parameters as instance variables.
+ ///
+ public interface IParameterSetter
+ {
+ ///
+ /// This resets the setter to the beginning. It is used for setters that rely on positional state
+ /// information. It is called prior to setting any method values.
+ ///
+ void reset();
+ ///
+ /// This method is used to both query support for setting a parameter and actually set the value.
+ /// True is returned if the parameter passed in is updated.
+ ///
+ /// The reflection information about this parameter.
+ /// The location of the prameter in the parameter list.
+ /// The parameter object
+ /// true if the parameter is matched and false otherwise
+ bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter);
+ }
+
+ ///
+ /// This setter object takes a simple object array full of parameter data. It applys the objects in order
+ /// to the method parameter list.
+ ///
+ public class OrderParameterSetter : IParameterSetter
+ {
+ public OrderParameterSetter(params object[] _Params)
+ {
+ _ParamList = _Params;
+ }
+ public void reset()
+ {
+ _counter = 0;
+ }
+ public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
+ {
+ if (_counter >= _ParamList.Length)
+ return false;
+ parameter = _ParamList[_counter++];
+ return true;
+ }
+
+ object[] _ParamList;
+ int _counter;
+ }
+
+ ///
+ /// This setter object stores the parameter data in a Hashtable and uses the hashtable keys to match
+ /// the parameter names of the method to the parameter data. This allows methods to be called like
+ /// stored procedures, with the parameters being passed in independent of order.
+ ///
+ public class NamedParameterSetter : IParameterSetter
+ {
+ public NamedParameterSetter(Hashtable Params)
+ {
+ _Params = Params;
+ }
+ public void reset()
+ {
+ }
+ public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
+ {
+ string ParamName = pi.Name;
+ if (!_Params.ContainsKey(ParamName))
+ return false;
+ parameter = _Params[ParamName];
+ return true;
+ }
+ Hashtable _Params;
+ }
+
+
+ ///
+ /// ParameterSetterList maintains a collection of IParameterSetter objects and applies them in order to each
+ /// parameter of the method. Each time a match occurs the next parameter is tried starting with the first
+ /// setter object until it is matched.
+ ///
+ public class ParameterSetterList
+ {
+ public void Add(IParameterSetter setter)
+ {
+ _List.Add(setter);
+ }
+
+ public IParameterSetter[] ToArray()
+ {
+ return (IParameterSetter[])_List.ToArray(typeof(IParameterSetter));
+ }
+
+ public void reset()
+ {
+ foreach(IParameterSetter Setter in _List)
+ Setter.reset();
+ }
+
+ public object[] GetParameters(MethodInfo Method)
+ {
+ ParameterInfo[] Params = Method.GetParameters();
+ object[] Values = new object[Params.Length];
+ //TODO: Update to iterate backwards
+ for(int i=0; i
+ /// IMethodCall represents a partially specified parameter data list and a method. This allows methods to be
+ /// dynamically late invoked for things like timers and other event driven frameworks.
+ ///
+ public interface IMethodCall
+ {
+ ParameterSetterList ParamList { get; }
+ object Execute();
+ object Execute(IParameterSetter Params);
+ void EventHandler(object obj, EventArgs e);
+ IAsyncResult BeginExecute(AsyncCallback callback, object obj);
+ IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj);
+ }
+
+ delegate object Exec();
+ delegate object Exec2(IParameterSetter Params);
+
+ ///
+ /// Method call captures the data required to do a defered method call.
+ ///
+ public class DelegateMethodCall : MethodCallBase, IMethodCall
+ {
+ public DelegateMethodCall(Delegate f)
+ {
+ _f = f;
+ }
+
+ public DelegateMethodCall(Delegate f, params object[] Params)
+ {
+ if (f.Method.GetParameters().Length < Params.Length)
+ throw new ArgumentException("Too many parameters specified for delegate", "f");
+
+ _f = f;
+ ParamList.Add(new OrderParameterSetter(Params));
+ }
+
+ public DelegateMethodCall(Delegate f, IParameterSetter Params)
+ {
+ _f = f;
+ ParamList.Add(Params);
+ }
+
+ Delegate _f;
+
+ public Delegate f
+ {
+ get { return _f; }
+ set { _f = value; }
+ }
+
+ public MethodInfo Method
+ {
+ get { return _f.Method; }
+ }
+
+ public object Execute()
+ {
+ return f.DynamicInvoke(GetParameterList(Method));
+ }
+
+ public object Execute(IParameterSetter Params)
+ {
+ return f.DynamicInvoke(GetParameterList(Method, Params));
+ }
+
+ public void EventHandler(object obj, EventArgs e)
+ {
+ Execute();
+ }
+
+ Exec _exec;
+ public IAsyncResult BeginExecute(AsyncCallback callback, object obj)
+ {
+ _exec = new Exec(Execute);
+ return _exec.BeginInvoke(callback, obj);
+ }
+
+ public IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj)
+ {
+ Exec2 exec = new Exec2(Execute);
+ return exec.BeginInvoke(Params, callback, obj);
+ }
+ }
+
+ public class DynamicMethodCall : MethodCallBase, IMethodCall
+ {
+ public DynamicMethodCall(MethodInfo method)
+ {
+ _obj = null;
+ _method = method;
+ }
+
+ public DynamicMethodCall(object obj, MethodInfo method)
+ {
+ _obj = obj;
+ _method = method;
+ }
+
+ public DynamicMethodCall(object obj, MethodInfo method, IParameterSetter setter)
+ {
+ _obj = obj;
+ _method = method;
+ ParamList.Add(setter);
+ }
+
+ object _obj;
+ MethodInfo _method;
+
+ public MethodInfo Method
+ {
+ get { return _method; }
+ set { _method = value; }
+ }
+
+ public object Execute()
+ {
+ return _method.Invoke(_obj, GetParameterList(Method));
+ }
+
+ public object Execute(IParameterSetter Params)
+ {
+ return _method.Invoke(_obj, GetParameterList(Method, Params));
+ }
+
+ public void EventHandler(object obj, EventArgs e)
+ {
+ Execute();
+ }
+
+ Exec _exec;
+ public IAsyncResult BeginExecute(AsyncCallback callback, object obj)
+ {
+ _exec = new Exec(Execute);
+ return _exec.BeginInvoke(callback, null);
+ }
+
+ public IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj)
+ {
+ Exec2 exec = new Exec2(Execute);
+ return exec.BeginInvoke(Params, callback, null);
+ }
+ }
+
+ ///
+ /// This is a base class that handles the Parameter list management for the 2 dynamic method call methods.
+ ///
+ public class MethodCallBase
+ {
+ ParameterSetterList _ParamList = new ParameterSetterList();
+
+ public ParameterSetterList ParamList
+ {
+ get { return _ParamList; }
+ }
+
+ protected object[] GetParameterList(MethodInfo Method)
+ {
+ ParamList.reset();
+ object[] Params = ParamList.GetParameters(Method);
+ return Params;
+ }
+
+ protected object[] GetParameterList(MethodInfo Method, IParameterSetter Params)
+ {
+ ParamList.reset();
+ object[] objParams = ParamList.GetParameters(Method, Params);
+ return objParams;
+ }
+ }
+
+}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f9af44f
--- /dev/null
+++ b/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// La información general sobre un ensamblado se controla mediante el siguiente
+// conjunto de atributos. Cambie estos atributos para modificar la información
+// asociada con un ensamblado.
+[assembly: AssemblyTitle("UtilidadesTSL4net.c")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany(".")]
+[assembly: AssemblyProduct("UtilidadesTSL4net.c")]
+[assembly: AssemblyCopyright("© . 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Si establece ComVisible como false hace que los tipos de este ensamblado no sean visibles
+// a los componentes COM. Si necesita obtener acceso a un tipo en este ensamblado desde
+// COM, establezca el atributo ComVisible como true en este tipo.
+[assembly: ComVisible(false)]
+
+// El siguiente GUID sirve como identificador de la biblioteca de tipos si este proyecto se expone a COM
+[assembly: Guid("51c70542-3016-463d-8d03-d306aae697f8")]
+
+// La información de versión de un ensamblado consta de los cuatro valores siguientes:
+//
+// Versión principal
+// Versión secundaria
+// Número de versión de compilación
+// Revisión
+//
+// Puede especificar todos los valores o puede establecer como valores predeterminados los números de revisión y generación
+// mediante el asterisco ('*'), como se muestra a continuación:
+[assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyFileVersion("1.0.*")]
diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..0907d74
--- /dev/null
+++ b/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// Este código fue generado por una herramienta.
+// Versión de runtime:4.0.30319.42000
+//
+// Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si
+// se vuelve a generar el código.
+//
+//------------------------------------------------------------------------------
+
+namespace Utilidadescsharp.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Properties/Settings.settings b/Properties/Settings.settings
new file mode 100644
index 0000000..049245f
--- /dev/null
+++ b/Properties/Settings.settings
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/ReportTimer.cs b/ReportTimer.cs
new file mode 100644
index 0000000..3a2f2a7
--- /dev/null
+++ b/ReportTimer.cs
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+
+namespace UtilidadesCSharp.Schedule
+{
+ public class ReportEventArgs : EventArgs
+ {
+ public ReportEventArgs(DateTime Time, int reportNo) { EventTime = Time; ReportNo = reportNo; }
+ public int ReportNo;
+ public DateTime EventTime;
+ }
+
+ public delegate void ReportEventHandler(object sender, ReportEventArgs e);
+
+ ///
+ /// Summary description for ReportTimer.
+ ///
+ public class ReportTimer : ScheduleTimerBase
+ {
+ public void AddReportEvent(IScheduledItem Schedule, int reportNo)
+ {
+ if (Elapsed == null)
+ throw new Exception("You must set elapsed before adding Events");
+ AddJob(new TimerJob(Schedule, new DelegateMethodCall(Handler, Elapsed, reportNo)));
+ }
+
+ public void AddAsyncReportEvent(IScheduledItem Schedule, int reportNo)
+ {
+ if (Elapsed == null)
+ throw new Exception("You must set elapsed before adding Events");
+ TimerJob Event = new TimerJob(Schedule, new DelegateMethodCall(Handler, Elapsed, reportNo));
+ Event.SyncronizedEvent = false;
+ AddJob(Event);
+ }
+
+ public event ReportEventHandler Elapsed;
+
+ delegate void ConvertHandler(ReportEventHandler Handler, int ReportNo, object sender, DateTime time);
+ static ConvertHandler Handler = new ConvertHandler(Converter);
+ static void Converter(ReportEventHandler Handler, int ReportNo, object sender, DateTime time)
+ {
+ if (Handler == null)
+ throw new ArgumentNullException("Handler");
+ if (sender == null)
+ throw new ArgumentNullException("sender");
+ Handler(sender, new ReportEventArgs(time, ReportNo));
+ }
+ }
+}
diff --git a/ScheduleFilter.cs b/ScheduleFilter.cs
new file mode 100644
index 0000000..466e6a9
--- /dev/null
+++ b/ScheduleFilter.cs
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// This is an empty filter that does not filter any of the events.
+ ///
+ public class Filter : IResultFilter
+ {
+ public static IResultFilter Empty = new Filter();
+ private Filter() {}
+
+ public void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List)
+ {
+ if (List == null)
+ return;
+ List.Sort();
+ }
+ }
+
+ ///
+ /// This causes only the first event of the interval to be counted.
+ ///
+ public class FirstEventFilter : IResultFilter
+ {
+ public static IResultFilter Filter = new FirstEventFilter();
+ private FirstEventFilter() {}
+
+ public void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List)
+ {
+ if (List == null)
+ return;
+ if (List.Count < 2)
+ return;
+ List.Sort();
+ List.RemoveRange(1, List.Count-1);
+ }
+ }
+
+ ///
+ /// This causes only the last event of the interval to be counted.
+ ///
+ public class LastEventFilter : IResultFilter
+ {
+ public static IResultFilter Filter = new LastEventFilter();
+ private LastEventFilter() {}
+
+ public void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List)
+ {
+ if (List == null)
+ return;
+ if (List.Count < 2)
+ return;
+ List.Sort();
+ List.RemoveRange(0, List.Count-1);
+ }
+ }
+
+}
diff --git a/ScheduleTimer.cs b/ScheduleTimer.cs
new file mode 100644
index 0000000..acace75
--- /dev/null
+++ b/ScheduleTimer.cs
@@ -0,0 +1,254 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Timers;
+using System.Diagnostics;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// ScheduleTimer represents a timer that fires on a more human friendly schedule. For example it is easy to
+ /// set it to fire every day at 6:00PM. It is useful for batch jobs or alarms that might be difficult to
+ /// schedule with the native .net timers.
+ /// It is similar to the .net timer that it is based on with the start and stop methods functioning similarly.
+ /// The main difference is the event uses a different delegate and arguement since the .net timer argument
+ /// class is not creatable.
+ ///
+ public class ScheduleTimerBase : IDisposable
+ {
+ public ScheduleTimerBase()
+ {
+ _Timer = new Timer();
+ _Timer.AutoReset = false;
+ _Timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
+ _Jobs = new TimerJobList();
+ _LastTime = DateTime.MaxValue;
+ }
+
+ ///
+ /// Adds a job to the timer. This method passes in a delegate and the parameters similar to the Invoke method of windows forms.
+ ///
+ /// The schedule that this delegate is to be run on.
+ /// The delegate to run
+ /// The method parameters to pass if you leave any DateTime parameters unbound, then they will be set with the scheduled run time of the
+ /// method. Any unbound object parameters will get this Job object passed in.
+ public void AddJob(IScheduledItem Schedule, Delegate f, params object[] Params)
+ {
+ _Jobs.Add(new TimerJob(Schedule, new DelegateMethodCall(f, Params)));
+ }
+
+ ///
+ /// Adds a job to the timer to operate asyncronously.
+ ///
+ /// The schedule that this delegate is to be run on.
+ /// The delegate to run
+ /// The method parameters to pass if you leave any DateTime parameters unbound, then they will be set with the scheduled run time of the
+ /// method. Any unbound object parameters will get this Job object passed in.
+ public void AddAsyncJob(IScheduledItem Schedule, Delegate f, params object[] Params)
+ {
+ TimerJob Event = new TimerJob(Schedule, new DelegateMethodCall(f, Params));
+ Event.SyncronizedEvent = false;
+ _Jobs.Add(Event);
+ }
+
+ ///
+ /// Adds a job to the timer.
+ ///
+ ///
+ public void AddJob(TimerJob Event)
+ {
+ _Jobs.Add(Event);
+ }
+
+ ///
+ /// Clears out all scheduled jobs.
+ ///
+ public void ClearJobs()
+ {
+ _Jobs.Clear();
+ }
+
+ ///
+ /// Begins executing all assigned jobs at the scheduled times
+ ///
+ public void Start()
+ {
+ _StopFlag = false;
+ QueueNextTime(EventStorage.ReadLastTime());
+ }
+
+ ///
+ /// Halts executing all jobs. When the timer is restarted all jobs that would have run while the timer was stopped are re-tried.
+ ///
+ public void Stop()
+ {
+ _StopFlag = true;
+ _Timer.Stop();
+ }
+
+ ///
+ /// EventStorage determines the method used to store the last event fire time. It defaults to keeping it in memory.
+ ///
+ public IEventStorage EventStorage = new LocalEventStorage();
+ public event ExceptionEventHandler Error;
+
+ #region Private Methods and Fields
+ ///
+ /// This is here to enhance accuracy. Even if nothing is scheduled the timer sleeps for a maximum of 1 minute.
+ ///
+ private static TimeSpan MAX_INTERVAL = new TimeSpan(0, 1, 0);
+
+ private DateTime _LastTime;
+ private Timer _Timer;
+ private TimerJobList _Jobs;
+ private volatile bool _StopFlag;
+
+ private double NextInterval(DateTime thisTime)
+ {
+ TimeSpan interval = _Jobs.NextRunTime(thisTime)-thisTime;
+ if (interval > MAX_INTERVAL)
+ interval = MAX_INTERVAL;
+ //Handles the case of 0 wait time, the interval property requires a duration > 0.
+ return (interval.TotalMilliseconds == 0) ? 1 : interval.TotalMilliseconds;
+ }
+
+ private void QueueNextTime(DateTime thisTime)
+ {
+ _Timer.Interval = NextInterval(thisTime);
+ System.Diagnostics.Debug.WriteLine(_Timer.Interval);
+ _LastTime = thisTime;
+ EventStorage.RecordLastTime(thisTime);
+ _Timer.Start();
+ }
+
+ private void Timer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ try
+ {
+ if (_Jobs == null)
+ return;
+
+ _Timer.Stop();
+
+ foreach(TimerJob Event in _Jobs.Jobs)
+ {
+ try { Event.Execute(this, _LastTime, e.SignalTime, Error); }
+ catch (Exception ex) { OnError(DateTime.Now, Event, ex); }
+ }
+ }
+ catch (Exception ex)
+ {
+ OnError(DateTime.Now, null, ex);
+ }
+ finally
+ {
+ if (_StopFlag == false)
+ QueueNextTime(e.SignalTime);
+ }
+ }
+
+ private void OnError(DateTime eventTime, TimerJob job, Exception e)
+ {
+ if (Error == null)
+ return;
+
+ try { Error(this, new ExceptionEventArgs(eventTime, e)); }
+ catch (Exception) {}
+ }
+ #endregion
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ if (_Timer != null)
+ _Timer.Dispose();
+ }
+
+ #endregion
+ }
+
+ public class ScheduleTimer : ScheduleTimerBase
+ {
+ ///
+ /// Add event is used in conjunction with the Elaspsed event handler. Set the Elapsed handler, add your schedule and call start.
+ ///
+ /// The schedule to fire the event at. Adding additional schedules will cause the event to fire whenever either schedule calls for it.
+ public void AddEvent(IScheduledItem Schedule)
+ {
+ if (Elapsed == null)
+ throw new ArgumentNullException("Elapsed", "member variable is null.");
+
+ AddJob(new TimerJob(Schedule, new DelegateMethodCall(Elapsed)));
+ }
+
+ ///
+ /// The event to fire when you only need to fire one event.
+ ///
+ public event ScheduledEventHandler Elapsed;
+ }
+
+ ///
+ /// ExceptionEventArgs allows exceptions to be captured and sent to the OnError event of the timer.
+ ///
+ public class ExceptionEventArgs : EventArgs
+ {
+ public ExceptionEventArgs(DateTime eventTime, Exception e)
+ {
+ EventTime = eventTime;
+ Error = e;
+ }
+ public DateTime EventTime;
+ public Exception Error;
+ }
+
+ ///
+ /// ExceptionEventHandler is the method type used by the OnError event for the timer.
+ ///
+ public delegate void ExceptionEventHandler(object sender, ExceptionEventArgs Args);
+
+ public class ScheduledEventArgs : EventArgs
+ {
+ public ScheduledEventArgs(DateTime eventTime)
+ {
+ EventTime = eventTime;
+ }
+ public DateTime EventTime;
+ }
+
+ public delegate void ScheduledEventHandler(object sender, ScheduledEventArgs e);
+
+ ///
+ /// The IResultFilter interface represents filters that either sort the events for an interval or
+ /// remove duplicate events either selecting the first or the last event.
+ ///
+ public interface IResultFilter
+ {
+ void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List);
+ }
+
+ ///
+ /// IEventStorage is used to provide persistance of schedule during service shutdowns.
+ ///
+ public interface IEventStorage
+ {
+ void RecordLastTime(DateTime Time);
+ DateTime ReadLastTime();
+ }
+
+
+}
\ No newline at end of file
diff --git a/ScheduledItems/BlockWrapper.cs b/ScheduledItems/BlockWrapper.cs
new file mode 100644
index 0000000..3427f75
--- /dev/null
+++ b/ScheduledItems/BlockWrapper.cs
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// This class will be used to implement a filter that enables a window of activity. For cases where you want to
+ /// run every 15 minutes between 6:00 AM and 5:00 PM. Or just on weekdays or weekends.
+ ///
+ public class BlockWrapper : IScheduledItem
+ {
+ public BlockWrapper(IScheduledItem item, string StrBase, string BeginOffset, string EndOffset)
+ {
+ _Item = item;
+ _Begin = new ScheduledTime(StrBase, BeginOffset);
+ _End = new ScheduledTime(StrBase, EndOffset);
+ }
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ DateTime Next = NextRunTime(Begin, true);
+ while (Next < End)
+ {
+ List.Add(Next);
+ Next = NextRunTime(Next, false);
+ }
+ }
+
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ return NextRunTime(time, 100, AllowExact);
+ }
+
+ DateTime NextRunTime(DateTime time, int count, bool AllowExact)
+ {
+ if (count == 0)
+ throw new Exception("Invalid block wrapper combination.");
+
+ DateTime
+ temp = _Item.NextRunTime(time, AllowExact),
+ begin = _Begin.NextRunTime(time, true),
+ end = _End.NextRunTime(time, true);
+ System.Diagnostics.Debug.WriteLine(string.Format("{0} {1} {2} {3}", time, begin, end, temp));
+ bool A = temp > end, B = temp < begin, C = end < begin;
+ System.Diagnostics.Debug.WriteLine(string.Format("{0} {1} {2}", A, B, C));
+ if (C)
+ {
+ if (A && B)
+ return NextRunTime(begin, --count, false);
+ else
+ return temp;
+ }
+ else
+ {
+ if (!A && !B)
+ return temp;
+ if (!A)
+ return NextRunTime(begin, --count, false);
+ else
+ return NextRunTime(end, --count, false);
+ }
+ }
+ private IScheduledItem _Item;
+ private ScheduledTime _Begin, _End;
+ }
+}
\ No newline at end of file
diff --git a/ScheduledItems/EventInstance.cs b/ScheduledItems/EventInstance.cs
new file mode 100644
index 0000000..09a1021
--- /dev/null
+++ b/ScheduledItems/EventInstance.cs
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+
+ ///
+ /// There have been quite a few requests to allow scheduling of multiple delegates and method parameter data
+ /// from the same timer. This class allows you to match the event with the time that it fired. I want to keep
+ /// the same simple implementation of the EventQueue and interval classes since they can be reused elsewhere.
+ /// The timer should be responsible for matching this data up.
+ ///
+ public class EventInstance : IComparable
+ {
+ public EventInstance(DateTime time, IScheduledItem scheduleItem, object data)
+ {
+ Time = time;
+ ScheduleItem = scheduleItem;
+ Data = data;
+ }
+ public DateTime Time;
+ public IScheduledItem ScheduleItem;
+ public object Data;
+
+ public int CompareTo(object obj)
+ {
+ if (obj is EventInstance)
+ return Time.CompareTo(((EventInstance)obj).Time);
+ if (obj is DateTime)
+ return Time.CompareTo((DateTime)obj);
+ return 0;
+ }
+ }
+
+}
+
+
diff --git a/ScheduledItems/EventQueue.cs b/ScheduledItems/EventQueue.cs
new file mode 100644
index 0000000..685f0b2
--- /dev/null
+++ b/ScheduledItems/EventQueue.cs
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// The event queue is a collection of scheduled items that represents the union of all child scheduled items.
+ /// This is useful for events that occur every 10 minutes or at multiple intervals not covered by the simple
+ /// scheduled items.
+ ///
+ public class EventQueue : IScheduledItem
+ {
+ public EventQueue()
+ {
+ _List = new ArrayList();
+ }
+ ///
+ /// Adds a ScheduledTime to the queue.
+ ///
+ /// The scheduled time to add
+ public void Add(IScheduledItem time)
+ {
+ _List.Add(time);
+ }
+
+ ///
+ /// Clears the list of scheduled times.
+ ///
+ public void Clear()
+ {
+ _List.Clear();
+ }
+
+ ///
+ /// Adds the running time for all events in the list.
+ ///
+ /// The beginning time of the interval
+ /// The end time of the interval
+ /// The list to add times to.
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ foreach(IScheduledItem st in _List)
+ st.AddEventsInInterval(Begin, End, List);
+ List.Sort();
+ }
+
+ ///
+ /// Returns the first time after the starting time for all events in the list.
+ ///
+ /// The starting time.
+ /// If this is true then it allows the return time to match the time parameter, false forces the return time to be greater then the time parameter
+ /// Either the next event after the input time or greater or equal to depending on the AllowExact parameter.
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ DateTime next = DateTime.MaxValue;
+ //Get minimum datetime from the list.
+ foreach(IScheduledItem st in _List)
+ {
+ DateTime Proposed = st.NextRunTime(time, AllowExact);
+ next = (Proposed < next) ? Proposed : next;
+ }
+ return next;
+ }
+ private ArrayList _List;
+ }
+}
\ No newline at end of file
diff --git a/ScheduledItems/ScheduledTime.cs b/ScheduledItems/ScheduledTime.cs
new file mode 100644
index 0000000..b0e2331
--- /dev/null
+++ b/ScheduledItems/ScheduledTime.cs
@@ -0,0 +1,177 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+
+namespace UtilidadesCSharp.Schedule
+{
+ public enum EventTimeBase
+ {
+ BySecond = 1,
+ ByMinute = 2,
+ Hourly = 3,
+ Daily = 4,
+ Weekly = 5,
+ Monthly = 6,
+ }
+
+ ///
+ /// This class represents a simple schedule. It can represent a repeating event that occurs anywhere from every
+ /// second to once a month. It consists of an enumeration to mark the interval and an offset from that interval.
+ /// For example new ScheduledTime(Hourly, new TimeSpan(0, 15, 0)) would represent an event that fired 15 minutes
+ /// after the hour every hour.
+ ///
+ [Serializable]
+ public class ScheduledTime : IScheduledItem
+ {
+ public ScheduledTime(EventTimeBase Base, TimeSpan Offset)
+ {
+ _Base = Base;
+ _Offset = Offset;
+ }
+
+ ///
+ /// intializes a simple scheduled time element from a pair of strings.
+ /// Here are the supported formats
+ ///
+ /// BySecond - single integer representing the offset in ms
+ /// ByMinute - A comma seperate list of integers representing the number of seconds and ms
+ /// Hourly - A comma seperated list of integers representing the number of minutes, seconds and ms
+ /// Daily - A time in HH:mm:ss AM/PM format
+ /// Weekly - n, time where n represents an integer and time is a time in the Daily format
+ /// Monthly - the same format as weekly.
+ ///
+ ///
+ /// A string representing the base enumeration for the scheduled time
+ /// A string representing the offset for the time.
+ public ScheduledTime(string StrBase, string StrOffset)
+ {
+ //TODO:Create an IScheduled time factory method.
+ _Base = (EventTimeBase)Enum.Parse(typeof(EventTimeBase), StrBase, true);
+ Init(StrOffset);
+ }
+
+ public int ArrayAccess(string[] Arr, int i)
+ {
+ if (i >= Arr.Length)
+ return 0;
+ return int.Parse(Arr[i]);
+ }
+
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ DateTime Next = NextRunTime(Begin, true);
+ while (Next < End)
+ {
+ List.Add(Next);
+ Next = IncInterval(Next);
+ }
+ }
+
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ DateTime NextRun = LastSyncForTime(time) + _Offset;
+ if (NextRun == time && AllowExact)
+ return time;
+ if (NextRun > time)
+ return NextRun;
+ return IncInterval(NextRun);
+ }
+
+
+ private DateTime LastSyncForTime(DateTime time)
+ {
+ switch (_Base)
+ {
+ case EventTimeBase.BySecond:
+ return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second);
+ case EventTimeBase.ByMinute:
+ return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, 0);
+ case EventTimeBase.Hourly:
+ return new DateTime(time.Year, time.Month, time.Day, time.Hour, 0, 0);
+ case EventTimeBase.Daily:
+ return new DateTime(time.Year, time.Month, time.Day);
+ case EventTimeBase.Weekly:
+ return (new DateTime(time.Year, time.Month, time.Day)).AddDays(-(int)time.DayOfWeek);
+ case EventTimeBase.Monthly:
+ return new DateTime(time.Year, time.Month, 1);
+ }
+ throw new Exception("Invalid base specified for timer.");
+ }
+
+ private DateTime IncInterval(DateTime Last)
+ {
+ switch (_Base)
+ {
+ case EventTimeBase.BySecond:
+ return Last.AddSeconds(1);
+ case EventTimeBase.ByMinute:
+ return Last.AddMinutes(1);
+ case EventTimeBase.Hourly:
+ return Last.AddHours(1);
+ case EventTimeBase.Daily:
+ return Last.AddDays(1);
+ case EventTimeBase.Weekly:
+ return Last.AddDays(7);
+ case EventTimeBase.Monthly:
+ return Last.AddMonths(1);
+ }
+ throw new Exception("Invalid base specified for timer.");
+ }
+
+ private void Init(string StrOffset)
+ {
+ switch (_Base)
+ {
+ case EventTimeBase.BySecond:
+ _Offset = new TimeSpan(0, 0, 0, 0, int.Parse(StrOffset));
+ break;
+ case EventTimeBase.ByMinute:
+ string[] ArrMinute = StrOffset.Split(',');
+ _Offset = new TimeSpan(0, 0, 0, ArrayAccess(ArrMinute, 0), ArrayAccess(ArrMinute, 1));
+ break;
+ case EventTimeBase.Hourly:
+ string[] ArrHour = StrOffset.Split(',');
+ _Offset = new TimeSpan(0, 0, ArrayAccess(ArrHour, 0), ArrayAccess(ArrHour, 1), ArrayAccess(ArrHour, 2));
+ break;
+ case EventTimeBase.Daily:
+ DateTime Daytime = DateTime.Parse(StrOffset);
+ _Offset = new TimeSpan(0, Daytime.Hour, Daytime.Minute, Daytime.Second, Daytime.Millisecond);
+ break;
+ case EventTimeBase.Weekly:
+ string[] ArrWeek = StrOffset.Split(',');
+ if (ArrWeek.Length != 2)
+ throw new Exception("Weekly offset must be in the format n, time where n is the day of the week starting with 0 for sunday");
+ DateTime WeekTime = DateTime.Parse(ArrWeek[1]);
+ _Offset = new TimeSpan(int.Parse(ArrWeek[0]), WeekTime.Hour, WeekTime.Minute, WeekTime.Second, WeekTime.Millisecond);
+ break;
+ case EventTimeBase.Monthly:
+ string[] ArrMonth = StrOffset.Split(',');
+ if (ArrMonth.Length != 2)
+ throw new Exception("Monthly offset must be in the format n, time where n is the day of the month starting with 1 for the first day of the month.");
+ DateTime MonthTime = DateTime.Parse(ArrMonth[1]);
+ _Offset = new TimeSpan(int.Parse(ArrMonth[0])-1, MonthTime.Hour, MonthTime.Minute, MonthTime.Second, MonthTime.Millisecond);
+ break;
+ default:
+ throw new Exception("Invalid base specified for timer.");
+ }
+ }
+
+ private EventTimeBase _Base;
+ private TimeSpan _Offset;
+ }
+}
\ No newline at end of file
diff --git a/ScheduledItems/SimpleInterval.cs b/ScheduledItems/SimpleInterval.cs
new file mode 100644
index 0000000..50f5639
--- /dev/null
+++ b/ScheduledItems/SimpleInterval.cs
@@ -0,0 +1,90 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+using System;
+using System.Collections;
+using System.Diagnostics;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// The simple interval represents the simple scheduling that .net supports natively. It consists of a start
+ /// absolute time and an interval that is counted off from the start time.
+ ///
+ [Serializable]
+ public class SimpleInterval : IScheduledItem
+ {
+ public SimpleInterval(DateTime StartTime, TimeSpan Interval)
+ {
+ _Interval = Interval;
+ _StartTime = StartTime;
+ _EndTime = DateTime.MaxValue;
+ }
+ public SimpleInterval(DateTime StartTime, TimeSpan Interval, int count)
+ {
+ _Interval = Interval;
+ _StartTime = StartTime;
+ _EndTime = StartTime + TimeSpan.FromTicks(Interval.Ticks*count);
+ }
+ public SimpleInterval(DateTime StartTime, TimeSpan Interval, DateTime EndTime)
+ {
+ _Interval = Interval;
+ _StartTime = StartTime;
+ _EndTime = EndTime;
+ }
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ if (End <= _StartTime)
+ return;
+ DateTime Next = NextRunTime(Begin, true);
+ while (Next < End)
+ {
+ List.Add(Next);
+ Next = NextRunTime(Next, false);
+ }
+ }
+
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ DateTime returnTime = NextRunTimeInt(time, AllowExact);
+ Debug.WriteLine(time);
+ Debug.WriteLine(returnTime);
+ Debug.WriteLine(_EndTime);
+ return (returnTime >= _EndTime) ? DateTime.MaxValue : returnTime;
+ }
+
+ private DateTime NextRunTimeInt(DateTime time, bool AllowExact)
+ {
+ TimeSpan Span = time-_StartTime;
+ if (Span < TimeSpan.Zero)
+ return _StartTime;
+ if (ExactMatch(time))
+ return AllowExact ? time : time + _Interval;
+ uint msRemaining = (uint)(_Interval.TotalMilliseconds - ((uint)Span.TotalMilliseconds % (uint)_Interval.TotalMilliseconds));
+ return time.AddMilliseconds(msRemaining);
+ }
+
+ private bool ExactMatch(DateTime time)
+ {
+ TimeSpan Span = time-_StartTime;
+ if (Span < TimeSpan.Zero)
+ return false;
+ return (Span.TotalMilliseconds % _Interval.TotalMilliseconds) == 0;
+ }
+
+ private TimeSpan _Interval;
+ private DateTime _StartTime;
+ private DateTime _EndTime;
+ }
+}
\ No newline at end of file
diff --git a/ScheduledItems/SingleEvent.cs b/ScheduledItems/SingleEvent.cs
new file mode 100644
index 0000000..29ae869
--- /dev/null
+++ b/ScheduledItems/SingleEvent.cs
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+using System;
+
+namespace UtilidadesCSharp.Schedule
+{
+ /// Single event represents an event which only fires once.
+ public class SingleEvent : IScheduledItem
+ {
+ public SingleEvent(DateTime eventTime)
+ {
+ _EventTime = eventTime;
+ }
+ #region IScheduledItem Members
+
+ public void AddEventsInInterval(DateTime Begin, DateTime End, System.Collections.ArrayList List)
+ {
+ if (Begin <= _EventTime && End > _EventTime)
+ List.Add(_EventTime);
+ }
+
+ public DateTime NextRunTime(DateTime time, bool IncludeStartTime)
+ {
+ if (IncludeStartTime)
+ return (_EventTime >= time) ? _EventTime : DateTime.MaxValue;
+ else
+ return (_EventTime > time) ? _EventTime : DateTime.MaxValue;
+ }
+ private DateTime _EventTime;
+
+ #endregion
+ }
+}
diff --git a/TimerJob.cs b/TimerJob.cs
new file mode 100644
index 0000000..9e4d9c8
--- /dev/null
+++ b/TimerJob.cs
@@ -0,0 +1,181 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Timers;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// Timer job groups a schedule, syncronization data, a result filter, method information and an enabled state so that multiple jobs
+ /// can be managed by the same timer. Each one operating independently of the others with different syncronization and recovery settings.
+ ///
+ public class TimerJob
+ {
+
+
+
+
+
+
+ public TimerJob(IScheduledItem schedule, IMethodCall method)
+ {
+ Schedule = schedule;
+ Method = method;
+ _ExecuteHandler = new ExecuteHandler(ExecuteInternal);
+ }
+ public IScheduledItem Schedule;
+ public bool SyncronizedEvent = true;
+ public IResultFilter Filter;
+ public IMethodCall Method;
+// public IJobLog Log;
+ public bool Enabled = true;
+
+ public DateTime NextRunTime(DateTime time, bool IncludeStartTime)
+ {
+ if (!Enabled)
+ return DateTime.MaxValue;
+ return Schedule.NextRunTime(time, IncludeStartTime);
+ }
+
+ public void Execute(object sender, DateTime Begin, DateTime End, ExceptionEventHandler Error)
+ {
+ if (!Enabled)
+ return;
+
+ ArrayList EventList = new ArrayList();
+ Schedule.AddEventsInInterval(Begin, End, EventList);
+
+ if (Filter != null)
+ Filter.FilterResultsInInterval(Begin, End, EventList);
+
+ foreach(DateTime EventTime in EventList)
+ {
+ if (SyncronizedEvent)
+ _ExecuteHandler(sender, EventTime, Error);
+ else
+ _ExecuteHandler.BeginInvoke(sender, EventTime, Error, null, null);
+ }
+ }
+
+ private void ExecuteInternal(object sender, DateTime EventTime, ExceptionEventHandler Error)
+ {
+ try
+ {
+ TimerParameterSetter Setter = new TimerParameterSetter(EventTime, sender);
+ Method.Execute(Setter);
+ }
+ catch (Exception ex)
+ {
+ if (Error != null)
+ try { Error(this, new ExceptionEventArgs(EventTime, ex)); } catch {}
+ }
+ }
+
+ private delegate void ExecuteHandler(object sender, DateTime EventTime, ExceptionEventHandler Error);
+
+ private ExecuteHandler _ExecuteHandler;
+ }
+
+ ///
+ /// Timer job manages a group of timer jobs.
+ ///
+ public class TimerJobList
+ {
+ public TimerJobList()
+ {
+ _List = new ArrayList();
+ }
+
+ public void Add(TimerJob Event)
+ {
+ _List.Add(Event);
+ }
+
+ public void Clear()
+ {
+ _List.Clear();
+ }
+
+ ///
+ /// Gets the next time any of the jobs in the list will run. Allows matching the exact start time. If no matches are found the return
+ /// is DateTime.MaxValue;
+ ///
+ /// The starting time for the interval being queried. This time is included in the interval
+ /// The first absolute date one of the jobs will execute on. If none of the jobs needs to run DateTime.MaxValue is returned.
+ public DateTime NextRunTime(DateTime time)
+ {
+ DateTime next = DateTime.MaxValue;
+ //Get minimum datetime from the list.
+ foreach(TimerJob Job in _List)
+ {
+ DateTime Proposed = Job.NextRunTime(time, true);
+ next = (Proposed < next) ? Proposed : next;
+ }
+ return next;
+ }
+
+ public TimerJob[] Jobs
+ {
+ get { return (TimerJob[])_List.ToArray(typeof(TimerJob)); }
+ }
+
+ private ArrayList _List;
+ }
+
+ ///
+ /// The timer job allows delegates to be specified with unbound parameters. This ParameterSetter assigns all unbound datetime parameters
+ /// with the specified time and all unbound object parameters with the calling object.
+ ///
+ public class TimerParameterSetter : IParameterSetter
+ {
+ ///
+ /// Initalize the ParameterSetter with the time to pass to unbound time parameters and object to pass to unbound object parameters.
+ ///
+ /// The time to pass to the unbound DateTime parameters
+ /// The object to pass to the unbound object parameters
+ public TimerParameterSetter(DateTime time, object sender)
+ {
+ _time = time;
+ _sender = sender;
+ }
+ public void reset()
+ {
+ }
+ public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
+ {
+ switch(pi.ParameterType.Name.ToLower())
+ {
+ case "datetime":
+ parameter = _time;
+ return true;
+ case "object":
+ parameter = _sender;
+ return true;
+ case "scheduledeventargs":
+ parameter = new ScheduledEventArgs(_time);
+ return true;
+ case "eventargs":
+ parameter = new ScheduledEventArgs(_time);
+ return true;
+ }
+ return false;
+ }
+ DateTime _time;
+ object _sender;
+ }
+}
diff --git a/UtilidadesTSL4net.c.csproj b/UtilidadesTSL4net.c.csproj
new file mode 100644
index 0000000..f30f060
--- /dev/null
+++ b/UtilidadesTSL4net.c.csproj
@@ -0,0 +1,143 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {BF2447F5-65A1-4A47-A16E-F2227634E050}
+ Library
+ Properties
+ Utilidadescsharp
+ UtilidadesTSL4net.c
+
+
+ 3.5
+
+
+ v4.8
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ AnyCPU
+ AllRules.ruleset
+
+
+ false
+ false
+
+
+ pdbonly
+ true
+ bin\release\
+ TRACE
+ prompt
+ 4
+ x86
+ AllRules.ruleset
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+
+
+
+
+
+
+
+
+ UserControl
+
+
+
+
+
+ Designer
+ ucImagen.cs
+
+
+
+
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UtilidadesTSL4net.c.sln b/UtilidadesTSL4net.c.sln
new file mode 100644
index 0000000..586a0bf
--- /dev/null
+++ b/UtilidadesTSL4net.c.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 18
+VisualStudioVersion = 18.6.11806.211 stable
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtilidadesTSL4net.c", "UtilidadesTSL4net.c.csproj", "{BF2447F5-65A1-4A47-A16E-F2227634E050}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {BF2447F5-65A1-4A47-A16E-F2227634E050}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BF2447F5-65A1-4A47-A16E-F2227634E050}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BF2447F5-65A1-4A47-A16E-F2227634E050}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BF2447F5-65A1-4A47-A16E-F2227634E050}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {7AC260D0-FB99-4CCE-9185-C8A31FF3F375}
+ EndGlobalSection
+EndGlobal
diff --git a/UtilidadesTSL4net.c/EventStorage.cs b/UtilidadesTSL4net.c/EventStorage.cs
new file mode 100644
index 0000000..f3b3b4f
--- /dev/null
+++ b/UtilidadesTSL4net.c/EventStorage.cs
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// Null event strorage disables error recovery by returning now for the last time an event fired.
+ ///
+ public class NullEventStorage : IEventStorage
+ {
+ public NullEventStorage()
+ {
+ }
+
+ public void RecordLastTime(DateTime Time)
+ {
+ }
+
+ public DateTime ReadLastTime()
+ {
+ return DateTime.Now;
+ }
+ }
+
+ ///
+ /// Local event strorage keeps the last time in memory so that skipped events are not recovered.
+ ///
+ public class LocalEventStorage : IEventStorage
+ {
+ public LocalEventStorage()
+ {
+ _LastTime = DateTime.MaxValue;
+ }
+
+ public void RecordLastTime(DateTime Time)
+ {
+ _LastTime = Time;
+ }
+
+ public DateTime ReadLastTime()
+ {
+ if (_LastTime == DateTime.MaxValue)
+ _LastTime = DateTime.Now;
+ return _LastTime;
+ }
+
+ DateTime _LastTime;
+ }
+
+ ///
+ /// FileEventStorage saves the last time in an XmlDocument so that recovery will include periods that the
+ /// process is shutdown.
+ ///
+ public class FileEventStorage : IEventStorage
+ {
+ public FileEventStorage(string FileName, string XPath)
+ {
+ _FileName = FileName;
+ _XPath = XPath;
+ }
+
+ public void RecordLastTime(DateTime Time)
+ {
+ _Doc.SelectSingleNode(_XPath).Value = Time.ToString();
+ _Doc.Save(_FileName);
+ }
+
+ public DateTime ReadLastTime()
+ {
+ _Doc.Load(_FileName);
+ string Value = _Doc.SelectSingleNode(_XPath).Value;
+ if (Value == null || Value == string.Empty)
+ return DateTime.Now;
+ return DateTime.Parse(Value);
+ }
+
+ string _FileName;
+ string _XPath;
+ XmlDocument _Doc = new XmlDocument();
+ }
+}
diff --git a/UtilidadesTSL4net.c/IScheduledItem.cs b/UtilidadesTSL4net.c/IScheduledItem.cs
new file mode 100644
index 0000000..bd23e0b
--- /dev/null
+++ b/UtilidadesTSL4net.c/IScheduledItem.cs
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// IScheduledItem represents a scheduled event. You can query it for the number of events that occur
+ /// in a time interval and for the remaining interval before the next event.
+ ///
+ public interface IScheduledItem
+ {
+ ///
+ /// Returns the times of the events that occur in the given time interval. The interval is closed
+ /// at the start and open at the end so that intervals can be stacked without overlapping.
+ ///
+ /// The beginning of the interval
+ /// The end of the interval
+ /// All events >= Begin and < End
+ void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List);
+
+ ///
+ /// Returns the next run time of the scheduled item. Optionally excludes the starting time.
+ ///
+ /// The starting time of the interval
+ /// if true then the starting time is included in the query false, it is excluded.
+ /// The next execution time either on or after the starting time.
+ DateTime NextRunTime(DateTime time, bool IncludeStartTime);
+ }
+
+}
diff --git a/UtilidadesTSL4net.c/MethodCall.cs b/UtilidadesTSL4net.c/MethodCall.cs
new file mode 100644
index 0000000..a0f39b7
--- /dev/null
+++ b/UtilidadesTSL4net.c/MethodCall.cs
@@ -0,0 +1,332 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// IParameterSetter represents a serialized parameter list. This is used to provide a partial specialized
+ /// method call. This is useful for remote invocation of method calls. For example if you have a method with
+ /// 3 parameters. The first 2 might represent static data such as a report and a storage location. The third
+ /// might be the time that the report is invoked, which is only known when the method is invoked. Using this,
+ /// you just pass the method and the first 2 parameters to a timer object, which supplies the 3rd parameter.
+ /// Without these objects, you would have to generate a custom object type for each method you wished to
+ /// execute in this manner and store the static parameters as instance variables.
+ ///
+ public interface IParameterSetter
+ {
+ ///
+ /// This resets the setter to the beginning. It is used for setters that rely on positional state
+ /// information. It is called prior to setting any method values.
+ ///
+ void reset();
+ ///
+ /// This method is used to both query support for setting a parameter and actually set the value.
+ /// True is returned if the parameter passed in is updated.
+ ///
+ /// The reflection information about this parameter.
+ /// The location of the prameter in the parameter list.
+ /// The parameter object
+ /// true if the parameter is matched and false otherwise
+ bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter);
+ }
+
+ ///
+ /// This setter object takes a simple object array full of parameter data. It applys the objects in order
+ /// to the method parameter list.
+ ///
+ public class OrderParameterSetter : IParameterSetter
+ {
+ public OrderParameterSetter(params object[] _Params)
+ {
+ _ParamList = _Params;
+ }
+ public void reset()
+ {
+ _counter = 0;
+ }
+ public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
+ {
+ if (_counter >= _ParamList.Length)
+ return false;
+ parameter = _ParamList[_counter++];
+ return true;
+ }
+
+ object[] _ParamList;
+ int _counter;
+ }
+
+ ///
+ /// This setter object stores the parameter data in a Hashtable and uses the hashtable keys to match
+ /// the parameter names of the method to the parameter data. This allows methods to be called like
+ /// stored procedures, with the parameters being passed in independent of order.
+ ///
+ public class NamedParameterSetter : IParameterSetter
+ {
+ public NamedParameterSetter(Hashtable Params)
+ {
+ _Params = Params;
+ }
+ public void reset()
+ {
+ }
+ public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
+ {
+ string ParamName = pi.Name;
+ if (!_Params.ContainsKey(ParamName))
+ return false;
+ parameter = _Params[ParamName];
+ return true;
+ }
+ Hashtable _Params;
+ }
+
+
+ ///
+ /// ParameterSetterList maintains a collection of IParameterSetter objects and applies them in order to each
+ /// parameter of the method. Each time a match occurs the next parameter is tried starting with the first
+ /// setter object until it is matched.
+ ///
+ public class ParameterSetterList
+ {
+ public void Add(IParameterSetter setter)
+ {
+ _List.Add(setter);
+ }
+
+ public IParameterSetter[] ToArray()
+ {
+ return (IParameterSetter[])_List.ToArray(typeof(IParameterSetter));
+ }
+
+ public void reset()
+ {
+ foreach(IParameterSetter Setter in _List)
+ Setter.reset();
+ }
+
+ public object[] GetParameters(MethodInfo Method)
+ {
+ ParameterInfo[] Params = Method.GetParameters();
+ object[] Values = new object[Params.Length];
+ //TODO: Update to iterate backwards
+ for(int i=0; i
+ /// IMethodCall represents a partially specified parameter data list and a method. This allows methods to be
+ /// dynamically late invoked for things like timers and other event driven frameworks.
+ ///
+ public interface IMethodCall
+ {
+ ParameterSetterList ParamList { get; }
+ object Execute();
+ object Execute(IParameterSetter Params);
+ void EventHandler(object obj, EventArgs e);
+ IAsyncResult BeginExecute(AsyncCallback callback, object obj);
+ IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj);
+ }
+
+ delegate object Exec();
+ delegate object Exec2(IParameterSetter Params);
+
+ ///
+ /// Method call captures the data required to do a defered method call.
+ ///
+ public class DelegateMethodCall : MethodCallBase, IMethodCall
+ {
+ public DelegateMethodCall(Delegate f)
+ {
+ _f = f;
+ }
+
+ public DelegateMethodCall(Delegate f, params object[] Params)
+ {
+ if (f.Method.GetParameters().Length < Params.Length)
+ throw new ArgumentException("Too many parameters specified for delegate", "f");
+
+ _f = f;
+ ParamList.Add(new OrderParameterSetter(Params));
+ }
+
+ public DelegateMethodCall(Delegate f, IParameterSetter Params)
+ {
+ _f = f;
+ ParamList.Add(Params);
+ }
+
+ Delegate _f;
+
+ public Delegate f
+ {
+ get { return _f; }
+ set { _f = value; }
+ }
+
+ public MethodInfo Method
+ {
+ get { return _f.Method; }
+ }
+
+ public object Execute()
+ {
+ return f.DynamicInvoke(GetParameterList(Method));
+ }
+
+ public object Execute(IParameterSetter Params)
+ {
+ return f.DynamicInvoke(GetParameterList(Method, Params));
+ }
+
+ public void EventHandler(object obj, EventArgs e)
+ {
+ Execute();
+ }
+
+ Exec _exec;
+ public IAsyncResult BeginExecute(AsyncCallback callback, object obj)
+ {
+ _exec = new Exec(Execute);
+ return _exec.BeginInvoke(callback, obj);
+ }
+
+ public IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj)
+ {
+ Exec2 exec = new Exec2(Execute);
+ return exec.BeginInvoke(Params, callback, obj);
+ }
+ }
+
+ public class DynamicMethodCall : MethodCallBase, IMethodCall
+ {
+ public DynamicMethodCall(MethodInfo method)
+ {
+ _obj = null;
+ _method = method;
+ }
+
+ public DynamicMethodCall(object obj, MethodInfo method)
+ {
+ _obj = obj;
+ _method = method;
+ }
+
+ public DynamicMethodCall(object obj, MethodInfo method, IParameterSetter setter)
+ {
+ _obj = obj;
+ _method = method;
+ ParamList.Add(setter);
+ }
+
+ object _obj;
+ MethodInfo _method;
+
+ public MethodInfo Method
+ {
+ get { return _method; }
+ set { _method = value; }
+ }
+
+ public object Execute()
+ {
+ return _method.Invoke(_obj, GetParameterList(Method));
+ }
+
+ public object Execute(IParameterSetter Params)
+ {
+ return _method.Invoke(_obj, GetParameterList(Method, Params));
+ }
+
+ public void EventHandler(object obj, EventArgs e)
+ {
+ Execute();
+ }
+
+ Exec _exec;
+ public IAsyncResult BeginExecute(AsyncCallback callback, object obj)
+ {
+ _exec = new Exec(Execute);
+ return _exec.BeginInvoke(callback, null);
+ }
+
+ public IAsyncResult BeginExecute(IParameterSetter Params, AsyncCallback callback, object obj)
+ {
+ Exec2 exec = new Exec2(Execute);
+ return exec.BeginInvoke(Params, callback, null);
+ }
+ }
+
+ ///
+ /// This is a base class that handles the Parameter list management for the 2 dynamic method call methods.
+ ///
+ public class MethodCallBase
+ {
+ ParameterSetterList _ParamList = new ParameterSetterList();
+
+ public ParameterSetterList ParamList
+ {
+ get { return _ParamList; }
+ }
+
+ protected object[] GetParameterList(MethodInfo Method)
+ {
+ ParamList.reset();
+ object[] Params = ParamList.GetParameters(Method);
+ return Params;
+ }
+
+ protected object[] GetParameterList(MethodInfo Method, IParameterSetter Params)
+ {
+ ParamList.reset();
+ object[] objParams = ParamList.GetParameters(Method, Params);
+ return objParams;
+ }
+ }
+
+}
diff --git a/UtilidadesTSL4net.c/Properties/AssemblyInfo.cs b/UtilidadesTSL4net.c/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c75d144
--- /dev/null
+++ b/UtilidadesTSL4net.c/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// La información general sobre un ensamblado se controla mediante el siguiente
+// conjunto de atributos. Cambie estos atributos para modificar la información
+// asociada con un ensamblado.
+[assembly: AssemblyTitle("UtilidadesTSL4net.c")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany(".")]
+[assembly: AssemblyProduct("UtilidadesTSL4net.c")]
+[assembly: AssemblyCopyright("© . 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Si establece ComVisible como false hace que los tipos de este ensamblado no sean visibles
+// a los componentes COM. Si necesita obtener acceso a un tipo en este ensamblado desde
+// COM, establezca el atributo ComVisible como true en este tipo.
+[assembly: ComVisible(false)]
+
+// El siguiente GUID sirve como identificador de la biblioteca de tipos si este proyecto se expone a COM
+[assembly: Guid("51c70542-3016-463d-8d03-d306aae697f8")]
+
+// La información de versión de un ensamblado consta de los cuatro valores siguientes:
+//
+// Versión principal
+// Versión secundaria
+// Número de versión de compilación
+// Revisión
+//
+// Puede especificar todos los valores o puede establecer como valores predeterminados los números de revisión y generación
+// mediante el asterisco ('*'), como se muestra a continuación:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/UtilidadesTSL4net.c/Properties/Settings.Designer.cs b/UtilidadesTSL4net.c/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..7b1c916
--- /dev/null
+++ b/UtilidadesTSL4net.c/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// Este código fue generado por una herramienta.
+// Versión de runtime:4.0.30319.1
+//
+// Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si
+// se vuelve a generar el código.
+//
+//------------------------------------------------------------------------------
+
+namespace Utilidadescsharp.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/UtilidadesTSL4net.c/Properties/Settings.settings b/UtilidadesTSL4net.c/Properties/Settings.settings
new file mode 100644
index 0000000..049245f
--- /dev/null
+++ b/UtilidadesTSL4net.c/Properties/Settings.settings
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/UtilidadesTSL4net.c/ReportTimer.cs b/UtilidadesTSL4net.c/ReportTimer.cs
new file mode 100644
index 0000000..3a2f2a7
--- /dev/null
+++ b/UtilidadesTSL4net.c/ReportTimer.cs
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+
+namespace UtilidadesCSharp.Schedule
+{
+ public class ReportEventArgs : EventArgs
+ {
+ public ReportEventArgs(DateTime Time, int reportNo) { EventTime = Time; ReportNo = reportNo; }
+ public int ReportNo;
+ public DateTime EventTime;
+ }
+
+ public delegate void ReportEventHandler(object sender, ReportEventArgs e);
+
+ ///
+ /// Summary description for ReportTimer.
+ ///
+ public class ReportTimer : ScheduleTimerBase
+ {
+ public void AddReportEvent(IScheduledItem Schedule, int reportNo)
+ {
+ if (Elapsed == null)
+ throw new Exception("You must set elapsed before adding Events");
+ AddJob(new TimerJob(Schedule, new DelegateMethodCall(Handler, Elapsed, reportNo)));
+ }
+
+ public void AddAsyncReportEvent(IScheduledItem Schedule, int reportNo)
+ {
+ if (Elapsed == null)
+ throw new Exception("You must set elapsed before adding Events");
+ TimerJob Event = new TimerJob(Schedule, new DelegateMethodCall(Handler, Elapsed, reportNo));
+ Event.SyncronizedEvent = false;
+ AddJob(Event);
+ }
+
+ public event ReportEventHandler Elapsed;
+
+ delegate void ConvertHandler(ReportEventHandler Handler, int ReportNo, object sender, DateTime time);
+ static ConvertHandler Handler = new ConvertHandler(Converter);
+ static void Converter(ReportEventHandler Handler, int ReportNo, object sender, DateTime time)
+ {
+ if (Handler == null)
+ throw new ArgumentNullException("Handler");
+ if (sender == null)
+ throw new ArgumentNullException("sender");
+ Handler(sender, new ReportEventArgs(time, ReportNo));
+ }
+ }
+}
diff --git a/UtilidadesTSL4net.c/ScheduleFilter.cs b/UtilidadesTSL4net.c/ScheduleFilter.cs
new file mode 100644
index 0000000..466e6a9
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduleFilter.cs
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// This is an empty filter that does not filter any of the events.
+ ///
+ public class Filter : IResultFilter
+ {
+ public static IResultFilter Empty = new Filter();
+ private Filter() {}
+
+ public void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List)
+ {
+ if (List == null)
+ return;
+ List.Sort();
+ }
+ }
+
+ ///
+ /// This causes only the first event of the interval to be counted.
+ ///
+ public class FirstEventFilter : IResultFilter
+ {
+ public static IResultFilter Filter = new FirstEventFilter();
+ private FirstEventFilter() {}
+
+ public void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List)
+ {
+ if (List == null)
+ return;
+ if (List.Count < 2)
+ return;
+ List.Sort();
+ List.RemoveRange(1, List.Count-1);
+ }
+ }
+
+ ///
+ /// This causes only the last event of the interval to be counted.
+ ///
+ public class LastEventFilter : IResultFilter
+ {
+ public static IResultFilter Filter = new LastEventFilter();
+ private LastEventFilter() {}
+
+ public void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List)
+ {
+ if (List == null)
+ return;
+ if (List.Count < 2)
+ return;
+ List.Sort();
+ List.RemoveRange(0, List.Count-1);
+ }
+ }
+
+}
diff --git a/UtilidadesTSL4net.c/ScheduleTimer.cs b/UtilidadesTSL4net.c/ScheduleTimer.cs
new file mode 100644
index 0000000..acace75
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduleTimer.cs
@@ -0,0 +1,254 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Timers;
+using System.Diagnostics;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// ScheduleTimer represents a timer that fires on a more human friendly schedule. For example it is easy to
+ /// set it to fire every day at 6:00PM. It is useful for batch jobs or alarms that might be difficult to
+ /// schedule with the native .net timers.
+ /// It is similar to the .net timer that it is based on with the start and stop methods functioning similarly.
+ /// The main difference is the event uses a different delegate and arguement since the .net timer argument
+ /// class is not creatable.
+ ///
+ public class ScheduleTimerBase : IDisposable
+ {
+ public ScheduleTimerBase()
+ {
+ _Timer = new Timer();
+ _Timer.AutoReset = false;
+ _Timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
+ _Jobs = new TimerJobList();
+ _LastTime = DateTime.MaxValue;
+ }
+
+ ///
+ /// Adds a job to the timer. This method passes in a delegate and the parameters similar to the Invoke method of windows forms.
+ ///
+ /// The schedule that this delegate is to be run on.
+ /// The delegate to run
+ /// The method parameters to pass if you leave any DateTime parameters unbound, then they will be set with the scheduled run time of the
+ /// method. Any unbound object parameters will get this Job object passed in.
+ public void AddJob(IScheduledItem Schedule, Delegate f, params object[] Params)
+ {
+ _Jobs.Add(new TimerJob(Schedule, new DelegateMethodCall(f, Params)));
+ }
+
+ ///
+ /// Adds a job to the timer to operate asyncronously.
+ ///
+ /// The schedule that this delegate is to be run on.
+ /// The delegate to run
+ /// The method parameters to pass if you leave any DateTime parameters unbound, then they will be set with the scheduled run time of the
+ /// method. Any unbound object parameters will get this Job object passed in.
+ public void AddAsyncJob(IScheduledItem Schedule, Delegate f, params object[] Params)
+ {
+ TimerJob Event = new TimerJob(Schedule, new DelegateMethodCall(f, Params));
+ Event.SyncronizedEvent = false;
+ _Jobs.Add(Event);
+ }
+
+ ///
+ /// Adds a job to the timer.
+ ///
+ ///
+ public void AddJob(TimerJob Event)
+ {
+ _Jobs.Add(Event);
+ }
+
+ ///
+ /// Clears out all scheduled jobs.
+ ///
+ public void ClearJobs()
+ {
+ _Jobs.Clear();
+ }
+
+ ///
+ /// Begins executing all assigned jobs at the scheduled times
+ ///
+ public void Start()
+ {
+ _StopFlag = false;
+ QueueNextTime(EventStorage.ReadLastTime());
+ }
+
+ ///
+ /// Halts executing all jobs. When the timer is restarted all jobs that would have run while the timer was stopped are re-tried.
+ ///
+ public void Stop()
+ {
+ _StopFlag = true;
+ _Timer.Stop();
+ }
+
+ ///
+ /// EventStorage determines the method used to store the last event fire time. It defaults to keeping it in memory.
+ ///
+ public IEventStorage EventStorage = new LocalEventStorage();
+ public event ExceptionEventHandler Error;
+
+ #region Private Methods and Fields
+ ///
+ /// This is here to enhance accuracy. Even if nothing is scheduled the timer sleeps for a maximum of 1 minute.
+ ///
+ private static TimeSpan MAX_INTERVAL = new TimeSpan(0, 1, 0);
+
+ private DateTime _LastTime;
+ private Timer _Timer;
+ private TimerJobList _Jobs;
+ private volatile bool _StopFlag;
+
+ private double NextInterval(DateTime thisTime)
+ {
+ TimeSpan interval = _Jobs.NextRunTime(thisTime)-thisTime;
+ if (interval > MAX_INTERVAL)
+ interval = MAX_INTERVAL;
+ //Handles the case of 0 wait time, the interval property requires a duration > 0.
+ return (interval.TotalMilliseconds == 0) ? 1 : interval.TotalMilliseconds;
+ }
+
+ private void QueueNextTime(DateTime thisTime)
+ {
+ _Timer.Interval = NextInterval(thisTime);
+ System.Diagnostics.Debug.WriteLine(_Timer.Interval);
+ _LastTime = thisTime;
+ EventStorage.RecordLastTime(thisTime);
+ _Timer.Start();
+ }
+
+ private void Timer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ try
+ {
+ if (_Jobs == null)
+ return;
+
+ _Timer.Stop();
+
+ foreach(TimerJob Event in _Jobs.Jobs)
+ {
+ try { Event.Execute(this, _LastTime, e.SignalTime, Error); }
+ catch (Exception ex) { OnError(DateTime.Now, Event, ex); }
+ }
+ }
+ catch (Exception ex)
+ {
+ OnError(DateTime.Now, null, ex);
+ }
+ finally
+ {
+ if (_StopFlag == false)
+ QueueNextTime(e.SignalTime);
+ }
+ }
+
+ private void OnError(DateTime eventTime, TimerJob job, Exception e)
+ {
+ if (Error == null)
+ return;
+
+ try { Error(this, new ExceptionEventArgs(eventTime, e)); }
+ catch (Exception) {}
+ }
+ #endregion
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ if (_Timer != null)
+ _Timer.Dispose();
+ }
+
+ #endregion
+ }
+
+ public class ScheduleTimer : ScheduleTimerBase
+ {
+ ///
+ /// Add event is used in conjunction with the Elaspsed event handler. Set the Elapsed handler, add your schedule and call start.
+ ///
+ /// The schedule to fire the event at. Adding additional schedules will cause the event to fire whenever either schedule calls for it.
+ public void AddEvent(IScheduledItem Schedule)
+ {
+ if (Elapsed == null)
+ throw new ArgumentNullException("Elapsed", "member variable is null.");
+
+ AddJob(new TimerJob(Schedule, new DelegateMethodCall(Elapsed)));
+ }
+
+ ///
+ /// The event to fire when you only need to fire one event.
+ ///
+ public event ScheduledEventHandler Elapsed;
+ }
+
+ ///
+ /// ExceptionEventArgs allows exceptions to be captured and sent to the OnError event of the timer.
+ ///
+ public class ExceptionEventArgs : EventArgs
+ {
+ public ExceptionEventArgs(DateTime eventTime, Exception e)
+ {
+ EventTime = eventTime;
+ Error = e;
+ }
+ public DateTime EventTime;
+ public Exception Error;
+ }
+
+ ///
+ /// ExceptionEventHandler is the method type used by the OnError event for the timer.
+ ///
+ public delegate void ExceptionEventHandler(object sender, ExceptionEventArgs Args);
+
+ public class ScheduledEventArgs : EventArgs
+ {
+ public ScheduledEventArgs(DateTime eventTime)
+ {
+ EventTime = eventTime;
+ }
+ public DateTime EventTime;
+ }
+
+ public delegate void ScheduledEventHandler(object sender, ScheduledEventArgs e);
+
+ ///
+ /// The IResultFilter interface represents filters that either sort the events for an interval or
+ /// remove duplicate events either selecting the first or the last event.
+ ///
+ public interface IResultFilter
+ {
+ void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List);
+ }
+
+ ///
+ /// IEventStorage is used to provide persistance of schedule during service shutdowns.
+ ///
+ public interface IEventStorage
+ {
+ void RecordLastTime(DateTime Time);
+ DateTime ReadLastTime();
+ }
+
+
+}
\ No newline at end of file
diff --git a/UtilidadesTSL4net.c/ScheduledItems/BlockWrapper.cs b/UtilidadesTSL4net.c/ScheduledItems/BlockWrapper.cs
new file mode 100644
index 0000000..3427f75
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduledItems/BlockWrapper.cs
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// This class will be used to implement a filter that enables a window of activity. For cases where you want to
+ /// run every 15 minutes between 6:00 AM and 5:00 PM. Or just on weekdays or weekends.
+ ///
+ public class BlockWrapper : IScheduledItem
+ {
+ public BlockWrapper(IScheduledItem item, string StrBase, string BeginOffset, string EndOffset)
+ {
+ _Item = item;
+ _Begin = new ScheduledTime(StrBase, BeginOffset);
+ _End = new ScheduledTime(StrBase, EndOffset);
+ }
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ DateTime Next = NextRunTime(Begin, true);
+ while (Next < End)
+ {
+ List.Add(Next);
+ Next = NextRunTime(Next, false);
+ }
+ }
+
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ return NextRunTime(time, 100, AllowExact);
+ }
+
+ DateTime NextRunTime(DateTime time, int count, bool AllowExact)
+ {
+ if (count == 0)
+ throw new Exception("Invalid block wrapper combination.");
+
+ DateTime
+ temp = _Item.NextRunTime(time, AllowExact),
+ begin = _Begin.NextRunTime(time, true),
+ end = _End.NextRunTime(time, true);
+ System.Diagnostics.Debug.WriteLine(string.Format("{0} {1} {2} {3}", time, begin, end, temp));
+ bool A = temp > end, B = temp < begin, C = end < begin;
+ System.Diagnostics.Debug.WriteLine(string.Format("{0} {1} {2}", A, B, C));
+ if (C)
+ {
+ if (A && B)
+ return NextRunTime(begin, --count, false);
+ else
+ return temp;
+ }
+ else
+ {
+ if (!A && !B)
+ return temp;
+ if (!A)
+ return NextRunTime(begin, --count, false);
+ else
+ return NextRunTime(end, --count, false);
+ }
+ }
+ private IScheduledItem _Item;
+ private ScheduledTime _Begin, _End;
+ }
+}
\ No newline at end of file
diff --git a/UtilidadesTSL4net.c/ScheduledItems/EventInstance.cs b/UtilidadesTSL4net.c/ScheduledItems/EventInstance.cs
new file mode 100644
index 0000000..09a1021
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduledItems/EventInstance.cs
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+
+ ///
+ /// There have been quite a few requests to allow scheduling of multiple delegates and method parameter data
+ /// from the same timer. This class allows you to match the event with the time that it fired. I want to keep
+ /// the same simple implementation of the EventQueue and interval classes since they can be reused elsewhere.
+ /// The timer should be responsible for matching this data up.
+ ///
+ public class EventInstance : IComparable
+ {
+ public EventInstance(DateTime time, IScheduledItem scheduleItem, object data)
+ {
+ Time = time;
+ ScheduleItem = scheduleItem;
+ Data = data;
+ }
+ public DateTime Time;
+ public IScheduledItem ScheduleItem;
+ public object Data;
+
+ public int CompareTo(object obj)
+ {
+ if (obj is EventInstance)
+ return Time.CompareTo(((EventInstance)obj).Time);
+ if (obj is DateTime)
+ return Time.CompareTo((DateTime)obj);
+ return 0;
+ }
+ }
+
+}
+
+
diff --git a/UtilidadesTSL4net.c/ScheduledItems/EventQueue.cs b/UtilidadesTSL4net.c/ScheduledItems/EventQueue.cs
new file mode 100644
index 0000000..685f0b2
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduledItems/EventQueue.cs
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// The event queue is a collection of scheduled items that represents the union of all child scheduled items.
+ /// This is useful for events that occur every 10 minutes or at multiple intervals not covered by the simple
+ /// scheduled items.
+ ///
+ public class EventQueue : IScheduledItem
+ {
+ public EventQueue()
+ {
+ _List = new ArrayList();
+ }
+ ///
+ /// Adds a ScheduledTime to the queue.
+ ///
+ /// The scheduled time to add
+ public void Add(IScheduledItem time)
+ {
+ _List.Add(time);
+ }
+
+ ///
+ /// Clears the list of scheduled times.
+ ///
+ public void Clear()
+ {
+ _List.Clear();
+ }
+
+ ///
+ /// Adds the running time for all events in the list.
+ ///
+ /// The beginning time of the interval
+ /// The end time of the interval
+ /// The list to add times to.
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ foreach(IScheduledItem st in _List)
+ st.AddEventsInInterval(Begin, End, List);
+ List.Sort();
+ }
+
+ ///
+ /// Returns the first time after the starting time for all events in the list.
+ ///
+ /// The starting time.
+ /// If this is true then it allows the return time to match the time parameter, false forces the return time to be greater then the time parameter
+ /// Either the next event after the input time or greater or equal to depending on the AllowExact parameter.
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ DateTime next = DateTime.MaxValue;
+ //Get minimum datetime from the list.
+ foreach(IScheduledItem st in _List)
+ {
+ DateTime Proposed = st.NextRunTime(time, AllowExact);
+ next = (Proposed < next) ? Proposed : next;
+ }
+ return next;
+ }
+ private ArrayList _List;
+ }
+}
\ No newline at end of file
diff --git a/UtilidadesTSL4net.c/ScheduledItems/ScheduledTime.cs b/UtilidadesTSL4net.c/ScheduledItems/ScheduledTime.cs
new file mode 100644
index 0000000..49b2798
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduledItems/ScheduledTime.cs
@@ -0,0 +1,177 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+
+namespace UtilidadesCSharp.Schedule
+{
+ public enum EventTimeBase
+ {
+ BySecond = 1,
+ ByMinute = 2,
+ Hourly = 3,
+ Daily = 4,
+ Weekly = 5,
+ Monthly = 6,
+ }
+
+ ///
+ /// This class represents a simple schedule. It can represent a repeating event that occurs anywhere from every
+ /// second to once a month. It consists of an enumeration to mark the interval and an offset from that interval.
+ /// For example new ScheduledTime(Hourly, new TimeSpan(0, 15, 0)) would represent an event that fired 15 minutes
+ /// after the hour every hour.
+ ///
+ [Serializable]
+ public class ScheduledTime : IScheduledItem
+ {
+ public ScheduledTime(EventTimeBase Base, TimeSpan Offset)
+ {
+ _Base = Base;
+ _Offset = Offset;
+ }
+
+ ///
+ /// intializes a simple scheduled time element from a pair of strings.
+ /// Here are the supported formats
+ ///
+ /// BySecond - single integer representing the offset in ms
+ /// ByMinute - A comma seperate list of integers representing the number of seconds and ms
+ /// Hourly - A comma seperated list of integers representing the number of minutes, seconds and ms
+ /// Daily - A time in hh:mm:ss AM/PM format
+ /// Weekly - n, time where n represents an integer and time is a time in the Daily format
+ /// Monthly - the same format as weekly.
+ ///
+ ///
+ /// A string representing the base enumeration for the scheduled time
+ /// A string representing the offset for the time.
+ public ScheduledTime(string StrBase, string StrOffset)
+ {
+ //TODO:Create an IScheduled time factory method.
+ _Base = (EventTimeBase)Enum.Parse(typeof(EventTimeBase), StrBase, true);
+ Init(StrOffset);
+ }
+
+ public int ArrayAccess(string[] Arr, int i)
+ {
+ if (i >= Arr.Length)
+ return 0;
+ return int.Parse(Arr[i]);
+ }
+
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ DateTime Next = NextRunTime(Begin, true);
+ while (Next < End)
+ {
+ List.Add(Next);
+ Next = IncInterval(Next);
+ }
+ }
+
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ DateTime NextRun = LastSyncForTime(time) + _Offset;
+ if (NextRun == time && AllowExact)
+ return time;
+ if (NextRun > time)
+ return NextRun;
+ return IncInterval(NextRun);
+ }
+
+
+ private DateTime LastSyncForTime(DateTime time)
+ {
+ switch (_Base)
+ {
+ case EventTimeBase.BySecond:
+ return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second);
+ case EventTimeBase.ByMinute:
+ return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, 0);
+ case EventTimeBase.Hourly:
+ return new DateTime(time.Year, time.Month, time.Day, time.Hour, 0, 0);
+ case EventTimeBase.Daily:
+ return new DateTime(time.Year, time.Month, time.Day);
+ case EventTimeBase.Weekly:
+ return (new DateTime(time.Year, time.Month, time.Day)).AddDays(-(int)time.DayOfWeek);
+ case EventTimeBase.Monthly:
+ return new DateTime(time.Year, time.Month, 1);
+ }
+ throw new Exception("Invalid base specified for timer.");
+ }
+
+ private DateTime IncInterval(DateTime Last)
+ {
+ switch (_Base)
+ {
+ case EventTimeBase.BySecond:
+ return Last.AddSeconds(1);
+ case EventTimeBase.ByMinute:
+ return Last.AddMinutes(1);
+ case EventTimeBase.Hourly:
+ return Last.AddHours(1);
+ case EventTimeBase.Daily:
+ return Last.AddDays(1);
+ case EventTimeBase.Weekly:
+ return Last.AddDays(7);
+ case EventTimeBase.Monthly:
+ return Last.AddMonths(1);
+ }
+ throw new Exception("Invalid base specified for timer.");
+ }
+
+ private void Init(string StrOffset)
+ {
+ switch (_Base)
+ {
+ case EventTimeBase.BySecond:
+ _Offset = new TimeSpan(0, 0, 0, 0, int.Parse(StrOffset));
+ break;
+ case EventTimeBase.ByMinute:
+ string[] ArrMinute = StrOffset.Split(',');
+ _Offset = new TimeSpan(0, 0, 0, ArrayAccess(ArrMinute, 0), ArrayAccess(ArrMinute, 1));
+ break;
+ case EventTimeBase.Hourly:
+ string[] ArrHour = StrOffset.Split(',');
+ _Offset = new TimeSpan(0, 0, ArrayAccess(ArrHour, 0), ArrayAccess(ArrHour, 1), ArrayAccess(ArrHour, 2));
+ break;
+ case EventTimeBase.Daily:
+ DateTime Daytime = DateTime.Parse(StrOffset);
+ _Offset = new TimeSpan(0, Daytime.Hour, Daytime.Minute, Daytime.Second, Daytime.Millisecond);
+ break;
+ case EventTimeBase.Weekly:
+ string[] ArrWeek = StrOffset.Split(',');
+ if (ArrWeek.Length != 2)
+ throw new Exception("Weekly offset must be in the format n, time where n is the day of the week starting with 0 for sunday");
+ DateTime WeekTime = DateTime.Parse(ArrWeek[1]);
+ _Offset = new TimeSpan(int.Parse(ArrWeek[0]), WeekTime.Hour, WeekTime.Minute, WeekTime.Second, WeekTime.Millisecond);
+ break;
+ case EventTimeBase.Monthly:
+ string[] ArrMonth = StrOffset.Split(',');
+ if (ArrMonth.Length != 2)
+ throw new Exception("Monthly offset must be in the format n, time where n is the day of the month starting with 1 for the first day of the month.");
+ DateTime MonthTime = DateTime.Parse(ArrMonth[1]);
+ _Offset = new TimeSpan(int.Parse(ArrMonth[0])-1, MonthTime.Hour, MonthTime.Minute, MonthTime.Second, MonthTime.Millisecond);
+ break;
+ default:
+ throw new Exception("Invalid base specified for timer.");
+ }
+ }
+
+ private EventTimeBase _Base;
+ private TimeSpan _Offset;
+ }
+}
\ No newline at end of file
diff --git a/UtilidadesTSL4net.c/ScheduledItems/SimpleInterval.cs b/UtilidadesTSL4net.c/ScheduledItems/SimpleInterval.cs
new file mode 100644
index 0000000..50f5639
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduledItems/SimpleInterval.cs
@@ -0,0 +1,90 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+using System;
+using System.Collections;
+using System.Diagnostics;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// The simple interval represents the simple scheduling that .net supports natively. It consists of a start
+ /// absolute time and an interval that is counted off from the start time.
+ ///
+ [Serializable]
+ public class SimpleInterval : IScheduledItem
+ {
+ public SimpleInterval(DateTime StartTime, TimeSpan Interval)
+ {
+ _Interval = Interval;
+ _StartTime = StartTime;
+ _EndTime = DateTime.MaxValue;
+ }
+ public SimpleInterval(DateTime StartTime, TimeSpan Interval, int count)
+ {
+ _Interval = Interval;
+ _StartTime = StartTime;
+ _EndTime = StartTime + TimeSpan.FromTicks(Interval.Ticks*count);
+ }
+ public SimpleInterval(DateTime StartTime, TimeSpan Interval, DateTime EndTime)
+ {
+ _Interval = Interval;
+ _StartTime = StartTime;
+ _EndTime = EndTime;
+ }
+ public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
+ {
+ if (End <= _StartTime)
+ return;
+ DateTime Next = NextRunTime(Begin, true);
+ while (Next < End)
+ {
+ List.Add(Next);
+ Next = NextRunTime(Next, false);
+ }
+ }
+
+ public DateTime NextRunTime(DateTime time, bool AllowExact)
+ {
+ DateTime returnTime = NextRunTimeInt(time, AllowExact);
+ Debug.WriteLine(time);
+ Debug.WriteLine(returnTime);
+ Debug.WriteLine(_EndTime);
+ return (returnTime >= _EndTime) ? DateTime.MaxValue : returnTime;
+ }
+
+ private DateTime NextRunTimeInt(DateTime time, bool AllowExact)
+ {
+ TimeSpan Span = time-_StartTime;
+ if (Span < TimeSpan.Zero)
+ return _StartTime;
+ if (ExactMatch(time))
+ return AllowExact ? time : time + _Interval;
+ uint msRemaining = (uint)(_Interval.TotalMilliseconds - ((uint)Span.TotalMilliseconds % (uint)_Interval.TotalMilliseconds));
+ return time.AddMilliseconds(msRemaining);
+ }
+
+ private bool ExactMatch(DateTime time)
+ {
+ TimeSpan Span = time-_StartTime;
+ if (Span < TimeSpan.Zero)
+ return false;
+ return (Span.TotalMilliseconds % _Interval.TotalMilliseconds) == 0;
+ }
+
+ private TimeSpan _Interval;
+ private DateTime _StartTime;
+ private DateTime _EndTime;
+ }
+}
\ No newline at end of file
diff --git a/UtilidadesTSL4net.c/ScheduledItems/SingleEvent.cs b/UtilidadesTSL4net.c/ScheduledItems/SingleEvent.cs
new file mode 100644
index 0000000..29ae869
--- /dev/null
+++ b/UtilidadesTSL4net.c/ScheduledItems/SingleEvent.cs
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+using System;
+
+namespace UtilidadesCSharp.Schedule
+{
+ /// Single event represents an event which only fires once.
+ public class SingleEvent : IScheduledItem
+ {
+ public SingleEvent(DateTime eventTime)
+ {
+ _EventTime = eventTime;
+ }
+ #region IScheduledItem Members
+
+ public void AddEventsInInterval(DateTime Begin, DateTime End, System.Collections.ArrayList List)
+ {
+ if (Begin <= _EventTime && End > _EventTime)
+ List.Add(_EventTime);
+ }
+
+ public DateTime NextRunTime(DateTime time, bool IncludeStartTime)
+ {
+ if (IncludeStartTime)
+ return (_EventTime >= time) ? _EventTime : DateTime.MaxValue;
+ else
+ return (_EventTime > time) ? _EventTime : DateTime.MaxValue;
+ }
+ private DateTime _EventTime;
+
+ #endregion
+ }
+}
diff --git a/UtilidadesTSL4net.c/TimerJob.cs b/UtilidadesTSL4net.c/TimerJob.cs
new file mode 100644
index 0000000..9e4d9c8
--- /dev/null
+++ b/UtilidadesTSL4net.c/TimerJob.cs
@@ -0,0 +1,181 @@
+/***************************************************************************
+ * Copyright Andy Brummer 2004-2005
+ *
+ * This code is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * This code may be used in compiled form in any way you desire. This
+ * file may be redistributed unmodified by any means provided it is
+ * not sold for profit without the authors written consent, and
+ * providing that this notice and the authors name is included. If
+ * the source code in this file is used in any commercial application
+ * then a simple email would be nice.
+ *
+ **************************************************************************/
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Timers;
+
+namespace UtilidadesCSharp.Schedule
+{
+ ///
+ /// Timer job groups a schedule, syncronization data, a result filter, method information and an enabled state so that multiple jobs
+ /// can be managed by the same timer. Each one operating independently of the others with different syncronization and recovery settings.
+ ///
+ public class TimerJob
+ {
+
+
+
+
+
+
+ public TimerJob(IScheduledItem schedule, IMethodCall method)
+ {
+ Schedule = schedule;
+ Method = method;
+ _ExecuteHandler = new ExecuteHandler(ExecuteInternal);
+ }
+ public IScheduledItem Schedule;
+ public bool SyncronizedEvent = true;
+ public IResultFilter Filter;
+ public IMethodCall Method;
+// public IJobLog Log;
+ public bool Enabled = true;
+
+ public DateTime NextRunTime(DateTime time, bool IncludeStartTime)
+ {
+ if (!Enabled)
+ return DateTime.MaxValue;
+ return Schedule.NextRunTime(time, IncludeStartTime);
+ }
+
+ public void Execute(object sender, DateTime Begin, DateTime End, ExceptionEventHandler Error)
+ {
+ if (!Enabled)
+ return;
+
+ ArrayList EventList = new ArrayList();
+ Schedule.AddEventsInInterval(Begin, End, EventList);
+
+ if (Filter != null)
+ Filter.FilterResultsInInterval(Begin, End, EventList);
+
+ foreach(DateTime EventTime in EventList)
+ {
+ if (SyncronizedEvent)
+ _ExecuteHandler(sender, EventTime, Error);
+ else
+ _ExecuteHandler.BeginInvoke(sender, EventTime, Error, null, null);
+ }
+ }
+
+ private void ExecuteInternal(object sender, DateTime EventTime, ExceptionEventHandler Error)
+ {
+ try
+ {
+ TimerParameterSetter Setter = new TimerParameterSetter(EventTime, sender);
+ Method.Execute(Setter);
+ }
+ catch (Exception ex)
+ {
+ if (Error != null)
+ try { Error(this, new ExceptionEventArgs(EventTime, ex)); } catch {}
+ }
+ }
+
+ private delegate void ExecuteHandler(object sender, DateTime EventTime, ExceptionEventHandler Error);
+
+ private ExecuteHandler _ExecuteHandler;
+ }
+
+ ///
+ /// Timer job manages a group of timer jobs.
+ ///
+ public class TimerJobList
+ {
+ public TimerJobList()
+ {
+ _List = new ArrayList();
+ }
+
+ public void Add(TimerJob Event)
+ {
+ _List.Add(Event);
+ }
+
+ public void Clear()
+ {
+ _List.Clear();
+ }
+
+ ///
+ /// Gets the next time any of the jobs in the list will run. Allows matching the exact start time. If no matches are found the return
+ /// is DateTime.MaxValue;
+ ///
+ /// The starting time for the interval being queried. This time is included in the interval
+ /// The first absolute date one of the jobs will execute on. If none of the jobs needs to run DateTime.MaxValue is returned.
+ public DateTime NextRunTime(DateTime time)
+ {
+ DateTime next = DateTime.MaxValue;
+ //Get minimum datetime from the list.
+ foreach(TimerJob Job in _List)
+ {
+ DateTime Proposed = Job.NextRunTime(time, true);
+ next = (Proposed < next) ? Proposed : next;
+ }
+ return next;
+ }
+
+ public TimerJob[] Jobs
+ {
+ get { return (TimerJob[])_List.ToArray(typeof(TimerJob)); }
+ }
+
+ private ArrayList _List;
+ }
+
+ ///
+ /// The timer job allows delegates to be specified with unbound parameters. This ParameterSetter assigns all unbound datetime parameters
+ /// with the specified time and all unbound object parameters with the calling object.
+ ///
+ public class TimerParameterSetter : IParameterSetter
+ {
+ ///
+ /// Initalize the ParameterSetter with the time to pass to unbound time parameters and object to pass to unbound object parameters.
+ ///
+ /// The time to pass to the unbound DateTime parameters
+ /// The object to pass to the unbound object parameters
+ public TimerParameterSetter(DateTime time, object sender)
+ {
+ _time = time;
+ _sender = sender;
+ }
+ public void reset()
+ {
+ }
+ public bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter)
+ {
+ switch(pi.ParameterType.Name.ToLower())
+ {
+ case "datetime":
+ parameter = _time;
+ return true;
+ case "object":
+ parameter = _sender;
+ return true;
+ case "scheduledeventargs":
+ parameter = new ScheduledEventArgs(_time);
+ return true;
+ case "eventargs":
+ parameter = new ScheduledEventArgs(_time);
+ return true;
+ }
+ return false;
+ }
+ DateTime _time;
+ object _sender;
+ }
+}
diff --git a/UtilidadesTSL4net.c/UtilidadesTSL4net.c.csproj b/UtilidadesTSL4net.c/UtilidadesTSL4net.c.csproj
new file mode 100644
index 0000000..2772a08
--- /dev/null
+++ b/UtilidadesTSL4net.c/UtilidadesTSL4net.c.csproj
@@ -0,0 +1,132 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {BF2447F5-65A1-4A47-A16E-F2227634E050}
+ Library
+ Properties
+ Utilidadescsharp
+ UtilidadesTSL4net.c
+
+
+ 3.5
+
+
+ v2.0
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ x86
+ AllRules.ruleset
+
+
+
+
+ pdbonly
+ true
+ bin\release\
+ TRACE
+ prompt
+ 4
+ x86
+ AllRules.ruleset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+
+
+
+
+
+
+
+
+ UserControl
+
+
+
+
+
+ Designer
+ ucImagen.cs
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/UtilidadesTSL4net.c/ucImagen.cs b/UtilidadesTSL4net.c/ucImagen.cs
new file mode 100644
index 0000000..5be67ef
--- /dev/null
+++ b/UtilidadesTSL4net.c/ucImagen.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Windows.Forms;
+
+namespace UtilidadesCSharp.Imagen
+{
+ public enum SizeMode
+ {
+ Scrollable,
+ RatioStretch
+ }
+ ///
+ /// Summary description for Viewer.
+ ///
+ public class Imagen : System.Windows.Forms.UserControl
+ {
+ private System.Windows.Forms.PictureBox pictureBox1;
+ private System.ComponentModel.IContainer components;
+ private SizeMode sizeMode;
+
+ public Imagen()
+ {
+ // This call is required by the Windows.Forms Form Designer.
+ InitializeComponent();
+ this.ImageSizeMode = SizeMode.RatioStretch;
+ }
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (components != null)
+ {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ public Image Image
+ {
+ get { return this.pictureBox1.Image; }
+ set
+ {
+ this.pictureBox1.Image = value;
+ this.SetLayout();
+ //this.ChangeSize();
+ }
+ }
+ public SizeMode ImageSizeMode
+ {
+ get { return this.sizeMode; }
+ set
+ {
+ this.sizeMode = value;
+ this.AutoScroll = (this.sizeMode == SizeMode.Scrollable);
+ this.SetLayout();
+ }
+ }
+
+ private void RatioStretch()
+ {
+ float pRatio = (float)this.Width / this.Height;
+ float imRatio = (float)this.pictureBox1.Image.Width / this.pictureBox1.Image.Height;
+
+ if (this.Width >= this.pictureBox1.Image.Width && this.Height >= this.pictureBox1.Image.Height)
+ {
+ this.pictureBox1.Width = this.pictureBox1.Image.Width;
+ this.pictureBox1.Height = this.pictureBox1.Image.Height;
+ }
+ else if (this.Width > this.pictureBox1.Image.Width && this.Height < this.pictureBox1.Image.Height)
+ {
+ this.pictureBox1.Height = this.Height;
+ this.pictureBox1.Width = (int)(this.Height * imRatio);
+ }
+ else if (this.Width < this.pictureBox1.Image.Width && this.Height > this.pictureBox1.Image.Height)
+ {
+ this.pictureBox1.Width = this.Width;
+ this.pictureBox1.Height = (int)(this.Width / imRatio);
+ }
+ else if (this.Width < this.pictureBox1.Image.Width && this.Height < this.pictureBox1.Image.Height)
+ {
+ if (this.Width >= this.Height)
+ {
+ //width image
+ if (this.pictureBox1.Image.Width >= this.pictureBox1.Image.Height && imRatio >= pRatio)
+ {
+ this.pictureBox1.Width = this.Width;
+ this.pictureBox1.Height = (int)(this.Width / imRatio);
+ }
+ else
+ {
+ this.pictureBox1.Height = this.Height;
+ this.pictureBox1.Width = (int)(this.Height * imRatio);
+ }
+ }
+ else
+ {
+ //width image
+ if (this.pictureBox1.Image.Width < this.pictureBox1.Image.Height && imRatio < pRatio)
+ {
+ this.pictureBox1.Height = this.Height;
+ this.pictureBox1.Width = (int)(this.Height * imRatio);
+ }
+ else // height image
+ {
+ this.pictureBox1.Width = this.Width;
+ this.pictureBox1.Height = (int)(this.Width / imRatio);
+ }
+ }
+ }
+ this.CenterImage();
+ }
+ private void Scrollable()
+ {
+ this.pictureBox1.Width = this.pictureBox1.Image.Width;
+ this.pictureBox1.Height = this.pictureBox1.Image.Height;
+ this.CenterImage();
+ }
+ private void SetLayout()
+ {
+ if (this.pictureBox1.Image == null)
+ return;
+ if (this.sizeMode == SizeMode.RatioStretch)
+ this.RatioStretch();
+ else
+ {
+ this.AutoScroll = false;
+ this.Scrollable();
+ this.AutoScroll = true;
+
+ }
+ }
+ private void CenterImage()
+ {
+ int top = (int)((this.Height - this.pictureBox1.Height) / 2.0);
+ int left = (int)((this.Width - this.pictureBox1.Width) / 2.0);
+ if (top < 0)
+ top = 0;
+ if (left < 0)
+ left = 0;
+ this.pictureBox1.Top = top;
+ this.pictureBox1.Left = left;
+ }
+
+ #region Component Designer generated code
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.BackColor = System.Drawing.Color.Transparent;
+ this.pictureBox1.Cursor = System.Windows.Forms.Cursors.Default;
+ this.pictureBox1.Location = new System.Drawing.Point(24, 32);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(296, 208);
+ this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pictureBox1.TabIndex = 0;
+ this.pictureBox1.TabStop = false;
+ //
+ // Imagen
+ //
+ this.AutoScroll = true;
+ this.BackColor = System.Drawing.Color.Transparent;
+ this.Controls.Add(this.pictureBox1);
+ this.Name = "Imagen";
+ this.Size = new System.Drawing.Size(352, 272);
+ this.Load += new System.EventHandler(this.Viewer_Load);
+ this.Resize += new System.EventHandler(this.Viewer_Resize);
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+ #endregion
+
+ private void Viewer_Load(object sender, System.EventArgs e)
+ {
+ this.pictureBox1.Width = 0;
+ this.pictureBox1.Height = 0;
+ this.SetLayout();
+ }
+
+ private void Viewer_Resize(object sender, System.EventArgs e)
+ {
+ this.SetLayout();
+ }
+
+ }
+}
diff --git a/UtilidadesTSL4net.c/ucImagen.resx b/UtilidadesTSL4net.c/ucImagen.resx
new file mode 100644
index 0000000..19dc0dd
--- /dev/null
+++ b/UtilidadesTSL4net.c/ucImagen.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/ucImagen.cs b/ucImagen.cs
new file mode 100644
index 0000000..5be67ef
--- /dev/null
+++ b/ucImagen.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Windows.Forms;
+
+namespace UtilidadesCSharp.Imagen
+{
+ public enum SizeMode
+ {
+ Scrollable,
+ RatioStretch
+ }
+ ///
+ /// Summary description for Viewer.
+ ///
+ public class Imagen : System.Windows.Forms.UserControl
+ {
+ private System.Windows.Forms.PictureBox pictureBox1;
+ private System.ComponentModel.IContainer components;
+ private SizeMode sizeMode;
+
+ public Imagen()
+ {
+ // This call is required by the Windows.Forms Form Designer.
+ InitializeComponent();
+ this.ImageSizeMode = SizeMode.RatioStretch;
+ }
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (components != null)
+ {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ public Image Image
+ {
+ get { return this.pictureBox1.Image; }
+ set
+ {
+ this.pictureBox1.Image = value;
+ this.SetLayout();
+ //this.ChangeSize();
+ }
+ }
+ public SizeMode ImageSizeMode
+ {
+ get { return this.sizeMode; }
+ set
+ {
+ this.sizeMode = value;
+ this.AutoScroll = (this.sizeMode == SizeMode.Scrollable);
+ this.SetLayout();
+ }
+ }
+
+ private void RatioStretch()
+ {
+ float pRatio = (float)this.Width / this.Height;
+ float imRatio = (float)this.pictureBox1.Image.Width / this.pictureBox1.Image.Height;
+
+ if (this.Width >= this.pictureBox1.Image.Width && this.Height >= this.pictureBox1.Image.Height)
+ {
+ this.pictureBox1.Width = this.pictureBox1.Image.Width;
+ this.pictureBox1.Height = this.pictureBox1.Image.Height;
+ }
+ else if (this.Width > this.pictureBox1.Image.Width && this.Height < this.pictureBox1.Image.Height)
+ {
+ this.pictureBox1.Height = this.Height;
+ this.pictureBox1.Width = (int)(this.Height * imRatio);
+ }
+ else if (this.Width < this.pictureBox1.Image.Width && this.Height > this.pictureBox1.Image.Height)
+ {
+ this.pictureBox1.Width = this.Width;
+ this.pictureBox1.Height = (int)(this.Width / imRatio);
+ }
+ else if (this.Width < this.pictureBox1.Image.Width && this.Height < this.pictureBox1.Image.Height)
+ {
+ if (this.Width >= this.Height)
+ {
+ //width image
+ if (this.pictureBox1.Image.Width >= this.pictureBox1.Image.Height && imRatio >= pRatio)
+ {
+ this.pictureBox1.Width = this.Width;
+ this.pictureBox1.Height = (int)(this.Width / imRatio);
+ }
+ else
+ {
+ this.pictureBox1.Height = this.Height;
+ this.pictureBox1.Width = (int)(this.Height * imRatio);
+ }
+ }
+ else
+ {
+ //width image
+ if (this.pictureBox1.Image.Width < this.pictureBox1.Image.Height && imRatio < pRatio)
+ {
+ this.pictureBox1.Height = this.Height;
+ this.pictureBox1.Width = (int)(this.Height * imRatio);
+ }
+ else // height image
+ {
+ this.pictureBox1.Width = this.Width;
+ this.pictureBox1.Height = (int)(this.Width / imRatio);
+ }
+ }
+ }
+ this.CenterImage();
+ }
+ private void Scrollable()
+ {
+ this.pictureBox1.Width = this.pictureBox1.Image.Width;
+ this.pictureBox1.Height = this.pictureBox1.Image.Height;
+ this.CenterImage();
+ }
+ private void SetLayout()
+ {
+ if (this.pictureBox1.Image == null)
+ return;
+ if (this.sizeMode == SizeMode.RatioStretch)
+ this.RatioStretch();
+ else
+ {
+ this.AutoScroll = false;
+ this.Scrollable();
+ this.AutoScroll = true;
+
+ }
+ }
+ private void CenterImage()
+ {
+ int top = (int)((this.Height - this.pictureBox1.Height) / 2.0);
+ int left = (int)((this.Width - this.pictureBox1.Width) / 2.0);
+ if (top < 0)
+ top = 0;
+ if (left < 0)
+ left = 0;
+ this.pictureBox1.Top = top;
+ this.pictureBox1.Left = left;
+ }
+
+ #region Component Designer generated code
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.BackColor = System.Drawing.Color.Transparent;
+ this.pictureBox1.Cursor = System.Windows.Forms.Cursors.Default;
+ this.pictureBox1.Location = new System.Drawing.Point(24, 32);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(296, 208);
+ this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pictureBox1.TabIndex = 0;
+ this.pictureBox1.TabStop = false;
+ //
+ // Imagen
+ //
+ this.AutoScroll = true;
+ this.BackColor = System.Drawing.Color.Transparent;
+ this.Controls.Add(this.pictureBox1);
+ this.Name = "Imagen";
+ this.Size = new System.Drawing.Size(352, 272);
+ this.Load += new System.EventHandler(this.Viewer_Load);
+ this.Resize += new System.EventHandler(this.Viewer_Resize);
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+ #endregion
+
+ private void Viewer_Load(object sender, System.EventArgs e)
+ {
+ this.pictureBox1.Width = 0;
+ this.pictureBox1.Height = 0;
+ this.SetLayout();
+ }
+
+ private void Viewer_Resize(object sender, System.EventArgs e)
+ {
+ this.SetLayout();
+ }
+
+ }
+}
diff --git a/ucImagen.resx b/ucImagen.resx
new file mode 100644
index 0000000..19dc0dd
--- /dev/null
+++ b/ucImagen.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file