Added new logging backend.

This commit is contained in:
Greg Edwards 2014-07-10 22:34:56 -04:00
parent 61c42047c6
commit a147e976bf
6 changed files with 252 additions and 75 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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; }

View File

@ -66,6 +66,7 @@
<Compile Include="Support\AssertHelper.cs" />
<Compile Include="Support\EncodedString4.cs" />
<Compile Include="Support\EncodedString5.cs" />
<Compile Include="Support\LogHelper.cs" />
<Compile Include="Support\StreamExtender.cs" />
<Compile Include="Support\StringHelper.cs" />
</ItemGroup>

View File

@ -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>(T first, T second) where T : IEquatable<T>
{
Assert(((IEquatable<T>)first).Equals((IEquatable<T>)second), "Values are not equal.");
Assert(((IEquatable<T>)first).Equals((IEquatable<T>)second), "Assert failed: Values are not equal.");
}
}
}

View File

@ -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
}
}