• Regarding the user of a Windows Service, the following is the code that we use:

    using System;

    using System.ServiceProcess;

    using System.Threading;

    namespace ROAMLogService

    {

    public delegate void ThreadCallback ( string Message );

    public partial class ROAMLogService : ServiceBase

    {

    private ServiceThread ST;

    private Thread m_ServiceThread;

    public ROAMLogService ()

    {

    InitializeComponent ();

    }

    public void StartService ()

    {

    this.ST = new ServiceThread ( new ThreadCallback ( ServiceEnded ) );

    this.m_ServiceThread = new Thread ( new ThreadStart ( ST.Run ) );

    this.m_ServiceThread.Start ();

    }

    private void ServiceEnded ( string Message )

    {

    Thread.Sleep ( 3000 );

    this.StartService ();

    }

    protected override void OnStart ( string[] args )

    {

    this.StartService ();

    }

    protected override void OnStop ()

    {

    this.ST.Terminate = true;

    Thread.Sleep ( 3000 );

    if ( this.m_ServiceThread != null )

    {

    this.m_ServiceThread.Abort ();

    this.m_ServiceThread.Join ();

    }

    }

    }

    }

    The Service Thread is where all of the work is done:

    using System;

    using System.Data.SqlClient;

    using System.IO;

    using System.Xml;

    namespace ROAMLogService

    {

    class ServiceThread

    {

    private bool m_Terminate = false;

    public bool Terminate

    {

    set { this.m_Terminate = value; }

    }

    private string LogConnectionString;

    private string LogFolder = "";

    private string ArchiveFolder = "";

    private ThreadCallback m_Callback;

    public ServiceThread ( ThreadCallback Callback )

    {

    this.m_Callback = Callback;

    this.LogFolder = System.Configuration.ConfigurationManager.AppSettings[ "LogFolder" ].ToString ();

    this.ArchiveFolder = this.LogFolder + @"\Old Logs";

    this.LogConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings[ "Logging" ].ToString ();

    if ( this.LogConnectionString == null )

    {

    this.m_Callback ( "Log ConnectionString not found - exiting" );

    this.m_Terminate = true;

    }

    }

    public void Run ()

    {

    try

    {

    using ( SqlConnection Conn = new SqlConnection ( this.LogConnectionString ) )

    {

    Conn.Open ();

    using ( SqlCommand Cmd = Conn.CreateCommand () )

    {

    Cmd.CommandText = "ProcessLogQueue";

    Cmd.CommandType = System.Data.CommandType.StoredProcedure;

    Cmd.CommandTimeout = 0;

    while ( !this.m_Terminate )

    {

    string Response = Cmd.ExecuteScalar ().ToString ();

    if ( Response.Length > 0 )

    {

    XmlDocument Doc = new XmlDocument ();

    Doc.LoadXml ( Response );

    XmlNode RootNode = Doc.SelectSingleNode ( "LOG" );

    XmlNode RowNode = RootNode.SelectSingleNode ( "Row" );

    string ProcessName = RowNode.SelectSingleNode ( "ProcessName" ).InnerText;

    string MachineName = RowNode.SelectSingleNode ( "MachineName" ).InnerText;

    string MachineFolder = Path.Combine ( this.LogFolder, MachineName );

    if ( !Directory.Exists ( MachineFolder ) )

    {

    try

    {

    Directory.CreateDirectory ( MachineFolder );

    }

    catch ( Exception Ex )

    {

    this.Log ( "Run", Ex.ToString () );

    return;

    }

    }

    if ( System.Diagnostics.Debugger.IsAttached )

    {

    Console.WriteLine ( "Processing message from {0}:{1}", MachineName, ProcessName );

    }

    string FileName = Path.Combine ( MachineFolder, ProcessName + ".log" );

    try

    {

    this.CheckLog ( MachineName, FileName );

    }

    catch ( Exception Ex )

    {

    return;

    }

    using ( StreamWriter SW = new StreamWriter ( FileName, true ) )

    {

    SW.WriteLine ( string.Format ( "{0} {1}", RowNode.SelectSingleNode ( "LogTime" ).InnerText, RowNode.SelectSingleNode ( "ProcessMessage" ).InnerText ) );

    }

    }

    }

    }

    }

    }

    catch ( SqlException Ex )

    {

    this.m_Callback ( Ex.Message );

    }

    catch ( Exception Ex )

    {

    this.m_Callback ( Ex.Message );

    }

    }

    private void CheckLog ( string MachineName, string FileName )

    {

    FileInfo FI = new FileInfo ( FileName );

    if ( FI.Exists )

    {

    DateTime Today = Convert.ToDateTime ( DateTime.Now.ToShortDateString () );

    if ( FI.LastWriteTime < Today )

    {

    string ArchiveFileName = Path.GetFileName ( FileName ).Replace ( ".log", FI.LastWriteTime.ToString ( "yyyyMMdd" ) + ".log" );

    string MachineFolder = Path.Combine ( this.ArchiveFolder, MachineName );

    if ( !Directory.Exists ( MachineFolder ) )

    {

    Directory.CreateDirectory ( MachineFolder );

    }

    FI.MoveTo ( Path.Combine ( MachineFolder, ArchiveFileName ) );

    }

    }

    }

    }

    }

    The important thing to remember about Windows Services is that they MUST return quickly from the Start command.

    Hope this helps.

    Ed