I leave a solution to the problem from the windows service approach, which is the missing example.
This is an implementation of a windows service that runs a scheduled task (shows the time every 15 seconds per console) with the Quartz library that I think is powerful enough to plan tasks.
In the code I left the external references that I was taking in the code to make it as simple as possible.
-
Program.cs (Application entry point) [1]
using System;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;
namespace ServicioDiario
{
/*
* El ejemplo se basa en una forma para depurar servicios windows de manera simple: https://stackoverflow.com/questions/125964/easier-way-to-debug-a-windows-service
*/
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] servicesToRun;
servicesToRun = new ServiceBase[]
{
new Service1()
};
if (Environment.UserInteractive)
{
RunInteractive(servicesToRun);
}
else
{
ServiceBase.Run(servicesToRun);
}
}
static void RunInteractive(ServiceBase[] servicesToRun)
{
Console.WriteLine("* El servicio esta corriendo en modo interactivo *");
Console.WriteLine();
MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart",
BindingFlags.Instance | BindingFlags.NonPublic);
foreach (ServiceBase service in servicesToRun)
{
Console.Write("Iniciando servicio {0}...", service.ServiceName);
onStartMethod.Invoke(service, new object[] { new string[] { } });
Console.Write("Iniciado");
}
Console.WriteLine();
Console.WriteLine(
"Presione una tecla para detener el servicio y el proceso...");
Console.ReadKey();
Console.WriteLine();
MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop",
BindingFlags.Instance | BindingFlags.NonPublic);
foreach (ServiceBase service in servicesToRun)
{
Console.Write("Deteniendo {0}...", service.ServiceName);
onStopMethod.Invoke(service, null);
Console.WriteLine("Detenido");
}
Console.WriteLine("Todos los servicios planificado estan detenidos.");
// Permanezco un segundo para que pueda ver el mensaje.
Thread.Sleep(1000);
}
}
}
-
Work.cs (Class that will do the dirty work) [3]
using System;
using Quartz;
namespace ServicioDiario
{
/*
* Libreria recomendada para planificacion
* https://www.quartz-scheduler.net/
*/
public class Trabajo : IJob
{
public void Execute(IJobExecutionContext context)
{
//Realizar la tarea planificada.
System.Console.WriteLine("Hora: " + DateTime.Now.ToString("hh:mm:ss"));
}
}
}
-
Planner.cs (Class used to manipulate the start and end of planning)
using Quartz;
using Quartz.Impl;
namespace ServicioDiario
{
public class Planificador
{
public void Iniciar()
{
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start();
IJobDetail job = JobBuilder.Create<Trabajo>().Build();
//Cada 15 segundos
ITrigger trigger = TriggerBuilder.Create()
.WithSimpleSchedule(a => a.WithIntervalInSeconds(15).RepeatForever())
.Build();
// Cada un dia
//ITrigger trigger = TriggerBuilder.Create()
// .WithSimpleSchedule(a => a.WithIntervalInHours(24).RepeatForever())
// .Build();
scheduler.ScheduleJob(job, trigger);
}
public void Detener()
{
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Shutdown();
}
}
}
-
Service1.cs (service that is created by default with the windows service template) [4]
using System.ServiceProcess;
namespace ServicioDiario
{
/*
* Codigo fuente basado en el siguiente enlace en ingles: http://www.codingdefined.com/2016/08/schedule-tasks-as-windows-service-using.html
*/
public partial class Service1 : ServiceBase
{
Planificador plan;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
plan = new Planificador();
plan.Iniciar();
}
protected override void OnStop()
{
if (plan != null)
{
plan.Detener();
}
}
}
}
Note: In this example it is necessary to change the application type to console so you can show the results and do the tests [2].
As a final remark: there is a whole debate about using the task scheduler, a timer or a windows service.
In my experience, the use depends on how much control and what monitoring you should do to the task (s).
While more tasks, related to an application, you should plan with different periods of execution and greater control, the windows service approach is better.
References:
[1] link
[2] link
[3] link
[4] link