Agregar archivos de proyecto.

This commit is contained in:
2026-05-14 09:48:46 +02:00
parent 664774c9a1
commit c3e469823c
41 changed files with 4240 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<package>
<metadata>
<id>UtilidadesTSL4net.c</id>
<version>1.0.0.0</version>
<authors>Manuel</authors>
<owners>Tecnosis S.A.</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Utilidades c# WPF Tecnosis.</description>
<tags>UtilidadesTSL4net.c .net48</tags>
<dependencies>
<group targetFramework=".NETFramework4.8" />
</dependencies>
</metadata>
<files>
<file src="C:\tecnosis.git\Comunes\UtilidadesTSL4net.c\bin\Debug\UtilidadesTSL4net.c.dll" target="lib\net48\" />
</files>
</package>

BIN
Baget/nuget.exe Normal file

Binary file not shown.

97
EventStorage.cs Normal file
View File

@@ -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
{
/// <summary>
/// Null event strorage disables error recovery by returning now for the last time an event fired.
/// </summary>
public class NullEventStorage : IEventStorage
{
public NullEventStorage()
{
}
public void RecordLastTime(DateTime Time)
{
}
public DateTime ReadLastTime()
{
return DateTime.Now;
}
}
/// <summary>
/// Local event strorage keeps the last time in memory so that skipped events are not recovered.
/// </summary>
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;
}
/// <summary>
/// FileEventStorage saves the last time in an XmlDocument so that recovery will include periods that the
/// process is shutdown.
/// </summary>
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();
}
}

45
IScheduledItem.cs Normal file
View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public interface IScheduledItem
{
/// <summary>
/// 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.
/// </summary>
/// <param name="Begin">The beginning of the interval</param>
/// <param name="End">The end of the interval</param>
/// <returns>All events >= Begin and &lt; End </returns>
void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List);
/// <summary>
/// Returns the next run time of the scheduled item. Optionally excludes the starting time.
/// </summary>
/// <param name="time">The starting time of the interval</param>
/// <param name="IncludeStartTime">if true then the starting time is included in the query false, it is excluded.</param>
/// <returns>The next execution time either on or after the starting time.</returns>
DateTime NextRunTime(DateTime time, bool IncludeStartTime);
}
}

332
MethodCall.cs Normal file
View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public interface IParameterSetter
{
/// <summary>
/// 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.
/// </summary>
void reset();
/// <summary>
/// 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.
/// </summary>
/// <param name="pi">The reflection information about this parameter.</param>
/// <param name="ParameterLoc">The location of the prameter in the parameter list.</param>
/// <param name="parameter">The parameter object</param>
/// <returns>true if the parameter is matched and false otherwise</returns>
bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter);
}
/// <summary>
/// This setter object takes a simple object array full of parameter data. It applys the objects in order
/// to the method parameter list.
/// </summary>
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;
}
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// 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.
/// </summary>
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<Params.Length; ++i)
SetValue(Params[i], i, ref Values[i]);
return Values;
}
public object[] GetParameters(MethodInfo Method, IParameterSetter LastSetter)
{
ParameterInfo[] Params = Method.GetParameters();
object[] Values = new object[Params.Length];
//TODO: Update to iterate backwards
for(int i=0; i<Params.Length; ++i)
{
if (!SetValue(Params[i], i, ref Values[i]))
LastSetter.GetParameterValue(Params[i], i, ref Values[i]);
}
return Values;
}
bool SetValue(ParameterInfo Info, int i, ref object Value)
{
foreach(IParameterSetter Setter in _List)
{
if (Setter.GetParameterValue(Info, i, ref Value))
return true;
}
return false;
}
ArrayList _List = new ArrayList();
}
/// <summary>
/// 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.
/// </summary>
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);
/// <summary>
/// Method call captures the data required to do a defered method call.
/// </summary>
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);
}
}
/// <summary>
/// This is a base class that handles the Parameter list management for the 2 dynamic method call methods.
/// </summary>
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;
}
}
}

View File

