0

I have a Windows Service. The service has static variables that record the service start time and the elapsed time (every 15 seconds).

The service start time is set in Constructor of the service, the elapsed time is recorded at OnTimer().

The OnStart() and the OnStop() are programmed to log the time to the log file. A Self Host Web API is embedded in the service to report the value of variables of the service.

When using the service manager to start and stop the service, the start or stop message is successfully logged in the log file.

My problem is when shutdown the system and reboot, there is no service stop and start message logged.

I did set the CanStop and CanShutdown to true.

It seems that the service is not stopped when the system was shutdown. This can be proved by checking the log file that no service stop and start records were logged. Also when running the Web API which shows that the start time and thus the elapsed time stayed at the same time when the last service start.

So, why did the variables of the service stay alive after a system reboot, I thought they are running in memory, but it tells not.

Does anyone have an idea? Thanks.


After some tries, I found that, when REBOOT the system, the service stop and start message are logged, the web api can return the new time value. However, when SHUTDOWN and turn on again, there is no stop and start message logged, the web api will return the old last service start time value.

So, my new question is, if the service is not stopped when shutdown, does the Constructor of the service needs to be called again when the system bootup? I am newbie to Windows Service, it is surprising if the answer is no.

    public partial class TimeGoesBy : ServiceBase
    {
        private Logger _logger;
        private static int _mainTaskInterval;
        private Timer timer;

        private static DateTime tmStartTime;
        private static TimeSpan tmElapsedTime;

        private string baseAddress;

        private static IDisposable _webapp;

        private static GameOneWorld _world;

        public TimeGoesBy() : this(LogManager.GetCurrentClassLogger())
        {
            InitializeComponent();
        }

        public TimeGoesBy(Logger logger, int mainTaskInterval = 15000) : base()
        {
            InitializeComponent();

            this.CanShutdown = true;
            this.CanStop = true;

            tmStartTime = DateTime.Now;

            this._logger = logger;

            _mainTaskInterval = mainTaskInterval;

            int interval;
            if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["TaskInterval"]))
            {
                if (Int32.TryParse(ConfigurationManager.AppSettings["TaskInterval"], out interval))
                {
                    _mainTaskInterval = interval;
                }
            }

            baseAddress = "http://" +
                (String.IsNullOrEmpty(ConfigurationManager.AppSettings["WebApiUrl"].ToString()) ? "" : ConfigurationManager.AppSettings["WebApiUrl"].ToString()) +
                (String.IsNullOrEmpty(ConfigurationManager.AppSettings["WebApiIpPort"].ToString()) ?  "/" : ":" + ConfigurationManager.AppSettings["WebApiIpPort"].ToString() + "/");

            // Start OWIN host 
            _webapp = WebApp.Start<Startup>(url: baseAddress);
            _logger.Info("Web API start at " + baseAddress);
        }

        protected override void OnStart(string[] args)
        {
            // set interval by service parameters
            if (args != null && args.Length > 0)
            {
                int intervalParameter;
                if (int.TryParse(args[0], out intervalParameter))
                { _mainTaskInterval = intervalParameter; }
            }

            // Setup timer
            timer = new Timer();
            timer.Interval = _mainTaskInterval;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
            timer.Start();
            _logger.Info("Start service...");

            base.OnStart(args);
        }

        protected override void OnStop()
        {
            _webapp?.Dispose();
            timer.Stop();
            _logger.Info("Stop service.");

            base.OnStop();
        }

        protected override void OnShutdown()
        {
            this.Stop();

            base.OnShutdown();
        }

        protected void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
        {
            try
            {
                MainTask();
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Main task exception");
            }
        }

        protected virtual void MainTask()
        {
            tmElapsedTime = DateTime.Now.Subtract(tmStartTime);
        }
    }

1 Answers1

0

Why the Windows Service not call the OnStart method?

After studied the above link, I realized that the trick is the Windows Fast Boot feature. By turning off the option, the SHUTDOWN can also log the service stop / start as expected. The Web API also reports the right value.