2009-05-31 16 views
8

Estoy buscando diferentes formas con fortalezas/debilidades para convertir una aplicación de consola que estamos utilizando a largo plazo en un servicio de Windows. Usamos algo llamado envoltorio de servicio de Java para ActiveMQ, y creo que la gente me ha dicho que puede envolver cualquier cosa con él. Sin embargo, eso no significa que deba envolver nada con eso; hemos tenido nuestros problemas con esta configuración.¿Cómo convertir una aplicación de consola a un servicio?

La aplicación de consola es una aplicación de consola .NET que por defecto registra mucha información en la consola, aunque esto es configurable.

¿Alguna recomendación?

¿Deberíamos simplemente reconstruirlo en Visual Studio como un servicio? Use un envoltorio ¿Cúal?

Respuesta

11

Me sentiría tentado de crear un proyecto de servicio de Windows vacío, y simplemente tomar los bits que tratan con un servicio; no es mucho, algunas referencias y parte del código en Main. Puede tener su consola actual trabajando como un servicio y como consola, ya sea verificando los argumentos a Main y usando (por ejemplo) un conmutador "-console", o creo que puede marcar Environment.UserInteractive.

Si está en el modo "consola", ejecute su código como lo hace ahora; si está en modo de servicio, ejecute el código que tomó del proyecto de la plantilla.

Para obtener información, puede también tienen el mismo trabajo exe que el instalador/desinstalador para el servicio! Lo hago con los modificadores "-install"/"-uninstall". Por ejemplo, see here.

0

Algunos pensamientos:

Create windows service with VS 2005

install .Net Service

escribí hace algún par de años un conjunto basado en Perl de ejecutables (theads), etc., que parece tener requisitos similares a los suyos .. .

Algunas cosas a tener en cuenta:

  • tienen interruptor debuggin (usted debe tener uno cuando algo va realmente mal)
  • salida a consola y archivos (tratar log4net por ejemplo)
  • construir su registro con el futuro análisis de expresiones regulares en cuenta
  • si hay algunos procesos inderdependant, aprender cómo matarlos, detener y reiniciar los
  • si hay algunos procesos inderdependant intentan comunicarse con ellos

Aquí hay un pequeño ejemplo de la consola de salida a dB, archivo y consola con log4net

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using log4net; 
    using log4net.Config; 
    using NUnit.Framework; 

    namespace ExampleConsoleApplication 
    { 
     [TestFixture] 
     class TestClass 
     { 

     //private static readonly ILog logger = 
     //  LogManager.GetLogger (typeof (TestClass)); 

     private static readonly log4net.ILog logger = log4net.LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

      static void Main (string[] args) 
      { 

       Console.WriteLine (" START "); 
       #region LoggerUsage 
       DOMConfigurator.Configure(); //tis configures the logger 
       logger.Debug ("Here is a debug log."); 
       logger.Info ("... and an Info log."); 
       logger.Warn ("... and a warning."); 
       logger.Error ("... and an error."); 
       logger.Fatal ("... and a fatal error."); 

       #endregion LoggerUsage 
       TestClass objTestClass = new TestClass(); 
       objTestClass.TestMethodNameOK(); 
       objTestClass.TestMethodNameNOK(); 

       Console.WriteLine (" END HIT A KEY TO EXIT "); 
       Console.ReadLine(); 
       } //eof method 

      [SetUp] 
      protected void SetUp() 
      { 
       //Add Here the Initialization of the objects 
      } 
      [Test (Description = "Add here the description of this test method ")] 
      protected void TestMethodNameOK() 
      { 
       //build ok use case scenario here - e.g. no exception should be raced ' 
       //Vegetable newCarrot = pool.GetItemByPropertyValue<Vegetable> ("WriongByPurpose", "Orange"); 
       //Assert.IsInstanceOfType (typeof (Vegetable), newCarrot); 
       //Assert.AreSame (newCarrot, carrot); 
       //logger.Info (" I got the newCarrot which is " + newCarrot.Color); 

      } //eof method 

      [Test (Description = "Add here the description of this test method ")] 
      protected void TestMethodNameNOK()   //e.g. the one that should raze Exception 
      { 
       //build ok use case scenario here - e.g. no exception should be raced ' 
       //Vegetable newCarrot = pool.GetItemByPropertyValue<Vegetable> ("WriongByPurpose", "Orange"); 
       //Assert.IsInstanceOfType (typeof (Vegetable), newCarrot); 
       //Assert.AreSame (newCarrot, carrot); 
       //logger.Info (" I got the newCarrot which is " + newCarrot.Color); 

      } //eof method 

     } //eof class 

    } //eof namespace 





    #region TheAppConfig 
// <?xml version="1.0" encoding="utf-8" ?> 
//<configuration> 
// <configSections> 
// <section name="log4net" 
//   type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> 
// </configSections> 

// <log4net> 
// <appender name="LogFileAppender" type="log4net.Appender.FileAppender"> 
//  <param name="File" value="Program.log" /> 
//  <param name="AppendToFile" value="true" /> 
//  <layout type="log4net.Layout.PatternLayout"> 
//  <!--<param name="Header" value="======================================" /> 
//  <param name="Footer" value="======================================" />--> 
//  <param name="ConversionPattern" value="%d [%t] %-5p - %m%n" /> 
//  </layout> 
// </appender> 