@@ -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.*")]

26
Properties/Settings.Designer.cs generated Normal file
View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
</SettingsFile>

63
ReportTimer.cs Normal file
View File

@@ -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>
/// Summary description for ReportTimer.
/// </summary>
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));
}
}
}

75
ScheduleFilter.cs Normal file
View File

@@ -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
{
/// <summary>
/// This is an empty filter that does not filter any of the events.
/// </summary>
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();
}
}
/// <summary>
/// This causes only the first event of the interval to be counted.
/// </summary>
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);
}
}
/// <summary>
/// This causes only the last event of the interval to be counted.
/// </summary>
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);
}
}
}

254
ScheduleTimer.cs Normal file
View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class ScheduleTimerBase : IDisposable
{
public ScheduleTimerBase()
{
_Timer = new Timer();
_Timer.AutoReset = false;
_Timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
_Jobs = new TimerJobList();
_LastTime = DateTime.MaxValue;
}
/// <summary>
/// Adds a job to the timer. This method passes in a delegate and the parameters similar to the Invoke method of windows forms.
/// </summary>
/// <param name="Schedule">The schedule that this delegate is to be run on.</param>
/// <param name="f">The delegate to run</param>
/// <param name="Params">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.</param>
public void AddJob(IScheduledItem Schedule, Delegate f, params object[] Params)
{
_Jobs.Add(new TimerJob(Schedule, new DelegateMethodCall(f, Params)));
}
/// <summary>
/// Adds a job to the timer to operate asyncronously.
/// </summary>
/// <param name="Schedule">The schedule that this delegate is to be run on.</param>
/// <param name="f">The delegate to run</param>
/// <param name="Params">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.</param>
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);
}
/// <summary>
/// Adds a job to the timer.
/// </summary>
/// <param name="Event"></param>
public void AddJob(TimerJob Event)
{
_Jobs.Add(Event);
}
/// <summary>
/// Clears out all scheduled jobs.
/// </summary>
public void ClearJobs()
{
_Jobs.Clear();
}
/// <summary>
/// Begins executing all assigned jobs at the scheduled times
/// </summary>
public void Start()
{
_StopFlag = false;
QueueNextTime(EventStorage.ReadLastTime());
}
/// <summary>
/// Halts executing all jobs. When the timer is restarted all jobs that would have run while the timer was stopped are re-tried.
/// </summary>
public void Stop()
{
_StopFlag = true;
_Timer.Stop();
}
/// <summary>
/// EventStorage determines the method used to store the last event fire time. It defaults to keeping it in memory.
/// </summary>
public IEventStorage EventStorage = new LocalEventStorage();
public event ExceptionEventHandler Error;
#region Private Methods and Fields
/// <summary>
/// This is here to enhance accuracy. Even if nothing is scheduled the timer sleeps for a maximum of 1 minute.
/// </summary>
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
{
/// <summary>
/// Add event is used in conjunction with the Elaspsed event handler. Set the Elapsed handler, add your schedule and call start.
/// </summary>
/// <param name="Schedule">The schedule to fire the event at. Adding additional schedules will cause the event to fire whenever either schedule calls for it.</param>
public void AddEvent(IScheduledItem Schedule)
{
if (Elapsed == null)
throw new ArgumentNullException("Elapsed", "member variable is null.");
AddJob(new TimerJob(Schedule, new DelegateMethodCall(Elapsed)));
}
/// <summary>
/// The event to fire when you only need to fire one event.
/// </summary>
public event ScheduledEventHandler Elapsed;
}
/// <summary>
/// ExceptionEventArgs allows exceptions to be captured and sent to the OnError event of the timer.
/// </summary>
public class ExceptionEventArgs : EventArgs
{
public ExceptionEventArgs(DateTime eventTime, Exception e)
{
EventTime = eventTime;
Error = e;
}
public DateTime EventTime;
public Exception Error;
}
/// <summary>
/// ExceptionEventHandler is the method type used by the OnError event for the timer.
/// </summary>
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);
/// <summary>
/// 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.
/// </summary>
public interface IResultFilter
{
void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List);
}
/// <summary>
/// IEventStorage is used to provide persistance of schedule during service shutdowns.
/// </summary>
public interface IEventStorage
{
void RecordLastTime(DateTime Time);
DateTime ReadLastTime();
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
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;
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
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;
}
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class EventQueue : IScheduledItem
{
public EventQueue()
{
_List = new ArrayList();
}
/// <summary>
/// Adds a ScheduledTime to the queue.
/// </summary>
/// <param name="time">The scheduled time to add</param>
public void Add(IScheduledItem time)
{
_List.Add(time);
}
/// <summary>
/// Clears the list of scheduled times.
/// </summary>
public void Clear()
{
_List.Clear();
}
/// <summary>
/// Adds the running time for all events in the list.
/// </summary>
/// <param name="Begin">The beginning time of the interval</param>
/// <param name="End">The end time of the interval</param>
/// <param name="List">The list to add times to.</param>
public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
{
foreach(IScheduledItem st in _List)
st.AddEventsInInterval(Begin, End, List);
List.Sort();
}
/// <summary>
/// Returns the first time after the starting time for all events in the list.
/// </summary>
/// <param name="time">The starting time.</param>
/// <param name="AllowExact">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</param>
/// <returns>Either the next event after the input time or greater or equal to depending on the AllowExact parameter.</returns>
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;
}
}

