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