instala el servicio Windows y la tarea programada con targets de MsBuild
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Install" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!--Siendo DAILY=Diariamente
TN=Nombre de la tare programada
ST=Hora inicio de la tarea programada
TR=comando que se ejecutara al iniciar la tarea programada-->
<CommandInstalandoTareaProgramada>SCHTASKS /Create /SC DAILY /TN tareaFormReportToXML /ST 03:00:00 /RU usertfsservice /RP xxxx /TR "net start FormReportToXml"</CommandInstalandoTareaProgramada>
<CommandInstallWindowsService>call "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\"installutil /user="usertfsservice" /password="xxxx" "FormReportToXML.exe"</CommandInstallWindowsService >
</PropertyGroup>
<ItemGroup>
<ManagementFiles Include=".\ManageFMB\*.*" ></ManagementFiles>
<Config Include=".\Config\*.*" ></Config>
<Ejecutable Include=".\FormReportToXML.exe"></Ejecutable>
</ItemGroup>
<Target Name="Install" DependsOnTargets="InstallWindowsService;TareaProgramada;CopyDeploymentFiles">
</Target>
<Target Name="InstallWindowsService">
<Message Text="Instalando Servicio Windows" />
<Exec Command="$(CommandInstallWindowsService)"/>
</Target>
<Target Name="TareaProgramada">
<Message Text="Creando Tarea Programada" />
<Exec Command="$(CommandInstalandoTareaProgramada)"/>
</Target>
<Target Name="CopyDeploymentFiles">
<Copy SourceFiles="@(ManagementFiles)" DestinationFolder="$(PROGRAMFILES)\MSBuild\Company\FmbToXml\"></Copy>
<Copy SourceFiles="@(Config)" DestinationFolder="$(PROGRAMFILES)\MSBuild\Company\"></Copy>
<Copy SourceFiles="@(Ejecutable)" DestinationFolder="$(PROGRAMFILES)\MSBuild\Company\"></Copy>
</Target>
</Project>
Stopwatch swTimer = new Stopwatch();
swTimer.Start();
try
{
if (File.Exists("c:/LogGetLatestVersion.log"))
{
File.Delete("c:/LogGetLatestVersion.log");
}
TextWriterTraceListener logFile = new TextWriterTraceListener("c:/LogGetLatestVersion.log");
logFile.Name = "LogGetLatestVersion";
Trace.Listeners.Add(logFile);
// LOGICA AQUI ***********************
}
catch (Exception ex)
{
Trace.WriteLine("------ERROR-----");
Trace.WriteLine("MESSAGE-->"+ex.Message);
Trace.WriteLine("STACKTRACE-->"+ex.StackTrace);
Trace.WriteLine("TARGETSITE-->" + ex.TargetSite);
Trace.WriteLine("INNEREXCEPTION-->" + ex.InnerException);
Trace.WriteLine("HELPLINK-->" + ex.HelpLink);
}
finally
{
swTimer.Stop();
Trace.WriteLine("TOTAL TIEMPO : " + swTimer.Elapsed);
Trace.Flush();
Trace.Close();
}
Seguramente en el grupo que sois más experimentados tengáis otras alternativas como utilizar Serilog, o incluso SqlServer con algo similar ELMAH (https://elmah.github.io/).
Seguirá estando vigente ELMAH (para ASP.NET) ?
En definitiva, llegar a tener tabla de errores:
CREATE TABLE [dbo].[ELMAH_Error] | |
( | |
[ErrorId] UNIQUEIDENTIFIER NOT NULL, | |
[Application] NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | |
[Host] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | |
[Type] NVARCHAR(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | |
[Source] NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | |
[Message] NVARCHAR(500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | |
[User] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, | |
[StatusCode] INT NOT NULL, | |
[TimeUtc] DATETIME NOT NULL, | |
[Sequence] INT IDENTITY (1, 1) NOT NULL, | |
[AllXml] NVARCHAR(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL | |
) | |
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] |
Más ideas?
En ambos casos, considerar el logging y el control de errrores...
#If DEBUG Then
'System.Diagnostics.Debugger.Launch()
Try
Dim servicio As New ServicioIndexadoAutomatico()
servicio.Arrancar()
Console.WriteLine("ServicioIndexadoAutomatico arrancado, pulse ENTER para terminar.....")
Console.ReadLine()
servicio.Parar()
Catch e As Exception
Console.WriteLine("Error ServicioIndexadoAutomatico" + e.Message)
Console.ReadLine()
End Try
#Else
' *** Modo Release. Si se instalan a través de MSI compilar en Release ***
Dim ServicesToRun As ServiceBase()
ServicesToRun = New ServiceBase() {New ServicioIndexadoAutomatico()}
ServiceBase.Run(ServicesToRun)
#End If
Y más allá, con TopSelf, yo no vi (o no encontré) ejemplos completos real world con un buen logging - error handling...
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
var host = HostFactory.New(x =>
{
x.BeforeStartingServices(s => _log.DebugFormat("Starting {0}...", ServiceName));
x.AfterStoppingServices(s => _log.DebugFormat("Stopping {0}...", ServiceName));
x.Service(s =>
{
s.SetServiceName(ServiceName);
s.ConstructUsing(name =>
{
return new AsimovDeployService();
});
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.SetDisplayName(ServiceName);
x.SetDescription(ServiceName);
x.SetServiceName(ServiceName);
});
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
host.Run();
}
SET FILENAME="C:\Temp\Test1.bat"
SET ANYERRCODE=0
SCHTASKS /Create /S cledt-123616 /RU usag\rcheek /RP Camaro78 /TR
%FILENAME% /TN test_proc /SC ONCE /ST 00:00:00 /SD 12/31/2020
IF NOT %ERRORLEVEL%==0 SET ANYERRCODE=%ERRORLEVEL%
SCHTASKS /Run /S CLEDT-123616 /TN test_proc
:loop
IF NOT EXIST "C:\Documents and Settings\rcheek\Desktop\test.txt" goto
loop
echo REBOOT OK >>"C:\Documents and Settings\rcheek\Desktop\log.txt"
SCHTASKS /Delete /S cledt-123616 /TN test_proc /F
EXIT /B %ANYERRCODE%
--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispano+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a altnet-hispano@googlegroups.com.
Visita este grupo en https://groups.google.com/group/altnet-hispano.
Para acceder a más opciones, visita https://groups.google.com/d/optout.
Se que esta es una lista orientada a .NET, pero igual lo pongo porque tal vez les pueda servir.Desde hace un tiempo, uso un patron muy parecido al que propone Carlos:1. El scheduler es solo el trigger.2. La logica del proceso, esta detras de un HTTP endpoint.Para #1, uso Webtask CRON: https://webtask.io/docs/cronNo tengo que hostear nada. Usa cron syntax. Lo unico que hace es llamar a una API en #2. Toda la logica esta ahi. Cambia muy infrecuentemente.Para #2, uso una variedad de cosas. Ultimamente uso mucho Webtask tambien (interactivo, HTTPs req/res). Pero perfectamente podria ser un WebAPI, etc.Este es un ejemplo que muestra el pattern en accion, aunque es una app de juguete (en esencia, manda un batch de SMSs 1 vez por dia):Disclaimers:1. Webtask es fundamentalmente una plataforma JS/nodejs, pero puede ejecutar .NET.2. No uso .NET hace mucho. (Y no tengo nada en contra, es simplemente que no se ha dado el caso)3. Webtask es un producto de mi empresa
2017-12-01 10:23 GMT-08:00 Carlos Admirador <admirado...@gmail.com>:
Es un debate amplio.En Tareas programadas, los Recursos como la memoria se libera automáticamente una vez que el proceso ha terminado. En Servicios windows, habría que reiniciar.También hay que considerar el control de errores. Por ejemplo, los servicios windows tienen opciones de Recovery.Servicios windows están disponibles 24x7, y consumiendo recursos del sistema (creo). Tareas programadas pueden tener un comportamiento más puntual.
--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispan...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a altnet-...@googlegroups.com.
Sin duda, todo lleva un tiempo de aprendizaje (curva de aprendizaje) y la agilidad lleva práctica. Y cada “maestrillo tiene su librillo”.
Por eso, en comunidad, que busca incentivar el aprendizaje, compartiendo las pequeñas “píldoras de conocimiento y experiencias”, la sistematización de lecciones aprendidas y buenas prácticas, además de recursos, necesidades y buscando sinergias, con la aportación de todos seguramente juntos somos más productivos.
--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispano+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a altnet-hispano@googlegroups.com.
Visita este grupo en https://groups.google.com/group/altnet-hispano.
Para acceder a más opciones, visita https://groups.google.com/d/optout.
static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; if (System.Environment.UserInteractive) { string parameter = string.Concat(args); switch (parameter) { case "--install": ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location }); break; case "--uninstall": ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location }); break; } } else { ServiceBase.Run(new Program()); } }
Installer[RunInstaller(true)] public class MyWindowsServiceInstaller : Installer { public MyWindowsServiceInstaller() { var processInstaller = new ServiceProcessInstaller(); var serviceInstaller = new ServiceInstaller(); //set the privileges processInstaller.Account = ServiceAccount.LocalSystem; serviceInstaller.DisplayName = "My Service"; serviceInstaller.StartType = ServiceStartMode.Automatic; //must be the same as what was set in Program's constructor serviceInstaller.ServiceName = "My Service"; this.Installers.Add(processInstaller); this.Installers.Add(serviceInstaller); } }
--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispan...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/altnet-hispano/9477387e-2be8-4d2e-99f6-f8fc4c6d4a3c%40googlegroups.com.