2012-10-14 4 views
27

J'ai créé un service Windows avec minuterie dans C# .net. cela fonctionne bien pendant que je débogue/construit le projet en studio visuel mais il ne fonctionne pas après l'installation.Service Windows avec minuterie

Quelle pourrait être la raison derrière cela?

code:

public partial class Service1 : ServiceBase 
{ 
     FileStream fs; 
     StreamWriter m_streamWriter; 
     Timer tm = new Timer(); 

     public Service1() 
     { 
      InitializeComponent(); 

      this.ServiceName = "timerservice"; 

      tm.Interval = 2000; 
      tm.Tick += new EventHandler(PerformOperations); 
      tm.Start(); 

      fs = new FileStream(@"c:\mcWindowsService.txt", FileMode.OpenOrCreate, FileAccess.Write); 

      m_streamWriter = new StreamWriter(fs); 
      m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); 
     } 

     private void PerformOperations(object sener, EventArgs e) 
     { 
      //StreamWriter swr = new StreamWriter("c:\\test_from_database.txt",true); 

      try 
      { 
       OdbcConnection con = new OdbcConnection("DSN=liquor_data"); 

       OdbcDataAdapter adp = new OdbcDataAdapter("", con); 

       DataSet ds = new DataSet(); 

       string sql = "select * from item_group"; 
       adp.SelectCommand.CommandText = sql; 

       adp.Fill(ds, "item_group"); 

       foreach (DataRow dr in ds.Tables["item_group"].Rows) 
       { 
        //  swr.Write(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); 

        //Console.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); 
        m_streamWriter.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); 
       } 

       m_streamWriter.Flush(); 
      } 

      catch (Exception ex) 
      { 
       // swr.Write("Error :"+ ex.Message + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); } 
      } 
     } 
    } 
+0

tient-elle compte avoir l'autorisation d'exécuter le service windows après l'installation? – urlreader

+0

yes..its admin .. –

+0

Essayez de décommenter la capture pour voir si une erreur est en train de se produire. Consultez également les journaux des événements Windows pour les erreurs éventuelles. – MattW

Répondre

50

Première approche avec Windows Le service est pas facile ..

Il y a longtemps, j'ai écrit un service C#.

Telle est la logique de la classe de service (testé, fonctionne très bien):

namespace MyServiceApp 
{ 
    public class MyService : ServiceBase 
    { 
     private System.Timers.Timer timer; 

     protected override void OnStart(string[] args) 
     { 
      this.timer = new System.Timers.Timer(30000D); // 30000 milliseconds = 30 seconds 
      this.timer.AutoReset = true; 
      this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed); 
      this.timer.Start(); 
     } 

     protected override void OnStop() 
     { 
      this.timer.Stop(); 
      this.timer = null; 
     } 

     private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
     { 
      MyServiceApp.ServiceWork.Main(); // my separate static method for do work 
     } 

     public MyService() 
     { 
      this.ServiceName = "MyService"; 
     } 

     // service entry point 
     static void Main() 
     { 
      System.ServiceProcess.ServiceBase.Run(new MyService()); 
     } 
    } 
} 

Je vous conseille d'écrire votre travail de service réel dans une méthode statique séparée (pourquoi pas, dans une application de la console ... ajoutez simplement une référence à celui-ci), pour simplifier le débogage et nettoyer le code de service.

Assurez-vous que l'intervalle est suffisant et écrivez UNIQUEMENT dans les journaux OnStart et OnStop.

Espérons que cela aide!

+0

"et écrire dans le journal UNIQUEMENT dans les commandes OnStart et OnStop." Pourquoi? Vous ne pouvez pas écrire dans un fichier texte à chaque événement écoulé? J'ai ce problème ... J'ai ma propre fonction qui écrit dans le fichier texte (journal), mais il ne fonctionne pas (ne fonctionne que sur le démarrage et l'arrêt), pouvez-vous m'aider à comprendre quel est le problème? –

+0

Oui, vous pouvez aussi écrire dans la méthode timer_tick, mais pour moi c'est inutile (la méthode de travail principale doit écrire son journal). Pouvez-vous me montrer plus (exception, etc.)? –

7

Vous devez mettre votre code principal sur la méthode OnStart.

Cet autre SO answer peut aider.

Vous aurez besoin de mettre du code pour activer le débogage dans visual-studio tout en maintenant votre application valide en tant que service Windows. Cet autre SO thread couvre le problème du débogage d'un service Windows.

EDIT:

S'il vous plaît voir aussi la documentation disponible here pour la méthode OnStart au MSDN où l'on peut lire ceci:

Ne pas utiliser le constructeur pour effectuer un traitement qui devrait être OnStart. Utilisez OnStart pour gérer l'initialisation de votre service. Le constructeur est appelé lorsque l'exécutable de l'application s'exécute, pas lorsque le service s'exécute. L'exécutable s'exécute avant OnStart. Lorsque vous continuer, par exemple, le constructeur n'est pas appelé à nouveau car le SCM contient déjà l'objet en mémoire. Si OnStop libère les ressources allouées dans le constructeur plutôt que dans OnStart, les ressources nécessaires ne seraient pas créés à nouveau la deuxième fois que le service est appelé .

0

Voici un exemple de travail dans lequel l'exécution du service est démarré dans le OnTimedEvent de la minuterie qui est mis en œuvre en tant que délégué dans la classe ServiceBase et la logique de la minuterie est encapsulé dans une méthode appelée SetupProcessingTimer():

public partial class MyServiceProject: ServiceBase 
{ 

private Timer _timer; 

public MyServiceProject() 
{ 
    InitializeComponent(); 
} 

private void SetupProcessingTimer() 
{ 
    _timer = new Timer(); 
    _timer.AutoReset = true; 
    double interval = Settings.Default.Interval; 
    _timer.Interval = interval * 60000; 
    _timer.Enabled = true; 
    _timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
} 

private void OnTimedEvent(object source, ElapsedEventArgs e) 
{ 
    // begin your service work 
    MakeSomething(); 
} 

protected override void OnStart(string[] args) 
{ 
    SetupProcessingTimer(); 
} 

... 
} 

l'intervalle est défini dans app.config en quelques minutes:

<userSettings> 
    <MyProject.Properties.Settings> 
     <setting name="Interval" serializeAs="String"> 
      <value>1</value> 
     </setting> 
    </MyProject.Properties.Settings> 
</userSettings>