View File

@@ -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,
}
/// <summary>
/// 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.
/// </summary>
[Serializable]
public class ScheduledTime : IScheduledItem
{
public ScheduledTime(EventTimeBase Base, TimeSpan Offset)
{
_Base = Base;
_Offset = Offset;
}
/// <summary>
/// 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.
///
/// </summary>
/// <param name="StrBase">A string representing the base enumeration for the scheduled time</param>
/// <param name="StrOffset">A string representing the offset for the time.</param>
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;
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
[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;
}
}

View File

@@ -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
{
/// <summary>Single event represents an event which only fires once.</summary>
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
}
}

181
TimerJob.cs Normal file
View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// Timer job manages a group of timer jobs.
/// </summary>
public class TimerJobList
{
public TimerJobList()
{
_List = new ArrayList();
}
public void Add(TimerJob Event)
{
_List.Add(Event);
}
public void Clear()
{
_List.Clear();
}
/// <summary>
/// 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;
/// </summary>
/// <param name="time">The starting time for the interval being queried. This time is included in the interval</param>
/// <returns>The first absolute date one of the jobs will execute on. If none of the jobs needs to run DateTime.MaxValue is returned.</returns>
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;
}
/// <summary>
/// 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.
/// </summary>
public class TimerParameterSetter : IParameterSetter
{
/// <summary>
/// Initalize the ParameterSetter with the time to pass to unbound time parameters and object to pass to unbound object parameters.
/// </summary>
/// <param name="time">The time to pass to the unbound DateTime parameters</param>
/// <param name="sender">The object to pass to the unbound object parameters</param>
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;
}
}

143
UtilidadesTSL4net.c.csproj Normal file
View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BF2447F5-65A1-4A47-A16E-F2227634E050}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Utilidadescsharp</RootNamespace>
<AssemblyName>UtilidadesTSL4net.c</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>
</DocumentationFile>
<UseVSHostingProcess>false</UseVSHostingProcess>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>
</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="EventStorage.cs" />
<Compile Include="IScheduledItem.cs" />
<Compile Include="MethodCall.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Include="ReportTimer.cs" />
<Compile Include="ScheduledItems\BlockWrapper.cs" />
<Compile Include="ScheduledItems\EventInstance.cs" />
<Compile Include="ScheduledItems\EventQueue.cs" />
<Compile Include="ScheduledItems\ScheduledTime.cs" />
<Compile Include="ScheduledItems\SimpleInterval.cs" />
<Compile Include="ScheduledItems\SingleEvent.cs" />
<Compile Include="ScheduleFilter.cs" />
<Compile Include="ScheduleTimer.cs" />
<Compile Include="TimerJob.cs" />
<Compile Include="ucImagen.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ucImagen.resx">
<SubType>Designer</SubType>
<DependentUpon>ucImagen.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Baget\UtilidadesTSL4net.c.1.0.0.nupkg" />
<None Include="Baget\UtilidadesTSL4net.c.nuspec" />
<None Include="bin\Debug\UtilidadesTSL4net.c.1.0.0.nupkg" />
<None Include="bin\UtilidadesTSL4net.c.1.0.0.nupkg" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="Baget\nuget.exe" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

