Tareas, tareas, tareas

43 views
Skip to first unread message

Preguntón Cojonero Cabrón

unread,
Nov 30, 2017, 5:47:39 PM11/30/17
to AltNet-Hispano
Hola.

Se tiene como base un "proceso" (sea app consola, etcétera) que se lanza a las 09:00 am, y tiene que leer un fichero CSV de un SFTP. Si no se encuentra el fichero, espera un tiempo (10 minutos), y otra vez intentar leer el f ichero. Así, hasta que lo procese.
Una vez procesado se puede cerrar o matar el proceso.

Otro "proceso" (sea app consola, etcétera) que se lanza a las 21:00 am, para generar un fichero CSV que se envía a un SFTP.

A partir de ahí surgen las ideas: app.Consola, tarea programada, ... servicio Windows... por el grupo leí algo de HangFire, Quartz, et´cetera.


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>


Seguramente con Powershell haya más versatilidad para hacerlo (ejemplos real world tienen?)


Sin d uda, un logging y control de errores es más que necesario. Algo básico podría ser:

            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?


Saludos. Gracias por cualquier idea o más...

Preguntón Cojonero Cabrón

unread,
Nov 30, 2017, 5:54:18 PM11/30/17
to AltNet-Hispano
Otro apunte con Servicios Windows.

En depuración (desarrollo) interesa que funcione como Aplicación de Consola, y en Release (Producción) como un servicio Windows (que se instala con comando installutil):

 

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();

}

 

 

Preguntón Cojonero Cabrón

unread,
Nov 30, 2017, 6:16:09 PM11/30/17
to AltNet-Hispano

Pensando siempre en clases helper (será un anti-patrón?) y la reutilización llegamos a: http://tech.einaregilsson.com/2007/08/15/run-windows-service-as-a-console-program/


 // Adapted from author and commenters here>
    /* "You’ll have to right click on your project in Visual Studio, 
    * choose Properties and select the Output type as ‘Console application’ for this to work."
    */

    public class NetServiceDebug
    {
        /// 
        /// Either runs service as console or windows service depending on Environment.UserInteractive
        /// 
        /// List of services to launch
        /// Command line parameters to pass along
        public static void RunServices(ServiceBase[] ServicesToRun, string[] args)
        {
            // Other alternatives to Environment.UserInteractive is to
            // 1. Use DEBUG conditional
            // 2. Use command line argument
            //#if (DEBUG)
            if (Environment.UserInteractive)
            {
                CallServiceMethod(ServicesToRun, "OnStart", new object[] { args });
                WaitPrompt(ServicesToRun);
                CallServiceMethod(ServicesToRun, "OnStop", null);
            }
            //#else
            else
            {
                ServiceBase.Run(ServicesToRun);
            }
            //#endif
        }

        private static void CallServiceMethod(ServiceBase[] ServicesToRun, string MethodName, object[] args)
        {
            Type type = typeof(ServiceBase);
            BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
            MethodInfo method = type.GetMethod(MethodName, flags);

            foreach (ServiceBase service in ServicesToRun)
            {
                method.Invoke(service, args);
            }
        }

        private static void WaitPrompt(ServiceBase[] ServicesToRun)
        {
            ConsoleKeyInfo Keypress = new ConsoleKeyInfo();
            do
            {
                Console.WriteLine("--- Press key ---");
                Console.WriteLine(" p to pause,");
                Console.WriteLine(" r to resume,");
                Console.WriteLine(" s to stop");
                Console.WriteLine("------");
                Keypress = Console.ReadKey(true);
                switch (Keypress.Key)
                {
                    case ConsoleKey.P:
                        CallServiceMethod(ServicesToRun, "OnPause", null);
                        Console.WriteLine("User> PAUSE");
                        break;
                    case ConsoleKey.R:
                        CallServiceMethod(ServicesToRun, "OnContinue", null);
                        Console.WriteLine("User> RESUME");
                        break;
                    case ConsoleKey.S:
                        // Stop is called after the prompt, don't do it here
                        Console.WriteLine("User> STOP");
                        break;
                }
            } while (Keypress.Key != ConsoleKey.S);
        }

    }

Preguntón Cojonero Cabrón

unread,
Nov 30, 2017, 6:59:26 PM11/30/17
to AltNet-Hispano

Con Tareas programadas y BAT podemos hacer ciertas cosas:

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%

Seguroq ue también con Powershell y Tareas programadas  sacamos todo el potencial..


La pregunta-duda es la diferencia (ventajas - desventajas) entre tareas programadas y servicios windows.

Saludos. Gracias de antemano!

Carlos Admirador

unread,
Dec 1, 2017, 1:23:10 PM12/1/17
to AltNet-Hispano
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.


Eugenio Pace

unread,
Dec 1, 2017, 2:38:14 PM12/1/17
to altnet-...@googlegroups.com
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/cron
No 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


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

Carlos Admirador

unread,
Dec 1, 2017, 6:01:34 PM12/1/17
to AltNet-Hispano
Eugenio, te animas a dar una VAN sobre Webtask?

