Link to home
Start Free TrialLog in
Avatar of VSmirk
VSmirk

asked on

C# 2005 Windows Service says is starting, but EventLog.WriteEntry() doesn't show

I have written Windows Services before, both in 2005 and in 2003, but I can't see what I'm missing.

I have a thin Windows Service that does little more than load an XML file for config options and then an external assembly which I've independantly tested.

After creating the new project with a Windows Service, and adding a timer and and installer, I have had so much difficulty figuring out what is not working that I have commented out everything but the OnStart and OnStop commands to EventLog.WriteEntry a message, essentially saying "I'm here".  But every time I reinstall my Service and start it up in the Services app, it immediately stops, and I do not get my custom EventLog entries.  I just get the default "The MultiFTP service was successfully sent a start control." messages.

Where do I need to go from here?

UPDATE:

As usual, I finally managed to get the basics to work.  Somehow though I added both the serviceInstaller and the serviceProcessIntaller, only one was shown as being added to the Installers.AddRange() method.  I do not know if this fixed my problem, because it didn't work at first, but when I cleared my events in the events viewer, suddenly it started to work for me.

I don't know why.

But now I have a different problem.  I am using a System.Windows.Forms.Timer control which supposedly fires off an event to an event handler.  But though I have a delegate method assigned to that event handler, when I attach to the process and put a breakpoint on that method, it never fires.  

I need help....

Here's the code.

using System;

namespace ServiceMultiFTP
{
    partial class ServiceMultiFTP
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void LoadConfig()
        {
            try
            {
                //Config.xml contains various configration options for the service.
                System.Xml.XmlDocument config = new System.Xml.XmlDocument();

                //Config.xml must be set as "Copy to output directory" in properties.
                config.Load(AppDomain.CurrentDomain.BaseDirectory + "Config.xml");

                this.timerMultiFTP.Interval = Convert.ToInt32(config.SelectSingleNode("//Config/Timer/IntervalInMinutes").InnerText) * 1000 * 60;

                this.EventLog.WriteEntry("Loaded Config.xml.  Interval set to " + this.timerMultiFTP.Interval.ToString() + " milliseconds.");
            }
            catch (Exception FileMissing)
            {
                this.timerMultiFTP.Interval = 1000;//600000;
                this.EventLog.WriteEntry("Missing config file Config.xml.  Interval set to " + this.timerMultiFTP.Interval.ToString() + " milliseconds.");
            }
        }

        #region Component Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.timerMultiFTP = new System.Windows.Forms.Timer(this.components);
            //
            // timerMultiFTP
            //
            this.timerMultiFTP.Interval = 1000;
            this.timerMultiFTP.Tick += new System.EventHandler(this.timerMultiFTP_Tick);
            this.timerMultiFTP.Disposed += new System.EventHandler(this.timerMultiFTP_Disposed);
            //
            // ServiceMultiFTP
            //
            this.AutoLog = false;
            this.CanPauseAndContinue = true;
            this.ServiceName = "ServiceMultiFTP";

        }

        #endregion

        private System.Windows.Forms.Timer timerMultiFTP;
    }
}


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;

namespace ServiceMultiFTP
{
    public partial class ServiceMultiFTP : ServiceBase
    {
        public ServiceMultiFTP()
        {
            InitializeComponent();
        }

        /// <summary>
        /// This will attempt to find a config file called Config.xml, but
        /// failing that it will simply use default values.
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            this.EventLog.WriteEntry("MultiFTP has started, dude!");
            LoadConfig();
            this.timerMultiFTP.Enabled = true;
        }

        protected override void OnStop()
        {
            this.EventLog.WriteEntry("MultiFTP has stopped, dude.");

            this.timerMultiFTP.Enabled = false;
        }

        private void timerMultiFTP_Tick(object sender, EventArgs e)
        {
            timerMultiFTP.Stop();

            this.EventLog.WriteEntry("MultiFTP cycle begun, checking for reports");

            MultiFTP.AutomatedProcessMain TheAutomatedApp = new MultiFTP.AutomatedProcessMain();

            TheAutomatedApp.RunMain();

            timerMultiFTP.Start();
        }

        private void timerMultiFTP_Disposed(object sender, EventArgs e)
        {
            this.EventLog.WriteEntry("timerMultiFTP disposed.");
        }
    }
}


Now that the installers are correctly starting and stopping the service, I'll assume that the installer code is not necessary.

V
ASKER CERTIFIED SOLUTION
Avatar of cookre
cookre
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of VSmirk
VSmirk

ASKER

Absolutely debug mode breakpoints in a service!

One of the best features of .Net 2005 (though I don't know for a fact that you couldn't do it earlier).  When your service is installed and running, you can go back to your IDE and "attach to a process" and find your running service there.  As far as I know, you can't do it quickly enough to get to a breakpoint in the OnStart, unless you put a delay in that block, but in other Windows Services, I have been able to put breakpoints on all of the other methods, like FileSystemWatcher event handlers, OnStop() and many others.  This is the first time using the timer control, though.

To that end, the reason I am using the timer I am is because that's the one that is provided by default in the Toolbox.  

Does the System.Timers control have the same interface?
Avatar of VSmirk

ASKER

Regardless, though, it looks like your suggestion to change the timer control did the trick.  I had to re-do some of the delegation, but it appears to work like a charm.  When I attach to the process in debug mode and put a breakpoint on the timer event handler, I came back around the time I hoped to see the event fired, and lo' there was the bright yellow break point line on my windows service!

Thanks for the help!

V
Dunno, I don't use the winforms one.  Here's a sample:

System.Timers.Timer  STimer;

...

STimer=new System.Timers.Timer();
STimer.Elapsed+=new ElapsedEventHandler(STimerTriggered);
STimer.Interval=500;
STimer.Enabled=true;



void STimerTriggered(object source,ElapsedEventArgs evt)
{
STimer.Enabled=false; // Leave us not interrupt ourselves
...
STimer.Enabled=true; // Leave us not interrupt ourselves
}



I've never had any problems in either a normal service or an interactive one.