25
UtilidadesTSL4net.c.sln Normal file
View File

@@ -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

View File

@@ -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
{
/// <summary>
/// Null event strorage disables error recovery by returning now for the last time an event fired.
/// </summary>
public class NullEventStorage : IEventStorage
{
public NullEventStorage()
{
}
public void RecordLastTime(DateTime Time)
{
}
public DateTime ReadLastTime()
{
return DateTime.Now;
}
}
/// <summary>
/// Local event strorage keeps the last time in memory so that skipped events are not recovered.
/// </summary>
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;
}
/// <summary>
/// FileEventStorage saves the last time in an XmlDocument so that recovery will include periods that the
/// process is shutdown.
/// </summary>
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();
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public interface IScheduledItem
{
/// <summary>
/// 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.
/// </summary>
/// <param name="Begin">The beginning of the interval</param>
/// <param name="End">The end of the interval</param>
/// <returns>All events >= Begin and &lt; End </returns>
void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List);
/// <summary>
/// Returns the next run time of the scheduled item. Optionally excludes the starting time.
/// </summary>
/// <param name="time">The starting time of the interval</param>
/// <param name="IncludeStartTime">if true then the starting time is included in the query false, it is excluded.</param>
/// <returns>The next execution time either on or after the starting time.</returns>
DateTime NextRunTime(DateTime time, bool IncludeStartTime);
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public interface IParameterSetter
{
/// <summary>
/// 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.
/// </summary>
void reset();
/// <summary>
/// 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.
/// </summary>
/// <param name="pi">The reflection information about this parameter.</param>
/// <param name="ParameterLoc">The location of the prameter in the parameter list.</param>
/// <param name="parameter">The parameter object</param>
/// <returns>true if the parameter is matched and false otherwise</returns>
bool GetParameterValue(ParameterInfo pi, int ParameterLoc, ref object parameter);
}
/// <summary>
/// This setter object takes a simple object array full of parameter data. It applys the objects in order
/// to the method parameter list.
/// </summary>
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;
}
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// 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.
/// </summary>
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<Params.Length; ++i)
SetValue(Params[i], i, ref Values[i]);
return Values;
}
public object[] GetParameters(MethodInfo Method, IParameterSetter LastSetter)
{
ParameterInfo[] Params = Method.GetParameters();
object[] Values = new object[Params.Length];
//TODO: Update to iterate backwards
for(int i=0; i<Params.Length; ++i)
{
if (!SetValue(Params[i], i, ref Values[i]))
LastSetter.GetParameterValue(Params[i], i, ref Values[i]);
}
return Values;
}
bool SetValue(ParameterInfo Info, int i, ref object Value)
{
foreach(IParameterSetter Setter in _List)
{
if (Setter.GetParameterValue(Info, i, ref Value))
return true;
}
return false;
}
ArrayList _List = new ArrayList();
}
/// <summary>
/// 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.
/// </summary>
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);
/// <summary>
/// Method call captures the data required to do a defered method call.
/// </summary>
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);
}
}
/// <summary>
/// This is a base class that handles the Parameter list management for the 2 dynamic method call methods.
/// </summary>
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;
}
}
}

View File

@@ -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")]

View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
</SettingsFile>

View File

@@ -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>
/// Summary description for ReportTimer.
/// </summary>
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));
}
}
}

View File

