Windows Service

Determining if code is running as an application or Service

We can use Environment.UserInteractive to determine this as follows;

using System.Collections.Generic;
using System.ServiceProcess;
using System.Text;
using System;
 
namespace WindowsServiceTest
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            if (Environment.UserInteractive)
            {
                Service1 service = new Service1();
                service.OnStart(null);
                Console.ReadLine();
                service.OnStop();
            }
            else
            {
                ServiceBase[] ServicesToRun;
 
                // More than one user Service may run within the same process. To add
                // another service to this process, change the following line to
                // create a second service object. For example,
                //
                //   ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
                //
                ServicesToRun = new ServiceBase[] { new Service1() };
 
                ServiceBase.Run(ServicesToRun);
            }
        }
    }
}

Template Service

// <copyright file="Lex.TemplateService.cs" company="Lex">Copyright (c) Lex.  All rights reserved.</copyright>
namespace Template.Service
{
    using System;
    using System.Configuration;
    using System.Diagnostics;
    using System.ServiceProcess;
    using System.Threading;
 
    /// <summary>The entry point for the service</summary>
    public partial class TemplateService : ServiceBase
    {
        #region members
 
        /// <summary>Private lock object for synchronisation purposes</summary>
        private static object serviceLock = new object();
 
        /// <summary>Whether the service is about to suspend work</summary>
        private bool isStopping;
 
        /// <summary>Whether the service is currently processing</summary>
        private bool isProcessing;
 
        #endregion
 
        #region constructors
 
        /// <summary>Initializes a new instance of the TemplateService class.</summary>
        public TemplateService()
        {
            this.InitializeComponent();
        }
 
        #endregion
 
        #region properties
 
        /// <summary>Gets the timer interval.</summary>
        /// <value>The timer interval.</value>
        public static int TimerInterval
        {
            get { return Convert.ToInt32(ConfigurationManager.AppSettings["TimerInterval"]); }
        }
 
        #endregion
 
        #region event handlers
 
        /// <summary>Runs when the service is started</summary>
        /// <param name="args">Startup arguments</param>
        protected override void OnStart(string[] args)
        {
            try
            {
                this.isStopping            = false;
                this.timer.AutoReset    = true;
                this.timer.Enabled        = true;
                this.timer.Interval        = TimerInterval;
                this.timer.Start();
            }
            catch (Exception exception)
            {
                Trace.TraceError("Error On Starting Timer: {0}\n{1}", exception.Message, exception.StackTrace);
                throw;
            }
 
            Trace.TraceInformation("Timer initialised correctly");
        }
 
        /// <summary>Runs when the service is stopped</summary>
        protected override void OnStop()
        {
            this.SuspendWork("stopped");
            base.OnStop();
        }
 
        /// <summary>Runs when the service is notified of a shutdown</summary>
        protected override void OnShutdown()
        {
            this.SuspendWork("shutdown");
            base.OnShutdown();
        }
 
        /// <summary>Runs when the service is paused</summary>
        protected override void OnPause()
        {
            this.SuspendWork("paused");
            base.OnPause();
        }
 
        /// <summary>Runs when the service is allowed to continue</summary>
        protected override void OnContinue()
        {
            base.OnContinue();
            this.OnStart(new string[0]);
        }
 
        /// <summary>
        /// Handles the Elapsed event of the Timer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Timers.ElapsedEventArgs"/> instance containing the event data.</param>
        protected void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            this.DoWork();
        }
 
        #endregion
 
        #region private methods
 
        /// <summary> Check to see if already running or stopping otherwise perform work</summary>
        private void DoWork()
        {
            bool allowWork = false;
            lock (serviceLock)
            {
                if (! this.isStopping && ! this.isProcessing)
                {
                    allowWork = true;
                    this.isProcessing = true;
                }
            }
 
            if (allowWork)
            {
                try
                {
                    ////.ProcessMediaWorkItems();
                }
                catch (Exception exception)
                {
                    // If an error occurs here we log, all reasonable steps to recover should already have been taken
                    Trace.TraceError("Error processing: {0}\n{1}", exception.Message, exception.StackTrace);
                    // Here you can choose to swollow exceptions (having already logged) or throw
                    // Be aware that throwing will kill the timer but not necessarily the service
                    ////throw;
                }
 
                this.isProcessing = false;
            }
        }
 
        /// <summary>Stops service timer from triggering and the service from performing more work</summary>
        /// <param name="suspendReason">The suspend action, used for logging examples include: stopped, paused and shutdown.</param>
        private void SuspendWork(string suspendReason)
        {
            this.isStopping = true;
            timer.Enabled = false;
            Trace.TraceInformation("Service operations were successfully suspended due to receiving a {0} event", suspendReason);            
        }
 
        #endregion
    }
}

Extract from Service Designer file (replace section from #region to class end)

#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.timer = new System.Timers.Timer();
            ((System.ComponentModel.ISupportInitialize)(this.timer)).BeginInit();
            // 
            // timer
            // 
            this.timer.Enabled = true;
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.Timer_Elapsed);
            // 
            // TemplateService
            // 
            this.ServiceName = "Service1";
            ((System.ComponentModel.ISupportInitialize)(this.timer)).EndInit();
 
        }
 
        #endregion
 
        private System.Timers.Timer timer;
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License