Veo que hay una versión gratuita de Webtask.Desconozco la  plataforma JS/nodejs, sería bueno la VAN desde cómo configurar un entorno Windows para Webtask, hasta aplicaciones más avanzadas, todo en su vertiente más práctica.


El viernes, 1 de diciembre de 2017, 20:38:14 (UTC+1), Eugenio Pace escribió:
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/cron
No 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.

Kiquenet

unread,
Dec 2, 2017, 5:12:26 AM12/2/17
to AltNet-Hispano
Hola.

En concreto para servicios Windows, tenemos un caso asociado al hosting de servicios WCF y WebAPI.

Hay 2 escenarios para servicios WCF y WebAPI:
  1. Self hosting
  2. IIS hosting
Self hosting tanto en una aplicación de consola como un servicio Windows. Nos permite "hostear" un servicio WCF fuera del IIS.

The scenario is enabled by the managed Windows service hosting option that is a long-running WCF service hosted outside of Internet Information Services (IIS) in a secure environment that is not message activated.


No sólo para TCP, MSMQ bindings, sino también aplica a httpBinding, wshttpBinding, etcétera, 

Y con WAS, es posible "hostear" (alojar) en IIS un servicio WCF que no utilice protocolo HTTP, por ejemplo, TCP, MSMQ:

 WAS is the new process activation service that is a generalization of Internet Information Services (IIS) features that work with non-HTTP transport protocols. WCF uses the listener adapter interface to communicate activation requests that are received over the non-HTTP protocols supported by WCF, such as TCP, named pipes, and Message Queuing.


La decisión de hostear WCF en IIS o un Servicio Windows, no sabría decirte al 100%.
 
En algunos clientes que trabajé, se hacía siempre en IIS los servicios WCF (svc, wshttpbinding). Por ejemplo, se tenían varios servidores en producción con IIS, lo cual permite el balanceo (NLB, F5) y repartir la carga en las llamadas a los servicios. IIS también te permite compresión, y datos de performance (Performance Monitor) y contadores de rendimiento.

Para un servicio WCF hosteado en un servicio Windows, no sé si se podría tener "balanceo" tal cual. Ni sé la mejor forma de mediciones de performance.
Igual en algún caso, si hubiera interesado utilizar un servicio WCF con protocolo TCP (por mayor performance) en un servicio Windows, en un entorno intranet, que no expongas el servicio WCF a internet. SEguramente más compañeros del grupo aporten más conocimiento acertado.


Y también para WebAPI se puede aplicar el Self-Hosting en un servicio Windows:




Salu2.

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. 


I’m so ALT.NET that it hurts
I’m so very, very, very ALT.NET that I’m NOT going to look at Ruby, Python or any other dynamic language. Everyone’s doing it, I’m taking my own path and stay C# and VB.NET.
There, glad I finally said it. My coming out!

BY DENNIS VAN DER STELT

Kiquenet

unread,
Dec 14, 2017, 6:37:17 PM12/14/17
to AltNet-Hispano
Hola grupo!!
No sé lo que requiere montar de infraestructura Quartz o Hangfire,  alguna experiencia al respecto?

No sé si es reinventar la rueda todo esto: https://github.com/topics/task-scheduler?l=c%23

Qué tal tareas programadas y notificaciones push para avisar de su finalización ??



Tormenta de ideas?

Uzi Mamani Fernández

unread,
Dec 21, 2017, 7:54:18 AM12/21/17
to altnet-...@googlegroups.com
Sobre servicios windows, la libreria que uso es TopShelf (http://topshelf-project.com/)tambien disponible para Mono, en el IDE se ejecuta como consola, es facilmente testeable (unit test) y para instalarla como servicios con el parametro install y listo, nada de instrucciones raras para ver si estas en modo desarrollo o modo release, simplemente funciona para es la mejor forma de escribir un servicio windows.
la documentacion es super clara, les recomiendo que le den una mirada

saludos


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



--
Saludos

uZi

About me

Carlos Admirador

unread,
Apr 7, 2018, 3:40:04 AM4/7/18
to AltNet-Hispano

Un servicio Windows como  una aplicación Windows Forms:


#if DEBUG
//If Debug start winform UI
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
System.Windows.Forms.Application.Run(new fMain());

#else
//Else run as Service
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new TestService() };
ServiceBase.Run(ServicesToRun);

#endif 




Carlos Admirador

unread,
May 28, 2020, 4:31:28 AM5/28/20
to AltNet-Hispano

        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); } }

Ariel Piñeiro

unread,
Jun 26, 2020, 6:44:57 PM6/26/20
to altnet-...@googlegroups.com

windows service + quartz es lo que escala, y para instalarlo con un batch te alcanza

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

Kiquenet

unread,
Feb 27, 2025, 7:45:03 AMFeb 27
to AltNet-Hispano
Vigente en 2025 ?
Reply all
Reply to author
Forward
0 new messages