2012-10-14 19 views
27

Ho creato un servizio Windows con timer in C# .net. funziona bene mentre eseguo il debug/build del progetto in Visual Studio ma non esegue le sue operazioni dopo l'installazione.Servizio Windows con timer

Quale potrebbe essere la ragione di questo?

codice:

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

fa il conto hanno il permesso di eseguire il servizio di Windows dopo l'installazione? – urlreader

+0

yes..its admin .. –

+0

Prova a rimuovere il commento per vedere se si sta verificando un errore. Controlla anche i log degli eventi di Windows per eventuali errori. – MattW

risposta

50

primo approccio con servizio di Windows non è facile ..

Molto tempo fa, ho scritto un servizio di C#.

Questa è la logica della classe di servizio (testato, funziona bene):

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

Vi consiglio di scrivere il lavoro vero e proprio servizio in un metodo statico separato (perché no, in un'applicazione console ... basta aggiungere un riferimento ad esso), per semplificare il debug e pulire il codice del servizio.

Verificare che l'intervallo sia sufficiente e scrivere SOLO nel registro SOLO nelle sostituzioni OnStart e OnStop.

Spero che questo aiuti!

+0

"e scrive SOLO nel registro SOLO nelle sostituzioni OnStart e OnStop." Perché? Non puoi scrivere su un file di testo ad ogni evento trascorso del timer? Sto avendo quel problema ... Ho una mia funzione che scrive su file di testo (log), ma non funziona (funziona solo su start e stop), puoi aiutarmi a capire qual è il problema? –

+0

Sì, puoi anche scrivere nel metodo timer_tick, ma per me non è necessario (il metodo di lavoro principale deve scrivere il suo log). Puoi mostrarmi di più (eccezione, ecc.)? –

7

È necessario inserire il codice principale del metodo OnStart.

Questo altro SO answer potrebbe aiutare.

Sarà necessario inserire del codice per abilitare il debug all'interno di visual-studio mantenendo l'applicazione valida come servizio di Windows. Questo altro SO thread copre il problema del debug di un servizio Windows.

EDIT:

Notate anche la documentazione disponibile here per il metodo OnStart al MSDN dove si può leggere questo:

Non utilizzare il costruttore per eseguire l'elaborazione che dovrebbe essere in OnStart. Utilizzare OnStart per gestire tutte le inizializzazioni del servizio. Il costruttore viene chiamato quando viene eseguito l'eseguibile dell'applicazione, non quando viene eseguito il servizio . L'eseguibile viene eseguito prima di OnStart. Ad esempio, se si continua con , il costruttore non viene richiamato perché lo SCM contiene già l'oggetto in memoria. Se OnStop rilascia le risorse stanziate nel costruttore piuttosto che in OnStart, le necessarie risorse non sarebbero creati di nuovo la seconda volta il servizio è chiamato.

0

Ecco un esempio di lavoro in cui si avvia l'esecuzione del servizio nel OnTimedEvent del temporizzatore che è implementato come delegato nella classe ServiceBase e la logica timer viene incapsulato in un metodo chiamato 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'intervallo è definito in app.config in minuti:

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