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;
page revision: 8, last edited: 20 Jan 2009 12:18