2009-05-31 150 views
8

我正在尋找不同的方法來將我們長期使用的控制檯應用程序轉換爲Windows服務的長處/弱點。我們爲ActiveMQ使用了一個名爲java service wrapper的東西,我相信有人告訴我你可以用它來包裝任何東西。這並不是說你應該用它來包裝任何東西;我們遇到了有關此設置的問題。將控制檯應用程序轉換爲服務?

控制檯應用程序是一個.NET控制檯應用程序,默認情況下會將很多信息記錄到控制檯,儘管這是可配置的。

任何reccomendations?

我們應該在Visual Studio中重建它作爲服務嗎?使用包裝?哪一個?

回答

11

我會試圖創建一個空的windows服務項目,並且只是抓住處理服務的位;它不是很多 - 幾個參考文獻和Main中的一些代碼。實際上,你可以有你的現有的控制檯工作作爲服務作爲控制檯 - 無論是通過檢查參數傳遞給Main和使用(例如)「-console」開關,或者我相信你可以檢查Environment.UserInteractive

如果它處於「控制檯」模式,請像現在這樣運行代碼;如果它處於服務模式,請運行您從模板項目中抓取的代碼。

有關信息,您可以具有相同的exe作爲服務的安裝程序/ uninstaller!我使用「-install」/「-uninstall」開關執行此操作。例如,see here

0

的幾點思考:

Create windows service with VS 2005

install .Net Service

我一些幾年前寫了一個基於Perl可執行文件集(theads)等,這似乎已經到了你類似的要求.. 。

有些東西要記住:

  • 確實有debuggin開關(你應該有一個當出現真的錯了)
  • 輸出到控制檯和文件(嘗試例如log4net的)
  • 建立與未來的正則表達式解析你的日誌記
  • 如果有一些inderdependant過程中,學習如何殺死他們,停止和重新啓動他們
  • 如果有一些inderdependant進程試圖向他們傳達

這裏是一個小控制檯例如輸出到數據庫,文件,控制檯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將把控制檯應用程序變成自行安裝的Windows服務。它是開源的,你可以下載源代碼。即使你不想使用圖書館,你仍然可以從中得到一些想法。

0

您的長期使用場景是什麼?一個Windows服務可能就足夠了......但Windows Server 2008/IIS7提供了一些有趣的新方法,通過Windows激活服務託管和激活「服務」。 Windows服務將始終運行,並可能需要一些特殊的編碼。使用WAS,您可以將主機寫爲普通的WCF服務,並在請求進入時按需激活,並在不使用時停用。其他選項也存在...比如MSMQ託管和實例化等。

0

我遇到了同樣的問題,最後我寫了自己的包裝,它只適用於最簡單的情況,但它確實有它的特權。你可以在這裏找到工具:http://runasservice.com。其中一些額外的優點包括,您可以將應用程序編寫爲易於在IDE中測試和運行的控制檯應用程序。設置服務涉及一個簡單的命令,因此您不必編輯您的應用程序。此外,您可以使用不同的名稱多次安裝該服務,如果要使用不同的參數運行每個名稱,則可能需要執行該操作。

就像我說的,雖然它只涵蓋了最簡單的場景,應用程序本來就是服務。這是他們不斷運行。我確信有很多其他的服務可以給你更多的選擇。

就我個人而言,我認爲轉換控制檯應用程序並不是特別困難,但它可能是一個麻煩的測試。最後,儘管它取決於你想要多少控制。如果這對您的公司來說真的是一項非常重要的服務,那麼我會轉換它。

相關問題