@@ -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
{
/// <summary>
/// This is an empty filter that does not filter any of the events.
/// </summary>
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();
}
}
/// <summary>
/// This causes only the first event of the interval to be counted.
/// </summary>
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);
}
}
/// <summary>
/// This causes only the last event of the interval to be counted.
/// </summary>
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);
}
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class ScheduleTimerBase : IDisposable
{
public ScheduleTimerBase()
{
_Timer = new Timer();
_Timer.AutoReset = false;
_Timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);
_Jobs = new TimerJobList();
_LastTime = DateTime.MaxValue;
}
/// <summary>
/// Adds a job to the timer. This method passes in a delegate and the parameters similar to the Invoke method of windows forms.
/// </summary>
/// <param name="Schedule">The schedule that this delegate is to be run on.</param>
/// <param name="f">The delegate to run</param>
/// <param name="Params">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.</param>
public void AddJob(IScheduledItem Schedule, Delegate f, params object[] Params)
{
_Jobs.Add(new TimerJob(Schedule, new DelegateMethodCall(f, Params)));
}
/// <summary>
/// Adds a job to the timer to operate asyncronously.
/// </summary>
/// <param name="Schedule">The schedule that this delegate is to be run on.</param>
/// <param name="f">The delegate to run</param>
/// <param name="Params">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.</param>
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);
}
/// <summary>
/// Adds a job to the timer.
/// </summary>
/// <param name="Event"></param>
public void AddJob(TimerJob Event)
{
_Jobs.Add(Event);
}
/// <summary>
/// Clears out all scheduled jobs.
/// </summary>
public void ClearJobs()
{
_Jobs.Clear();
}
/// <summary>
/// Begins executing all assigned jobs at the scheduled times
/// </summary>
public void Start()
{
_StopFlag = false;
QueueNextTime(EventStorage.ReadLastTime());
}
/// <summary>
/// Halts executing all jobs. When the timer is restarted all jobs that would have run while the timer was stopped are re-tried.
/// </summary>
public void Stop()
{
_StopFlag = true;
_Timer.Stop();
}
/// <summary>
/// EventStorage determines the method used to store the last event fire time. It defaults to keeping it in memory.
/// </summary>
public IEventStorage EventStorage = new LocalEventStorage();
public event ExceptionEventHandler Error;
#region Private Methods and Fields
/// <summary>
/// This is here to enhance accuracy. Even if nothing is scheduled the timer sleeps for a maximum of 1 minute.
/// </summary>
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
{
/// <summary>
/// Add event is used in conjunction with the Elaspsed event handler. Set the Elapsed handler, add your schedule and call start.
/// </summary>
/// <param name="Schedule">The schedule to fire the event at. Adding additional schedules will cause the event to fire whenever either schedule calls for it.</param>
public void AddEvent(IScheduledItem Schedule)
{
if (Elapsed == null)
throw new ArgumentNullException("Elapsed", "member variable is null.");
AddJob(new TimerJob(Schedule, new DelegateMethodCall(Elapsed)));
}
/// <summary>
/// The event to fire when you only need to fire one event.
/// </summary>
public event ScheduledEventHandler Elapsed;
}
/// <summary>
/// ExceptionEventArgs allows exceptions to be captured and sent to the OnError event of the timer.
/// </summary>
public class ExceptionEventArgs : EventArgs
{
public ExceptionEventArgs(DateTime eventTime, Exception e)
{
EventTime = eventTime;
Error = e;
}
public DateTime EventTime;
public Exception Error;
}
/// <summary>
/// ExceptionEventHandler is the method type used by the OnError event for the timer.
/// </summary>
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);
/// <summary>
/// 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.
/// </summary>
public interface IResultFilter
{
void FilterResultsInInterval(DateTime Start, DateTime End, ArrayList List);
}
/// <summary>
/// IEventStorage is used to provide persistance of schedule during service shutdowns.
/// </summary>
public interface IEventStorage
{
void RecordLastTime(DateTime Time);
DateTime ReadLastTime();
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
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;
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
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;
}
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class EventQueue : IScheduledItem
{
public EventQueue()
{
_List = new ArrayList();
}
/// <summary>
/// Adds a ScheduledTime to the queue.
/// </summary>
/// <param name="time">The scheduled time to add</param>
public void Add(IScheduledItem time)
{
_List.Add(time);
}
/// <summary>
/// Clears the list of scheduled times.
/// </summary>
public void Clear()
{
_List.Clear();
}
/// <summary>
/// Adds the running time for all events in the list.
/// </summary>
/// <param name="Begin">The beginning time of the interval</param>
/// <param name="End">The end time of the interval</param>
/// <param name="List">The list to add times to.</param>
public void AddEventsInInterval(DateTime Begin, DateTime End, ArrayList List)
{
foreach(IScheduledItem st in _List)
st.AddEventsInInterval(Begin, End, List);
List.Sort();
}
/// <summary>
/// Returns the first time after the starting time for all events in the list.
/// </summary>
/// <param name="time">The starting time.</param>
/// <param name="AllowExact">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</param>
/// <returns>Either the next event after the input time or greater or equal to depending on the AllowExact parameter.</returns>
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;
}
}

