// Log.cs File : v.1.8
// CLog Assembly : v.1.8
// CEventLog Assembly : v.1.3
//
// NOTE: I use the version number of each class will reflect latest changes to the interface.
// Example: If the last interface changed in v.1.4, then the assembly will be v.1.4
// even if the file version is v.1.6.
//
// Free threaded logger for Debug, Info, Errors log writting.
// Also can write to the EventLog.
//
// Versions:
// 1.8 - 03/06/2010 - Added error handling around File.Delete and checking to
// make sure when creating new file, it doesn't already exist.
// Added new interface methods to append Exceptions to the end of your buffer
// automatically.
// 1.7 - 02/07/2010 - Changed a method name from LogShutdown() to StopLogger().
// This is more consistant with StartLogger() method.
// Also modified property "LogLevel" as a defined LOG_TYPE instead of int.
// This way we are not always casting logging levels to int.
// Modified WriteLine params to have LogLevel in front of Buffer.
// This makes it more constistant with the other methods.
// Also modified CEventLog methods to have EventType as the first param so that it too
// will be more consistant with the logger methods.
// Added a control if log file already exists, which could happen if you have multiple
// applications opening log files at the same time.
// 1.6 - 11/01/2009 - Added properties ShowTimeZone and ShowDaylightSavings
// During daylight savings time shift, logs can look a bit strange at first.
// Adding the timezone in front of the time will help this transition.
// 1.5 - 10/17/2009 - Added ConsoleWrite
// This allows the user to write information to console if it's a console application.
// 1.4 - 10/11/2009 - Fixed bug in LogReset()
// Once reset m_arrFileHandles wasn't being updated with the new file handles.
// 1.3 - 03/17/2007 - First Release
//
// Written In:
// Visual Studio C# 2005/2008
// Framework 2.0, 3.0, 3.5/sp1
//
// Example of use:
// using Chizl.AsyncLogger; //CLog
//
// CEventlog.Write("My Tester App", "Log Test Starting");
// CLog.LogLevel = LOG_TYPE.LOG_DEBUG;
// CLog.MaxLogKBSize = 1024; //1024 = 1MB //Minimum Size
// CLog.LogFolder = @"MyLogFolder\SubFolder";
// CLog.ConsoleWrite = false;
// CLog.ApplicationName = "MyAppName";
// CLog.ShowDaylightSavings = true;
// CLog.ShowTimeZone = true;
//
// CLog.LogReset(true); //delete all log files. (TRUE) = Historical
//
// Thread log = new Thread(new ThreadStart(CLog.StartLogger));
// log.Start();
//
// int iSize = 1000000;
// CLog.WriteLine("Starting Test", LOG_TYPE.LOG_DEBUG);
//
// for (int k = 0; k < iSize; k++)
// {
// CLog.TRACE("{0} of {1} Test Writes....", k.ToString(), iSize.ToString());
// Thread.Sleep(0); //required for slower machines..
// }
//
// CLog.WriteLine(LOG_TYPE.LOG_DEBUG, "Testing with Params: {0}, {1}", DateTime.Now, "WoW");
// CLog.WriteLine("Ending Test", LOG_TYPE.LOG_DEBUG);
// CLog.StopLogger();
// CEventlog.Write("My Tester App", "Log Test Ended");
//
// //shutdown
//
// Copyright:
// 2007-2010, Karland International (www.karland.com)
// Written By:
// Gavin Landon, aka Chizl
//
// Permission:
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that the
// above copyright notice appears in all copies and that both that copyright notice
// and this permission notice appear in supporting documentation. Karland International
// makes no representations about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
using System; //String, DateTime, Byte
using System.IO; //File, FileStream
using System.Text; //ASCIIEncoding
using System.Threading; //Thread
using System.Collections; //ArrayList
using System.Diagnostics; //EventLog
using System.Reflection; //Assembly
namespace Chizl.AsyncLogger
{
//Log types..
public enum LOG_TYPE
{
LOG_ERR = 0,
LOG_WARN = 1,
LOG_DEBUG = 2,
} //LOG_TYPE
public class CLog
{
#region private structures and enums
//holds all the transaction information for this socket..
private enum EVENT_ID
{
ID_CHECKMAXSIZE = 100,
ID_CREATEFILEHANDLE = 101,
} //EVENT_ID
private struct FileHandles
{
public FileStream twHandle;
public String szFileName;
public decimal dwFileSize;
public String szRootFileName;
} //FileHandles
private struct TransLog
{
public String szBuffer;
public LOG_TYPE enumFileType;
public String AddedDateTime;
public bool bAddReturn;
public String szFileName;
} //TransLog
#endregion
#region Static Vars
private static bool m_bPathSetup = false;
private static int m_lLogLevel = (int)LOG_TYPE.LOG_WARN; //default log level
private static long m_lMaxKBLogSize = 1024; //default 1MB
private static String m_szRootLogFolder = @"Logs\"; //set root log folder
private static ArrayList m_arrLogQueue = new ArrayList();
private static int m_iPauseLogging = 0;
private static ArrayList m_arrFileHandles = new ArrayList();
private static object m_Locker = new object();
private static AutoResetEvent[] m_autoLogEvents;
private static bool m_bLogsInUse = false;
private static bool m_bConsoleWrite = false;
private static bool m_bTimezone = false;
private static bool m_bDaylightSavings = false;
private static bool m_LogFailure = false;
private static String m_strFilenameFormat = ""; //will be set during LogFolder setup.
private static String m_strApplicationName = ""; //application name, part of the filename.
//##################################################################
//## Making this true, you test this logger, have extra info //##
//## written to logs, like write time and queue count. //##
//## Keep in mind, this will slow the logger down, because //##
//## it's doing string copies to add information to the write. //##
private static bool m_bDebugSpeed = false; //##
//##################################################################
#endregion
#region const data
//constant events..
const int EVENT_MESSAGE = 0;
const int EVENT_SHUTDOWN = 1;
//default log extension..
const String LOG_EXTENSION = ".log";
//base log names..
const String LOG_DEBUG_NAME = "Debug_";
const String LOG_WARN_NAME = "Warning_";
const String LOG_ERR_NAME = "Error_";
//timezone and time formats..
const String LOG_DEFAULT_DST_FORMAT = "z"; //z = -6, zz = -06, zzz = -06:00
const String LOG_DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss:ffff";
#endregion
#region public properties
//property to set application path
static public void StopLogger()
{
if (m_autoLogEvents != null)
if (m_autoLogEvents[EVENT_SHUTDOWN] != null)
m_autoLogEvents[EVENT_SHUTDOWN].Set();
}
static public String ApplicationName
{
get { return m_strApplicationName; }
set { m_strApplicationName = value; }
}
static public bool ConsoleWrite
{
get { return m_bConsoleWrite; }
set { m_bConsoleWrite = value; }
}
static public bool ShowTimeZone
{
get { return m_bTimezone; }
set { m_bTimezone = value; }
}
static public bool ShowDaylightSavings
{
get { return m_bDaylightSavings; }
set { m_bDaylightSavings = value; }
}
//property to set the max Log size in KB. 1024KB = 1MB = Default
static public long MaxLogKBSize
{
get { return m_lMaxKBLogSize; }
set
{
m_lMaxKBLogSize = value;
//if 0, then unlimmited size, but if less than 1MB, this logger writes to
//fast and need more of a file size to maintain the integrety
//of the file name based on millisecond.
if (m_lMaxKBLogSize < 1024 && m_lMaxKBLogSize != 0)
m_lMaxKBLogSize = 1024;
}
}
//pause logging, so files are released and not written to. Everything is still queued
//during this time, but logging to physical disk will not occur until unpause.
static public bool PauseLogger
{
//The reason I'm using integers instead of bool is because if someone from thread1 pauses
//and thread2 also pauses, then I need to make sure thread1 doesn't unpause before thread2
//is ready. Nested pauses can bite ya, if we don't use this correctly.
get
{
if (m_iPauseLogging > 0)
return true;
else
return false;
}
set
{
if (value)
m_iPauseLogging++;
else
m_iPauseLogging--;
}
}
//property to set the max Log size in KB. 1024KB = 1MB = Default
static public LOG_TYPE LogLevel
{
get { return (LOG_TYPE)m_lLogLevel; }
set { m_lLogLevel = (int)value; }
}
//property to set the max Log location. Logs/ = Default
static public String LogFolder
{
get { return m_szRootLogFolder; }
set
{
m_szRootLogFolder = value;
if (m_szRootLogFolder == null)
m_szRootLogFolder = "";
if (!m_szRootLogFolder.EndsWith(@"\") && !String.IsNullOrEmpty(m_szRootLogFolder))
m_szRootLogFolder = m_szRootLogFolder + @"\";
}
}
#endregion
#region public methods
//polymorphic trace / debug
static public String TRACE(String sVar, params object[] args)
{
//Example of use:
// CLog.TRACE("{2}, {0} {1} is {3} years old", "John", "H", "Doe", 20);
sVar = String.Format(sVar, args);
TRACE(sVar);
return sVar;
} //TRACE
//polymorphic trace / debug
static public String TRACE(String sVar)
{
//Example of use:
// CLog.TRACE("Doe, John H is 20 years old");
if (m_bConsoleWrite)
Console.WriteLine(sVar);
WriteLine(LOG_TYPE.LOG_DEBUG, sVar);
return sVar;
} //TRACE
//polymorphic method for logging
static public bool WriteLine(Exception ex, String szBuffer, params object[] args)
{
szBuffer = String.Format(szBuffer, args);
szBuffer += " - TraceStack: " + ex.StackTrace + ", Source: " + ex.Source + ", Message: " + ex.Message;
//write normal
return WriteData(LOG_TYPE.LOG_ERR, szBuffer, true, true, "");
} //WriteLine
//polymorphic method for logging
static public bool WriteLine(Exception ex, String szBuffer)
{
szBuffer += " - TraceStack: " + ex.StackTrace + ", Source: " + ex.Source + ", Message: " + ex.Message;
//write normal
return WriteData(LOG_TYPE.LOG_ERR, szBuffer, true, true, "");
} //WriteLine
//polymorphic method for logging
static public bool WriteLine(Exception ex, String szBuffer, bool bAddDate)
{
szBuffer += " - TraceStack: " + ex.StackTrace + ", Source: " + ex.Source + ", Message: " + ex.Message;
//write normal
return WriteData(LOG_TYPE.LOG_ERR, szBuffer, bAddDate, true, "");
} //WriteLine
//polymorphic method for logging
static public bool WriteLine(LOG_TYPE enumFileType, String szBuffer, params object[] args)
{
//verify log level
if ((LOG_TYPE)m_lLogLevel < enumFileType)
return true;
szBuffer = String.Format(szBuffer, args);
//write normal
return WriteData(enumFileType, szBuffer, true, true, "");
} //WriteLine
//polymorphic method for logging
static public bool WriteLine(LOG_TYPE enumFileType, String szBuffer)
{
//verify log level
if ((LOG_TYPE)m_lLogLevel < enumFileType)
return true;
return WriteData(enumFileType, szBuffer, true, true, "");
} //WriteLine
//polymorphic method for logging
static public bool WriteLine(LOG_TYPE enumFileType, String szBuffer, bool bAddDate)
{
//verify log level
if ((LOG_TYPE)m_lLogLevel < enumFileType)
return true;
return WriteData(enumFileType, szBuffer, bAddDate, true, "");
} //WriteLine
static public void LogReset(bool bDeleteHistorical)
/*
* bDeleteHistorical - delete all files in the folder, not just the ones currently open.
*/
{
String strFunc = "CLog::LogReset";
//setup folder path
if (!SetupPath())
{
StopLogger();
return;
}
//set default file format
SetFileFormat();
//stop logging so files can be deleted
//NOTE: this does not stop the queueing of messages,
//only the physical write to harddrive.
PauseLogger = true;
//finish write, before reset
while (m_bLogsInUse)
Thread.Sleep(100);
FileHandles fh = new FileHandles();
String strDateTime = DateTime.Now.ToString(m_strFilenameFormat);
//close out open handles
for (int i = 0; i < m_arrFileHandles.Count; i++)
{
fh = (FileHandles)m_arrFileHandles[i];
//if file size is zero, meaning nothing was written, then delete it.
fh.twHandle.Close();
Thread.Sleep(0); //cycle cpu
try
{
File.Delete(fh.szFileName);
}
catch (Exception ex)
{
WriteLine(ex, "{0}: Error while deleting file: {1}", strFunc, fh.szFileName);
}
}
Thread.Sleep(0); //cycle cpu
if (bDeleteHistorical)
{
//gather all error files
String[] fileEntries = Directory.GetFiles(m_szRootLogFolder, m_strApplicationName + "_" + LOG_ERR_NAME + "*" + LOG_EXTENSION);
foreach (String fileName in fileEntries)
{
try
{
File.Delete(fileName); //delete all files in the log folder
}
catch (Exception ex)
{
WriteLine(ex, "{0}: Error while deleting file: {1}", strFunc, fh.szFileName);
}
}
Thread.Sleep(0); //cycle cpu
//gather all warning files
fileEntries = Directory.GetFiles(m_szRootLogFolder, m_strApplicationName + "_" + LOG_WARN_NAME + "*" + LOG_EXTENSION);
foreach (String fileName in fileEntries)
{
try
{
File.Delete(fileName); //delete all files in the log folder
}
catch (Exception ex)
{
WriteLine(ex, "{0}: Error while deleting file: {1}", strFunc, fh.szFileName);
}
}
Thread.Sleep(0); //cycle cpu
//gather all debug files
fileEntries = Directory.GetFiles(m_szRootLogFolder, m_strApplicationName + "_" + LOG_DEBUG_NAME + "*" + LOG_EXTENSION);
foreach (String fileName in fileEntries)
{
try
{
File.Delete(fileName); //delete all files in the log folder
}
catch (Exception ex)
{
WriteLine(ex, "{0}: Error while deleting file: {1}", strFunc, fh.szFileName);
}
}
}
//reopen files.
for (int i = 0; i < m_arrFileHandles.Count; i++)
{
fh = (FileHandles)m_arrFileHandles[i];
//if file size is zero, meaning nothing was written, then delete it.
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
while (File.Exists(fh.szFileName))
{
Thread.Sleep(100);
strDateTime = DateTime.Now.ToString(m_strFilenameFormat);
//make new file name, based on new time
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
}
fh.twHandle = new FileStream(fh.szFileName, FileMode.OpenOrCreate);
fh.dwFileSize = fh.twHandle.Length;
m_arrFileHandles[i] = fh;
}
//start logging again
PauseLogger = false;
}
//thread start for logging..
static public void StartLogger()
/*
* All files will have a date as the "Start Date" for each log. Based on this date
* and the modified date, you can tell by looking at the log at a high level, the time
* frame that the log carries.
*/
{
//log startup
FileHandles fh = new FileHandles();
String strQueueCount = ""; //debug speed test
//format path
if (!SetupPath())
return;
//set default file format
SetFileFormat();
//get current date and time, for part of the file name.
String strDateTime = DateTime.Now.ToString(m_strFilenameFormat);
//open all files and their handles into an arraylist
//ERROR Logs
fh.szRootFileName = m_strApplicationName + "_" + LOG_ERR_NAME;
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
//make sure file doesn't already exist
while (File.Exists(fh.szFileName))
{
Thread.Sleep(100);
strDateTime = DateTime.Now.ToString(m_strFilenameFormat);
//make new file name, based on new time
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
}
fh.twHandle = new FileStream(fh.szFileName, FileMode.OpenOrCreate);
fh.dwFileSize = fh.twHandle.Length;
m_arrFileHandles.Add(fh);
//INFORMATION Logs
fh.szRootFileName = m_strApplicationName + "_" + LOG_WARN_NAME;
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
//make sure file doesn't already exist
while (File.Exists(fh.szFileName))
{
Thread.Sleep(100);
strDateTime = DateTime.Now.ToString(m_strFilenameFormat);
//make new file name, based on new time
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
}
fh.twHandle = new FileStream(fh.szFileName, FileMode.OpenOrCreate);
fh.dwFileSize = fh.twHandle.Length;
m_arrFileHandles.Add(fh);
//DEBUG Logs
fh.szRootFileName = m_strApplicationName + "_" + LOG_DEBUG_NAME;
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
//make sure file doesn't already exist
while (File.Exists(fh.szFileName))
{
Thread.Sleep(100);
strDateTime = DateTime.Now.ToString(m_strFilenameFormat);
//make new file name, based on new time
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
}
fh.twHandle = new FileStream(fh.szFileName, FileMode.OpenOrCreate);
fh.dwFileSize = fh.twHandle.Length;
m_arrFileHandles.Add(fh);
//create events
m_autoLogEvents = new AutoResetEvent[]
{
new AutoResetEvent(true), //EVENT_MESSAGE
new AutoResetEvent(false) //EVENT_SHUTDOWN
};
String strDateFormat = GetDateFormat();
WriteFull("Logging thead has started", LOG_TYPE.LOG_DEBUG,
DateTime.Now.ToString(strDateFormat),
true, "");
int iEvent = EVENT_MESSAGE;
//if not EVENT_SHUTDOWN, then stay in the loop
while (iEvent == EVENT_MESSAGE)
{
//wait for an event to be fired, either shutdown or new log message
iEvent = WaitHandle.WaitAny(m_autoLogEvents);
//let everyone know, we are working
m_bLogsInUse = true;
//I removed the switch case here for shutdown or log event being fired.
//I figure there are times that something may be put in the queue at the same time that the event
//for shutdown is fired. Therefore, there's a very small chance to miss a log. Removing
//the switch allows even during shutdowns, the queue is check to see if data is in it and write
//them before shutdown occurs.
//if messages in queue and not paused
while (m_arrLogQueue.Count > 0 && m_iPauseLogging == 0 && !m_LogFailure)
{
//create temp array list
ArrayList arr = new ArrayList();
//lock public array list
lock (m_Locker)
{
//copy to temp
arr = m_arrLogQueue;
//clear public
m_arrLogQueue = new ArrayList();
}
//lets write how many transactions are in the queue, if debug is on.
if (m_bDebugSpeed)
strQueueCount = "(In Queue:" + arr.Count.ToString() + ") ";
else
strQueueCount = "";
int iLoopCount = 0;
//write each message to disk
foreach (TransLog tl in arr)
{
//keep track of looping
iLoopCount++;
//double check something didn't go wrong..
if (tl.AddedDateTime != null)
WriteFull(strQueueCount + tl.szBuffer, tl.enumFileType, tl.AddedDateTime,
tl.bAddReturn, tl.szFileName);
//free up the cpu every once in a while for slower machines.
//However, calling Sleep(0) each call slows down the loop, so
//lets call it if there are more than 100 in the queue at
//one given time.
if (iLoopCount > 100)
{
iLoopCount = 0;
Thread.Sleep(0); //cycle the cpu..
}
//if something failed, shut down logger.
if (m_LogFailure)
{
StopLogger();
break;
}
}
};
//lets flush em all to disk
for (int i = 0; i < m_arrFileHandles.Count; i++)
{
fh = (FileHandles)m_arrFileHandles[i];
try
{
//flush to disk
fh.twHandle.Flush();
}
catch
{
//ignore, we are shutting down..
}
}
m_bLogsInUse = false;
}
strDateFormat = GetDateFormat();
WriteFull("Logging thead has closed", LOG_TYPE.LOG_DEBUG,
DateTime.Now.ToString(strDateFormat),
true, "");
//close out open handles
for (int i = 0; i < m_arrFileHandles.Count; i++)
{
fh = (FileHandles)m_arrFileHandles[i];
CloseFile(fh, fh.twHandle.Length);
}
} //StartLogger
//method used by the polymorphic methods, for logging
static public bool WriteData(LOG_TYPE enumFileType, String szBuffer,
bool bAddDate, bool bAddReturn, String szFileName)
{
//verify log level
if ((LOG_TYPE)m_lLogLevel < enumFileType)
return true;
//failure to write so logging have been turned off.
if (m_LogFailure)
return false;
if (m_bConsoleWrite)
Console.WriteLine(szBuffer);
TransLog tl = new TransLog();
if (bAddDate)
{
String strDateFormat = GetDateFormat();
tl.AddedDateTime = DateTime.Now.ToString(strDateFormat);
}
//set params
tl.bAddReturn = bAddReturn;
tl.enumFileType = enumFileType;
tl.szBuffer = szBuffer;
tl.szFileName = szFileName;
//add to queue, make sure something isn't deleting while adding
lock (m_Locker)
m_arrLogQueue.Add(tl);
//fire event
if (m_autoLogEvents != null)
m_autoLogEvents[EVENT_MESSAGE].Set();
return true;
} //WriteData
#endregion
#region private methods
private static void SetFileFormat()
/*
* Setup default file name formats
*/
{
if (!String.IsNullOrEmpty(m_strFilenameFormat))
return;
m_strFilenameFormat = LOG_DEFAULT_DATE_FORMAT.Replace(" ", "_");
m_strFilenameFormat = m_strFilenameFormat.Replace(":", "");
m_strFilenameFormat = m_strFilenameFormat.Replace("-", "");
}
private static String GetDateFormat()
/*
* Based on configuration, we will format the date with TimeZone and Daylight Savings time flag.
*/
{
//default format
String strDateFormat = LOG_DEFAULT_DATE_FORMAT;
//if show timezone
if (m_bTimezone)
{
//if show daylight savings time
if (m_bDaylightSavings)
{
//check DST
if (DateTime.Now.IsDaylightSavingTime())
strDateFormat = "[" + LOG_DEFAULT_DST_FORMAT + ",1] " + LOG_DEFAULT_DATE_FORMAT;
else
strDateFormat = "[" + LOG_DEFAULT_DST_FORMAT + ",0] " + LOG_DEFAULT_DATE_FORMAT;
}
else
//show only timezone
strDateFormat = "[" + LOG_DEFAULT_DST_FORMAT + "] " + LOG_DEFAULT_DATE_FORMAT;
}
//return value
return strDateFormat;
}
private static void CloseFile(FileHandles fh, long lFileSize)
/*
* Close out file
*/
{
String strFunc = "CLog::CloseFile";
//if file size is zero, meaning nothing was written, then delete it.
fh.twHandle.Close();
if (lFileSize == 0)
{
Thread.Sleep(0); //cycle cpu
try
{
File.Delete(fh.szFileName);
}
catch (Exception ex)
{
WriteLine(ex, "{0}: Error while deleting file: {1}", strFunc, fh.szFileName);
}
}
}
//method used by the polymorphic methods, for logging
private static bool WriteFull(String szBuffer, LOG_TYPE enumFileType,
String szAddDate, bool bAddReturn, String szFileName)
{
//verify log level
if ((LOG_TYPE)m_lLogLevel < enumFileType)
return true;
if (m_LogFailure)
return false;
try
{
//add date/time, ONLY if requested
if (szAddDate != null)
if (!String.IsNullOrEmpty(szAddDate))
szBuffer = szAddDate + ": " + szBuffer;
//add carriage return line feed, ONLY if requested
if (bAddReturn)
szBuffer = szBuffer + "\r\n";
//format path
if (!SetupPath())
StopLogger();
FileHandles fh = (FileHandles)m_arrFileHandles[(int)enumFileType];
//check log size, make sure it's not bigger than max size.
//If max size is 0 then there's no limit
CheckMaxSize(ref fh);
//the handle may have been closed and reopened. Get handle after Check Size.
FileStream tw = fh.twHandle;
ASCIIEncoding encoding = new ASCIIEncoding();
if (m_bDebugSpeed)
szBuffer = "[WriteTime:" + DateTime.Now.ToString("HH:mm:ss:ffff") + "] " + szBuffer;
//update file size
fh.dwFileSize = fh.dwFileSize + szBuffer.Length;
//update array with new info
m_arrFileHandles[(int)enumFileType] = fh;
//encode and write
Byte[] base64Encode = encoding.GetBytes(szBuffer);
tw.Write(base64Encode, 0, base64Encode.Length);
return true;
}
catch
{
m_LogFailure = true;
return false;
}
} //WriteFull
private static void CheckMaxSize(ref FileHandles fh)
{
if (m_LogFailure)
return;
//if set to zero then it's set to unlimited size
if (m_lMaxKBLogSize > 0)
{
//validate the size isn't already larger than max
if (fh.dwFileSize > m_lMaxKBLogSize * 1024) //break m_lMaxKBLogSize down to bytes
{
//close existing file
fh.twHandle.Close();
//create name for backup file, since it's by
//millisecond, there is no way it currently exists, unless someone
//has the max KBLogSize to 1.
String strDateTime = DateTime.Now.ToString(m_strFilenameFormat);
fh.szFileName = m_szRootLogFolder + fh.szRootFileName + strDateTime + LOG_EXTENSION;
try
{
fh.twHandle = new FileStream(fh.szFileName, FileMode.OpenOrCreate);
fh.dwFileSize = fh.twHandle.Length;
}
catch (Exception e)
{
//log it to event log, since we failed on move..
String strAppPath = Assembly.GetExecutingAssembly().Location.ToString();
String strMsg = "Error '" + e.Message + "' in application '" +
strAppPath + "' while opening '" + fh.szFileName + "'";
CEventlog.Write(EventLogEntryType.Error, "Chizl.AsyncLogger", strMsg,
(int)EVENT_ID.ID_CREATEFILEHANDLE);
m_LogFailure = true;
return;
}
}
}
} //CheckMaxSize
private static bool SetupPath()
{
//only need to setup once..
if (m_bPathSetup)
return true;
//set var
m_bPathSetup = true;
if (!m_szRootLogFolder.EndsWith(@"\"))
m_szRootLogFolder += @"\";
try
{
//if directory doesnt exist, create it
if (!Directory.Exists(m_szRootLogFolder))
Directory.CreateDirectory(m_szRootLogFolder);
}
catch
{
return false;
}
return true;
} //SetupPath
#endregion
}
public class CEventlog
{
#region event logging
//method used by the polymorphic methods, for logging to eventlog
static public bool Write(String strSource, String strEvent)
{
return Write(EventLogEntryType.Information, strSource, strEvent, 0);
}
//method used by the polymorphic methods, for logging to eventlog
static public bool Write(EventLogEntryType evtType, String strSource, String strEvent)
{
return Write(evtType, strSource, strEvent, 0);
}
//main method used by the polymorphic methods, for logging to eventlog
static public bool Write(EventLogEntryType evtType, String strSource, String strEvent, int iEventID)
{
//default to application
String strLog = "Application";
try
{
//if the source does not exist, create it
if (!EventLog.SourceExists(strSource))
EventLog.CreateEventSource(strSource, strLog);
//write event
EventLog.WriteEntry(strSource, strEvent, evtType, iEventID);
}
catch
{
return false;
}
return true;
}
#endregion
}
}
|