From a147e976bfb8f79825112c04837f25ed07cd74cf Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Thu, 10 Jul 2014 22:34:56 -0400 Subject: [PATCH] Added new logging backend. --- GlobalTerminalService/GTServer4.cs | 73 +++++++++++++----- GlobalTerminalService/GTServer5.cs | 71 ++++++++++++------ GlobalTerminalService/GTServerBase.cs | 56 ++++++++++---- library/Library.csproj | 1 + library/Support/AssertHelper.cs | 24 ++---- library/Support/LogHelper.cs | 102 ++++++++++++++++++++++++++ 6 files changed, 252 insertions(+), 75 deletions(-) create mode 100644 library/Support/LogHelper.cs diff --git a/GlobalTerminalService/GTServer4.cs b/GlobalTerminalService/GTServer4.cs index 000bf7f4..b0924bcd 100644 --- a/GlobalTerminalService/GTServer4.cs +++ b/GlobalTerminalService/GTServer4.cs @@ -6,6 +6,8 @@ using System.IO; using PkmnFoundations.Support; using PkmnFoundations.Structures; using PkmnFoundations.Data; +using System.Net.Sockets; +using System.Diagnostics; namespace PkmnFoundations.GlobalTerminalService { @@ -40,13 +42,16 @@ namespace PkmnFoundations.GlobalTerminalService } } - protected override byte[] ProcessRequest(byte[] data) + protected override byte[] ProcessRequest(byte[] data, TcpClient c) { int length = BitConverter.ToInt32(data, 0); AssertHelper.Equals(length, data.Length); RequestTypes4 requestType = (RequestTypes4)data[4]; - Console.WriteLine("Handling Generation IV {0} request.", requestType); + StringBuilder logEntry = new StringBuilder(); + logEntry.AppendFormat("Handling Generation IV {0} request.\nHost: {1}", requestType, c.Client.RemoteEndPoint); + logEntry.AppendLine(); + EventLogEntryType type = EventLogEntryType.Information; CryptMessage(data); @@ -60,6 +65,8 @@ namespace PkmnFoundations.GlobalTerminalService int pid = BitConverter.ToInt32(data, 8); byte version = data[0x0c]; byte language = data[0x0d]; + logEntry.AppendFormat("pid: {0}", pid); + logEntry.AppendLine(); switch (requestType) { @@ -67,6 +74,8 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x360) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -79,12 +88,13 @@ namespace PkmnFoundations.GlobalTerminalService if (serial == 0) { - Console.WriteLine("Uploaded box already in server."); + logEntry.AppendLine("Uploaded box already in server."); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } - Console.WriteLine("Box uploaded successfully."); + logEntry.AppendFormat("Box {0} uploaded successfully.", record.SerialNumber); + logEntry.AppendLine(); response.Write(new byte[] { 0x00, 0x00 }, 0, 2); // result code (0 for OK) response.Write(BitConverter.GetBytes(serial), 0, 8); @@ -93,6 +103,8 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x14c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -111,13 +123,16 @@ namespace PkmnFoundations.GlobalTerminalService response.Write(BitConverter.GetBytes(result.SerialNumber), 0, 8); response.Write(result.Data, 0, 0x21c); } - Console.WriteLine("Retrieved {0} boxes.", results.Length); + logEntry.AppendFormat("Retrieved {0} boxes.", results.Length); + logEntry.AppendLine(); } break; case RequestTypes4.DressupUpload: { if (data.Length != 0x220) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -129,12 +144,12 @@ namespace PkmnFoundations.GlobalTerminalService if (serial == 0) { - Console.WriteLine("Uploaded dressup already in server."); + logEntry.AppendLine("Uploaded dressup already in server."); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } - Console.WriteLine("Dressup uploaded successfully."); + logEntry.AppendFormat("Dressup {0} uploaded successfully.", record.SerialNumber); response.Write(new byte[] { 0x00, 0x00 }, 0, 2); // result code (0 for OK) response.Write(BitConverter.GetBytes(serial), 0, 8); @@ -143,6 +158,8 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x14c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -160,13 +177,16 @@ namespace PkmnFoundations.GlobalTerminalService response.Write(BitConverter.GetBytes(result.SerialNumber), 0, 8); response.Write(result.Data, 0, 0xe0); } - Console.WriteLine("Retrieved {0} dressup results.", results.Length); + logEntry.AppendFormat("Retrieved {0} dressup results.", results.Length); + logEntry.AppendLine(); } break; case RequestTypes4.BattleVideoUpload: { if (data.Length != 0x1e8c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -178,12 +198,13 @@ namespace PkmnFoundations.GlobalTerminalService if (serial == 0) { - Console.WriteLine("Uploaded battle video already in server."); + logEntry.AppendFormat("Uploaded battle video already in server."); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } - Console.WriteLine("Battle video uploaded successfully."); + logEntry.AppendFormat("Battle video {0} uploaded successfully.", BattleVideoHeader4.FormatSerial(record.SerialNumber)); + logEntry.AppendLine(); response.Write(new byte[] { 0x00, 0x00 }, 0, 2); // result code (0 for OK) response.Write(BitConverter.GetBytes(serial), 0, 8); @@ -192,6 +213,8 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x15c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -202,15 +225,15 @@ namespace PkmnFoundations.GlobalTerminalService byte country = data[0x147]; byte region = data[0x148]; - Console.Write("Searching for "); + logEntry.AppendFormat("Searching for "); if (species != 0xffff) - Console.Write("species {0}, ", species); - Console.Write("{0}", meta); + logEntry.AppendFormat("species {0}, ", species); + logEntry.AppendFormat("{0}", meta); if (country != 0xff) - Console.Write(", country {0}", country); + logEntry.AppendFormat(", country {0}", country); if (region != 0xff) - Console.Write(", region {0}", region); - Console.WriteLine("."); + logEntry.AppendFormat(", region {0}", region); + logEntry.AppendLine("."); BattleVideoHeader4[] results = DataAbstract.Instance.BattleVideoSearch4(species, meta, country, region, 30); response.Write(new byte[] { 0x00, 0x00 }, 0, 2); // result code (0 for OK) @@ -222,13 +245,16 @@ namespace PkmnFoundations.GlobalTerminalService response.Write(BitConverter.GetBytes(result.SerialNumber), 0, 8); response.Write(result.Data, 0, 0xe4); } - Console.WriteLine("Retrieved {0} battle video results.", results.Length); + logEntry.AppendFormat("Retrieved {0} battle video results.", results.Length); + logEntry.AppendLine(); } break; case RequestTypes4.BattleVideoWatch: { if (data.Length != 0x14c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -238,7 +264,9 @@ namespace PkmnFoundations.GlobalTerminalService if (record == null) { response.Write(new byte[] { 0x02, 0x00 }, 0, 2); - Console.WriteLine("Requested battle video {0} was missing.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendFormat("Requested battle video {0} was missing.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendLine(); + type = EventLogEntryType.FailureAudit; break; } @@ -247,17 +275,20 @@ namespace PkmnFoundations.GlobalTerminalService response.Write(BitConverter.GetBytes(record.SerialNumber), 0, 8); response.Write(record.Header.Data, 0, 0xe4); response.Write(record.Data, 0, 0x1c68); - Console.WriteLine("Retrieved battle video {0}.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendFormat("Retrieved battle video {0}.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendLine(); } break; default: + logEntry.AppendLine("Unrecognized request type."); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } } catch (Exception ex) { - Console.WriteLine(ex.ToString()); + logEntry.AppendFormat("Unhandled exception while handling request.\nException: {0}", ex.ToString()); + logEntry.AppendLine(); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); } @@ -265,6 +296,8 @@ namespace PkmnFoundations.GlobalTerminalService byte[] responseData = response.ToArray(); WriteLength(responseData); CryptMessage(responseData); + + LogHelper.Write(logEntry.ToString(), type); return responseData; } diff --git a/GlobalTerminalService/GTServer5.cs b/GlobalTerminalService/GTServer5.cs index c89892c9..33a5e02f 100644 --- a/GlobalTerminalService/GTServer5.cs +++ b/GlobalTerminalService/GTServer5.cs @@ -7,6 +7,8 @@ using System.IO; using PkmnFoundations.Structures; using PkmnFoundations.Data; using System.Security.Cryptography.X509Certificates; +using System.Net.Sockets; +using System.Diagnostics; namespace PkmnFoundations.GlobalTerminalService { @@ -41,13 +43,16 @@ namespace PkmnFoundations.GlobalTerminalService } - protected override byte[] ProcessRequest(byte[] data) + protected override byte[] ProcessRequest(byte[] data, TcpClient c) { int length = BitConverter.ToInt32(data, 0); AssertHelper.Equals(length, data.Length); RequestTypes5 requestType = (RequestTypes5)data[4]; - Console.WriteLine("Handling Generation V {0} request.", requestType); + StringBuilder logEntry = new StringBuilder(); + logEntry.AppendFormat("Handling Generation V {0} request.\nHost: {1}", requestType, c.Client.RemoteEndPoint); + logEntry.AppendLine(); + EventLogEntryType type = EventLogEntryType.Information; MemoryStream response = new MemoryStream(); response.Write(new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0, 4); // placeholder for length @@ -59,6 +64,8 @@ namespace PkmnFoundations.GlobalTerminalService int pid = BitConverter.ToInt32(data, 8); byte version = data[0x0c]; byte language = data[0x0d]; + logEntry.AppendFormat("pid: {0}", pid); + logEntry.AppendLine(); switch (requestType) { @@ -66,6 +73,8 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x370) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -77,12 +86,13 @@ namespace PkmnFoundations.GlobalTerminalService if (serial == 0) { - Console.WriteLine("Uploaded musical already in server."); + logEntry.AppendLine("Uploaded musical already in server."); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } - Console.WriteLine("Musical uploaded successfully."); + logEntry.AppendFormat("Musical {0} uploaded successfully.", record.SerialNumber); + logEntry.AppendLine(); response.Write(new byte[] { 0x00, 0x00 }, 0, 2); // result code (0 for OK) response.Write(BitConverter.GetBytes(serial), 0, 8); @@ -91,6 +101,8 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x14c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -108,7 +120,8 @@ namespace PkmnFoundations.GlobalTerminalService response.Write(BitConverter.GetBytes(result.SerialNumber), 0, 8); response.Write(result.Data, 0, 0x230); } - Console.WriteLine("Retrieved {0} dressup results.", results.Length); + logEntry.AppendFormat("Retrieved {0} dressup results.", results.Length); + logEntry.AppendLine(); } break; @@ -116,6 +129,8 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x1ae8) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -138,12 +153,13 @@ namespace PkmnFoundations.GlobalTerminalService if (serial == 0) { - Console.WriteLine("Uploaded battle video already in server."); + logEntry.AppendLine("Uploaded battle video already in server."); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } - Console.WriteLine("Battle video uploaded successfully."); + logEntry.AppendFormat("Battle video {0} uploaded successfully.", BattleVideoHeader4.FormatSerial(record.SerialNumber)); + logEntry.AppendLine(); response.Write(new byte[] { 0x00, 0x00 }, 0, 2); // result code (0 for OK) response.Write(BitConverter.GetBytes(serial), 0, 8); @@ -152,12 +168,14 @@ namespace PkmnFoundations.GlobalTerminalService { if (data.Length != 0x15c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } // todo: validate or log some of this? - BattleVideoRankings5 type = (BattleVideoRankings5)BitConverter.ToUInt32(data, 0x140); + BattleVideoRankings5 ranking = (BattleVideoRankings5)BitConverter.ToUInt32(data, 0x140); ushort species = BitConverter.ToUInt16(data, 0x144); BattleVideoMetagames5 meta = (BattleVideoMetagames5)data[0x146]; @@ -169,19 +187,19 @@ namespace PkmnFoundations.GlobalTerminalService byte country = data[0x14a]; byte region = data[0x14b]; - Console.Write("Searching for "); - if (type != BattleVideoRankings5.None) - Console.Write("{0}, ", type); + logEntry.Append("Searching for "); + if (ranking != BattleVideoRankings5.None) + logEntry.AppendFormat("{0}, ", type); if (species != 0xffff) - Console.Write("species {0}, ", species); - Console.Write("{0}", meta); + logEntry.AppendFormat("species {0}, ", species); + logEntry.AppendFormat("{0}", meta); if (country != 0xff) - Console.Write(", country {0}", country); + logEntry.AppendFormat(", country {0}", country); if (region != 0xff) - Console.Write(", region {0}", region); - Console.WriteLine("."); + logEntry.AppendFormat(", region {0}", region); + logEntry.AppendLine("."); - BattleVideoHeader5[] results = DataAbstract.Instance.BattleVideoSearch5(species, type, meta, country, region, 30); + BattleVideoHeader5[] results = DataAbstract.Instance.BattleVideoSearch5(species, ranking, meta, country, region, 30); response.Write(new byte[] { 0x00, 0x00 }, 0, 2); // result code (0 for OK) response.Write(BitConverter.GetBytes(results.Length), 0, 4); @@ -191,13 +209,16 @@ namespace PkmnFoundations.GlobalTerminalService response.Write(BitConverter.GetBytes(result.SerialNumber), 0, 8); response.Write(result.Data, 0, 0xc4); } - Console.WriteLine("Retrieved {0} battle video results.", results.Length); + logEntry.AppendFormat("Retrieved {0} battle video results.", results.Length); + logEntry.AppendLine(); } break; case RequestTypes5.BattleVideoWatch: { if (data.Length != 0x14c) { + logEntry.AppendLine("Length did not validate."); + type = EventLogEntryType.FailureAudit; response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } @@ -207,7 +228,9 @@ namespace PkmnFoundations.GlobalTerminalService if (record == null) { response.Write(new byte[] { 0x02, 0x00 }, 0, 2); - Console.WriteLine("Requested battle video {0} was missing.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendFormat("Requested battle video {0} was missing.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendLine(); + type = EventLogEntryType.FailureAudit; break; } @@ -216,24 +239,30 @@ namespace PkmnFoundations.GlobalTerminalService response.Write(BitConverter.GetBytes(record.SerialNumber), 0, 8); response.Write(record.Header.Data, 0, 0xc4); response.Write(record.Data, 0, 0x17e0); - Console.WriteLine("Retrieved battle video {0}.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendFormat("Retrieved battle video {0}.", BattleVideoHeader4.FormatSerial(serial)); + logEntry.AppendLine(); } break; default: + logEntry.AppendLine("Unrecognized request type."); + response.Write(new byte[] { 0x02, 0x00 }, 0, 2); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); break; } } catch (Exception ex) { - Console.WriteLine(ex.ToString()); + logEntry.AppendFormat("Unhandled exception while handling request.\nException: {0}", ex.ToString()); + logEntry.AppendLine(); response.Write(new byte[] { 0x02, 0x00 }, 0, 2); } response.Flush(); byte[] responseData = response.ToArray(); WriteLength(responseData); + + LogHelper.Write(logEntry.ToString(), type); return responseData; } diff --git a/GlobalTerminalService/GTServerBase.cs b/GlobalTerminalService/GTServerBase.cs index 41ee0a1d..e1e1bfed 100644 --- a/GlobalTerminalService/GTServerBase.cs +++ b/GlobalTerminalService/GTServerBase.cs @@ -9,6 +9,7 @@ using System.Security.Cryptography.X509Certificates; using System.Net.Security; using System.Net; using PkmnFoundations.Support; +using System.Diagnostics; namespace PkmnFoundations.GlobalTerminalService { @@ -79,7 +80,7 @@ namespace PkmnFoundations.GlobalTerminalService { if (m_workers.Count > 0) return; - Console.WriteLine("{0} server running on port {1} with {2} threads.", Title, ((IPEndPoint)m_listener.LocalEndpoint).Port, Threads); + LogHelper.Write(String.Format("{0} server running on port {1} with {2} threads.", Title, ((IPEndPoint)m_listener.LocalEndpoint).Port, Threads)); m_closing = false; m_listener.Start(); @@ -108,7 +109,8 @@ namespace PkmnFoundations.GlobalTerminalService private void MainLoop(object o) { int threadIndex = m_workers.IndexOf(Thread.CurrentThread); - Console.WriteLine("Thread {0} begins.", threadIndex); + // This is too chatty for an event log. + //LogHelper.Write(String.Format("Thread {0} begins.", threadIndex)); while (!m_closing) { @@ -127,28 +129,52 @@ namespace PkmnFoundations.GlobalTerminalService continue; } - c.ReceiveTimeout = Timeout; - c.SendTimeout = Timeout; + try + { + c.ReceiveTimeout = Timeout; + c.SendTimeout = Timeout; - Stream s = GetStream(c); - BinaryReader br = new BinaryReader(s); + Stream s = GetStream(c); + BinaryReader br = new BinaryReader(s); - int length = br.ReadInt32(); - byte[] data = new byte[length]; - BitConverter.GetBytes(length).CopyTo(data, 0); - br.ReadBlock(data, 4, length - 4); + int length = br.ReadInt32(); + if (length > 7820) + { + LogHelper.Write(String.Format("Indicated request length is over limit.\nHost: {0}", c.Client.RemoteEndPoint), EventLogEntryType.FailureAudit); + continue; + } + if (length < 320) + { + LogHelper.Write(String.Format("Indicated request length is under limit.\nHost: {0}", c.Client.RemoteEndPoint), EventLogEntryType.FailureAudit); + continue; + } - byte[] response = ProcessRequest(data); - s.Write(response, 0, response.Length); + byte[] data = new byte[length]; + BitConverter.GetBytes(length).CopyTo(data, 0); + + int actualLength = br.ReadBlock(data, 4, length - 4); + if (actualLength + 4 != length) + { + LogHelper.Write(String.Format("The client disconnected prematurely.\nHost: {0}", c.Client.RemoteEndPoint), EventLogEntryType.FailureAudit); + continue; + } + + byte[] response = ProcessRequest(data, c); + s.Write(response, 0, response.Length); + } + catch (Exception ex) + { + LogHelper.Write(String.Format("Unhandled exception while handling request:\nHost: {0}\nException: {1}", c.Client.RemoteEndPoint, ex.Message), EventLogEntryType.Error); + } } } catch (Exception ex) { - Console.WriteLine(ex.ToString()); + LogHelper.Write(String.Format("Unhandled exception while handling request:\nException: {0}", ex.Message), EventLogEntryType.Error); } } - Console.WriteLine("Thread {0} ends.", threadIndex); + //LogHelper.Write(String.Format("Thread {0} ends.", threadIndex)); m_workers.Remove(Thread.CurrentThread); } @@ -172,7 +198,7 @@ namespace PkmnFoundations.GlobalTerminalService else return c.GetStream(); } - protected abstract byte[] ProcessRequest(byte[] data); + protected abstract byte[] ProcessRequest(byte[] data, TcpClient c); public abstract String Title { get; } diff --git a/library/Library.csproj b/library/Library.csproj index 055bdf66..60a6bab6 100644 --- a/library/Library.csproj +++ b/library/Library.csproj @@ -66,6 +66,7 @@ + diff --git a/library/Support/AssertHelper.cs b/library/Support/AssertHelper.cs index 2ff22e6a..374a6b37 100644 --- a/library/Support/AssertHelper.cs +++ b/library/Support/AssertHelper.cs @@ -10,25 +10,11 @@ namespace PkmnFoundations.Support { public static void Assert(bool condition, String message) { - if (!condition) try - { - using (StreamWriter s = File.CreateText("assert.log")) - { - s.Write("Assert failed: "); - s.WriteLine(message); - s.Write("Date: "); - s.WriteLine(DateTime.Now.ToString("G")); - s.Write("Stack trace: "); - s.WriteLine(new StackTrace(true).ToString()); - s.WriteLine(); - } - } - catch (Exception) - { - // directory not found or no write permissions there - } + if (!condition) LogHelper.Write(message, EventLogEntryType.Error); +#if DEBUG Debug.Assert(condition, message); +#endif } public static void Assert(bool condition) @@ -38,12 +24,12 @@ namespace PkmnFoundations.Support public static void Unreachable() { - Assert(false, "Unreachable code has been reached."); + Assert(false, "Assert failed: Unreachable code has been reached."); } public static void Equals(T first, T second) where T : IEquatable { - Assert(((IEquatable)first).Equals((IEquatable)second), "Values are not equal."); + Assert(((IEquatable)first).Equals((IEquatable)second), "Assert failed: Values are not equal."); } } } diff --git a/library/Support/LogHelper.cs b/library/Support/LogHelper.cs new file mode 100644 index 00000000..09c3439d --- /dev/null +++ b/library/Support/LogHelper.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; + +namespace PkmnFoundations.Support +{ + public static class LogHelper + { + static LogHelper() + { + Type = EventLogTypes.StandardError; + } + + public static void Write(String message, EventLogEntryType type, int eventID, ushort category, byte[] rawData) + { + switch (Type) + { + case EventLogTypes.StandardOutput: + Console.WriteLine(message); + break; + case EventLogTypes.StandardError: + Console.Error.WriteLine(message); + break; + case EventLogTypes.File: + try + { + using (FileStream fs = File.Open(m_filename, FileMode.Append)) + { + StreamWriter sw = new StreamWriter(fs); + sw.Write("{0}\t{1}\n", DateTime.Now, message); + sw.Close(); + } + } + catch (Exception ex) + { + Console.WriteLine("Can't open logfile at {0}.\nException: {1}\nMessage: {2}", m_filename, ex.Message, message); + } + break; + case EventLogTypes.Windows: + m_event_log.WriteEntry(message, type, eventID, (short)category, rawData); + break; + } + } + + public static void Write(String message, EventLogEntryType type) + { + Write(message, type, 0, 0, null); + } + + public static void Write(String message) + { + Write(message, EventLogEntryType.Information, 0, 0, null); + } + + public static void UseStandardOutput() + { + Type = EventLogTypes.StandardOutput; + m_event_log = null; + } + + public static void UseStandardError() + { + Type = EventLogTypes.StandardError; + m_event_log = null; + } + + public static void UseFile(String filename) + { + if (filename == null) throw new ArgumentNullException("filename"); + Type = EventLogTypes.File; + m_filename = filename; + m_event_log = null; + } + + public static void UseEventLog(EventLog event_log) + { + if (event_log == null) throw new ArgumentNullException("event_log"); + Type = EventLogTypes.Windows; + m_event_log = event_log; + } + + public static EventLogTypes Type + { + get; + private set; + } + + private static String m_filename; + private static EventLog m_event_log; + } + + public enum EventLogTypes + { + StandardOutput, + StandardError, + File, + Windows + } +}