// <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> 
//  <mapping> 
//  <level value="ERROR" /> 
//  <foreColor value="Red" /> 
//  </mapping> 
//  <mapping> 
//  <level value="DEBUG" /> 
//  <foreColor value="HighIntensity" /> 
//  </mapping> 
//  <mapping> 
//  <level value="INFO" /> 
//  <foreColor value="Green" /> 
//  </mapping> 
//  <mapping> 
//  <level value="WARN" /> 
//  <foreColor value="Yellow" /> 
//  </mapping> 
//  <mapping> 
//  <level value="FATAL" /> 
//  <foreColor value="White" /> 
//  <backColor value="Red" /> 
//  </mapping> 

//  <layout type="log4net.Layout.PatternLayout"> 
//  <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" /> 
//  </layout> 
// </appender> 


// <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> 
//  <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.2.10.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
//  <connectionString value="data source=ysg;initial catalog=DBGA_DEV;integrated security=true;persist security info=True;" /> 
//  <commandText value="INSERT INTO [DBGA_DEV].[ga].[tb_Data_Log] ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)" /> 

//  <parameter> 
//  <parameterName value="@log_date" /> 
//  <dbType value="DateTime" /> 
//  <layout type="log4net.Layout.PatternLayout" value="%date{yyyy'.'MM'.'dd HH':'mm':'ss'.'fff}" /> 
//  </parameter> 
//  <parameter> 
//  <parameterName value="@thread" /> 
//  <dbType value="String" /> 
//  <size value="255" /> 
//  <layout type="log4net.Layout.PatternLayout" value="%thread" /> 
//  </parameter> 
//  <parameter> 
//  <parameterName value="@domainName" /> 
//  <dbType value="String" /> 
//  <size value="255" /> 
//  <layout type="log4net.Layout.PatternLayout" value="%user" /> 
//  </parameter> 
//  <parameter> 
//  <parameterName value="@log_level" /> 
//  <dbType value="String" /> 
//  <size value="50" /> 
//  <layout type="log4net.Layout.PatternLayout" value="%level" /> 
//  </parameter> 
//  <parameter> 
//  <parameterName value="@logger" /> 
//  <dbType value="String" /> 
//  <size value="255" /> 
//  <layout type="log4net.Layout.PatternLayout" value="%logger" /> 
//  </parameter> 
//  <parameter> 
//  <parameterName value="@message" /> 
//  <dbType value="String" /> 
//  <size value="4000" /> 
//  <layout type="log4net.Layout.PatternLayout" value="%message" /> 
//  </parameter> 
// </appender> 
// <root> 
//  <level value="ALL" /> 
//  <appender-ref ref="LogFileAppender" /> 
//  <appender-ref ref="AdoNetAppender" /> 
//  <appender-ref ref="ColoredConsoleAppender" /> 
// </root> 
// </log4net> 
//</configuration> 
    #endregion TheAppconfig 

    //this is the xml added replace here your log4net and Nunit paths 
    //<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL"> 
    // <SpecificVersion>False</SpecificVersion> 
    // <HintPath>..\..\..\Log4Net\log4net-1.2.10\bin\net\2.0\release\log4net.dll</HintPath> 
    //</Reference> 
    //<Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" /> 
2

Vici WinService convertirá una aplicación de consola en un servicio de Windows de instalación automática. Es de código abierto y puedes descargar el código fuente. Incluso si no quiere usar la biblioteca, aún puede obtener algunas ideas de ella.

0

¿Cuál es su situación de uso a largo plazo? Un servicio de Windows podría ser suficiente ... pero Windows Server 2008/IIS7 proporciona nuevas formas interesantes de alojamiento y activación de "servicios" a través de los Servicios de Activación de Windows. Un servicio de Windows siempre se ejecutará, y puede requerir alguna codificación especial. Con WAS, puede escribir su host como un servicio WCF normal, y tenerlo activado bajo demanda cuando las solicitudes entran, y desactivado cuando no se usa. También existen otras opciones ... como alojamiento e instanciación de MSMQ, etc.

0

Me encontré con este mismo problema, terminé escribiendo mi propio envoltorio, solo es bueno para las situaciones más simples, pero tiene sus ventajas. Puede encontrar la herramienta aquí: http://runasservice.com. Algunas de las ventajas incluyen el hecho de que puede codificar su aplicación como una aplicación de consola que es fácil de probar y ejecutar en el IDE. Configurar un servicio implica un comando simple para que no tenga que editar su aplicación. También puede instalar el servicio varias veces con diferentes nombres, lo que puede hacer si desea ejecutar cada uno con diferentes parámetros.

Como dije, solo cubre los escenarios más simples, aplicaciones que ya son esencialmente servicios. Eso es que corren continuamente. Estoy seguro de que hay muchos otros servicios que ofrecen muchas más opciones.

Personalmente, no creo que sea particularmente difícil convertir una aplicación de consola, pero puede ser una tarea difícil de probar. Al final, depende de la cantidad de control que desee. Si se trata de un servicio realmente importante para su empresa, entonces yo diría que lo convierta.

Cuestiones relacionadas