View File

@@ -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,
}
/// <summary>
/// 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.
/// </summary>
[Serializable]
public class ScheduledTime : IScheduledItem
{
public ScheduledTime(EventTimeBase Base, TimeSpan Offset)
{
_Base = Base;
_Offset = Offset;
}
/// <summary>
/// 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.
///
/// </summary>
/// <param name="StrBase">A string representing the base enumeration for the scheduled time</param>
/// <param name="StrOffset">A string representing the offset for the time.</param>
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;
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
[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;
}
}

View File

@@ -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
{
/// <summary>Single event represents an event which only fires once.</summary>
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
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// Timer job manages a group of timer jobs.
/// </summary>
public class TimerJobList
{
public TimerJobList()
{
_List = new ArrayList();
}
public void Add(TimerJob Event)
{
_List.Add(Event);
}
public void Clear()
{
_List.Clear();
}
/// <summary>
/// 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;
/// </summary>
/// <param name="time">The starting time for the interval being queried. This time is included in the interval</param>
/// <returns>The first absolute date one of the jobs will execute on. If none of the jobs needs to run DateTime.MaxValue is returned.</returns>
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;
}
/// <summary>
/// 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.
/// </summary>
public class TimerParameterSetter : IParameterSetter
{
/// <summary>
/// Initalize the ParameterSetter with the time to pass to unbound time parameters and object to pass to unbound object parameters.
/// </summary>
/// <param name="time">The time to pass to the unbound DateTime parameters</param>
/// <param name="sender">The object to pass to the unbound object parameters</param>
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;
}
}

View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BF2447F5-65A1-4A47-A16E-F2227634E050}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Utilidadescsharp</RootNamespace>
<AssemblyName>UtilidadesTSL4net.c</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="EventStorage.cs" />
<Compile Include="IScheduledItem.cs" />
<Compile Include="MethodCall.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Include="ReportTimer.cs" />
<Compile Include="ScheduledItems\BlockWrapper.cs" />
<Compile Include="ScheduledItems\EventInstance.cs" />
<Compile Include="ScheduledItems\EventQueue.cs" />
<Compile Include="ScheduledItems\ScheduledTime.cs" />
<Compile Include="ScheduledItems\SimpleInterval.cs" />
<Compile Include="ScheduledItems\SingleEvent.cs" />
<Compile Include="ScheduleFilter.cs" />
<Compile Include="ScheduleTimer.cs" />
<Compile Include="TimerJob.cs" />
<Compile Include="ucImagen.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ucImagen.resx">
<SubType>Designer</SubType>
<DependentUpon>ucImagen.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -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>
/// Summary description for Viewer.
/// </summary>
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;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
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
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

202
ucImagen.cs Normal file
View File

@@ -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>
/// Summary description for Viewer.
/// </summary>
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;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
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
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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();
}
}
}

120
ucImagen.resx Normal file
View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>