it-swarm.com.de

Windows-Dienst mit Timer

Ich habe einen Windows-Dienst mit Timer in c # .net erstellt. Es funktioniert gut, während ich das Projekt in Visual Studio debugge/baue, aber nach der Installation wird es nicht ausgeführt.

Was könnte der Grund dafür sein?

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"); }
            }
        }
    }
29
Nitin Kabra

Der erste Ansatz mit dem Windows-Dienst ist nicht einfach.

Vor langer Zeit schrieb ich einen C # -Dienst.

Dies ist die Logik der Service-Klasse (getestet, funktioniert gut):

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

Ich empfehle Ihnen, Ihre eigentliche Service-Arbeit in einer separaten statischen Methode zu schreiben (warum nicht, in einer Konsolenanwendung ... fügen Sie einfach einen Verweis hinzu), um das Debuggen zu vereinfachen und Service-Code zu bereinigen.

Stellen Sie sicher, dass das Intervall ausreichend ist, und schreiben Sie NUR in OnStart- und OnStop-Überschreibungen.

Hoffe das hilft!

55
T-moty

Sie müssen Ihren Hauptcode in die OnStart -Methode einfügen.

Diese andere SO Antwort von mir könnte helfen.

Sie müssen Code eingeben, um das Debuggen in Visual Studio zu ermöglichen, während Ihre Anwendung als Windows-Dienst gültig bleibt. Dieser andere SO-Thread behandelt das Problem des Debuggens eines Windows-Dienstes.

EDIT:

Bitte lesen Sie auch die Dokumentation hier für die Methode OnStart auf der MSDN, wo Sie Folgendes lesen können:

Verwenden Sie den Konstruktor nicht, um eine Verarbeitung auszuführen, die sich in OnStart befinden sollte. Verwenden Sie OnStart , um die gesamte Initialisierung Ihres Dienstes durchzuführen. Der Konstruktor wird aufgerufen, wenn die ausführbare Datei der Anwendung ausgeführt wird, nicht, wenn der Dienst ausgeführt wird. Die ausführbare Datei wird vor OnStart ausgeführt. Wenn Sie beispielsweise fortfahren, wird der Konstruktor nicht erneut aufgerufen, da der SCM das Objekt bereits im Speicher hält. Wenn OnStop die im Konstruktor zugewiesenen Ressourcen freigibt und nicht in OnStart , wird die Die erforderlichen Ressourcen werden beim zweiten Aufruf des Dienstes nicht erneut erstellt.

7
Luis Quijada

Hier ein Arbeitsbeispiel, in dem die Ausführung des Dienstes im OnTimedEvent des Timers gestartet wird, der als Delegat in der ServiceBase-Klasse implementiert ist, und die Timer-Logik in einer Methode namens SetupProcessingTimer () gekapselt wird: 

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

...
}

Das Intervall ist in app.config in Minuten definiert:

<userSettings>
    <MyProject.Properties.Settings>
        <setting name="Interval" serializeAs="String">
            <value>1</value>
        </setting>
    </MyProject.Properties.Settings>
</userSettings>
0
Uwe Köhler