< Summary - Helper.Tests

Information
Class: Logging.Helper.Logger
Assembly: Logging.Helper
File(s): D:\a\NuGetPackages\NuGetPackages\src\Helper\Logging.Helper\Logger.cs
Tag: 3_8508158812
Line coverage
100%
Covered lines: 215
Uncovered lines: 0
Coverable lines: 215
Total lines: 634
Line coverage: 100%
Branch coverage
100%
Covered branches: 98
Total branches: 98
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_MaxLogFiles()100%11100%
set_MaxLogFiles(...)100%22100%
get_ConfigFile()100%11100%
get_WarnCount()100%11100%
get_ErrorCount()100%11100%
get_FatalCount()100%11100%
get_HasErrors()100%11100%
get_LogImpl()100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
Initialize(...)100%66100%
ToString()100%11100%
CleanString(...)100%22100%
CanLog(...)100%55100%
OnRaiseLog(...)100%11100%
Log(...)100%55100%
Info(...)100%44100%
Info(...)100%66100%
Warn(...)100%44100%
Warn(...)100%66100%
Error(...)100%44100%
Error(...)100%66100%
Error(...)100%22100%
Error(...)100%22100%
Fatal(...)100%44100%
Fatal(...)100%66100%
Fatal(...)100%11100%
Debug(...)100%44100%
Debug(...)100%66100%
SetLogFile(...)100%66100%
GetFileList(...)100%66100%
RemoveLogs(...)100%1212100%

File(s)

D:\a\NuGetPackages\NuGetPackages\src\Helper\Logging.Helper\Logger.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Reflection;
 5using System.Security;
 6using Application.Helper;
 7
 8namespace Logging.Helper
 9{
 10  #region Instructions
 11  /// <summary>Class that provides common logging properties and methods.</summary>
 12
 13  /// <remarks>
 14  /// <p>These are the different types of log message that can be used:</p>
 15  /// <table>
 16  /// <tr><th>Type</th><th>Description</th>
 17  /// </tr><tr>
 18  /// <td>Fatal</td><td>Use to log non-recoverable exceptions that
 19  /// unexpectedly end the process.</td>
 20  /// </tr><tr>
 21  /// <td>Error</td><td>Use to log exceptions that have been handled but caused
 22  /// the processing to stop.</td>
 23  /// </tr><tr>
 24  /// <td>Warning</td><td>Use to indicate that the process faced a potential problem
 25  /// but can continue.</td>
 26  /// </tr><tr>
 27  /// <td>Information</td><td>These are purely informational messages; they <i>should not</i>
 28  /// be used to indicate a fault or error state.</td>
 29  /// </tr><tr>
 30  /// <td>Debug</td><td>Used to indicate that the logged message can be used for
 31  /// debugging purposes to help find the solution to tricky bugs.</td>
 32  /// </tr>
 33  /// </table>
 34  /// </remarks>
 35
 36  /// <example>
 37  /// In the program that requires logging functionality:
 38  /// <code lang="C#">
 39  /// using Logging.Helper;
 40  /// public class Program
 41  /// {
 42  ///   /// <summary>Public static Logger.</summary>
 43  ///   // Logging configuration in the application settings (App.config)...
 44  ///   public static readonly Logger Logging = new Logger( typeof( Program ) );
 45  ///
 46  ///   // ... OR shared logging configuration filename specified in the application settings...
 47  ///   public static readonly Logger Logging = new Logger( Properties.Settings.Default.LogConfig );
 48  ///
 49  ///   // ... OR shared logging configuration filename hard-coded in each program...
 50  ///   public static readonly Logger Logging = new Logger( MethodBase.GetCurrentMethod().DeclaringType, "Sample.log4net
 51  ///
 52  ///   static void Main( string[] args )
 53  ///   {
 54  ///     try
 55  ///     {
 56  ///       Logging.Log( "Test specified message type.", LogSeverity.Warning );
 57  ///     }
 58  ///     catch( Exception ex )
 59  ///     {
 60  ///       // Handle any unexpected exceptions
 61  ///       Logging.Fatal( ex.ToString() );
 62  ///     }
 63  ///     finally
 64  ///     {
 65  ///       // Set the program exit code based on whether any errors have been logged
 66  ///       Environment.ExitCode = Logging.HasErrors ? 1 : 0;
 67  ///     }
 68  ///     Environment.Exit( Environment.ExitCode );
 69  ///   }
 70  /// }
 71  /// </code>
 72  /// <br/>To allow a processing class to log using the logger created in the program it must inherit
 73  /// from the Logging.Helper.LoggerEvent class and have the event handler set after it has been instantiated:
 74  /// <code lang="C#">
 75  /// using Logging.Helper;
 76  /// public class ProcessingClass : LoggerEvent
 77  /// {
 78  ///   internal int DoProcessing()
 79  ///   {
 80  ///     var retValue = 0; // Assume normal completion
 81  ///     try
 82  ///     {
 83  ///       // This method is inherited from the LoggerEvent class
 84  ///       RaiseLogEvent( "Information message about the processing..." );
 85  ///     }
 86  ///     catch( Exception ex )
 87  ///     {
 88  ///       RaiseLogEvent( ex.ToString(), LogSeverity.Fatal );
 89  ///       retValue = 1; // Abnormal completion
 90  ///     }
 91  ///     return retValue;
 92  ///   }
 93  /// }
 94  ///
 95  /// using Logging.Helper;
 96  /// public class Program
 97  /// {
 98  ///   /// <summary>Public static Logger.</summary>
 99  ///   public static readonly Logger Logging = new Logger( typeof( Program ) );
 100  ///
 101  ///   static void Main( string[] args )
 102  ///   {
 103  ///     try
 104  ///     {
 105  ///       // Create an object from a class that inherits LoggerEvent
 106  ///       var logicClass = new ProcessingClass();
 107  ///       logicClass.RaiseLogHandler += Logging.OnRaiseLog;
 108  ///
 109  ///       // Do Processing and set the Exit code
 110  ///       logicClass.DoProcessing();
 111  ///     }
 112  ///     catch( Exception ex )
 113  ///     {
 114  ///       // Handle any unexpected exceptions
 115  ///       Logging.Fatal( ex.ToString() );
 116  ///     }
 117  ///     finally
 118  ///     {
 119  ///       // Set the program exit code based on whether any errors have been logged
 120  ///       Environment.ExitCode = Logging.HasErrors ? 1 : 0;
 121  ///     }
 122  ///     Environment.Exit( Environment.ExitCode );
 123  ///   }
 124  /// }
 125  /// </code>
 126  /// </example>
 127  #endregion
 128  public sealed class Logger
 129  {
 130    #region Properties and Constants
 131
 132    /// <summary>Gets or sets the maximum number of log files to keep.</summary>
 133    public int MaxLogFiles
 134    {
 1135      get => LogImpl.MaxLogFiles;
 136      set
 16137      {
 16138        if( null != LogImpl )
 16139        {
 16140          LogImpl.MaxLogFiles = value;
 16141        }
 16142      }
 143    }
 144
 145    /// <summary>Gets the logging configuration file name.</summary>
 157146    public string ConfigFile { get; private set; } = string.Empty;
 147
 148    /// <summary>Gets the count of warning messages logged.</summary>
 85149    public int WarnCount { get; private set; }
 150
 151    /// <summary>Gets the count of error messages logged.</summary>
 149152    public int ErrorCount { get; private set; }
 153
 154    /// <summary>Gets the count of fatal messages logged.</summary>
 80155    public int FatalCount { get; private set; }
 156
 157    /// <summary>Indicates whether errors exists.</summary>
 1158    public bool HasErrors => ( ErrorCount + FatalCount ) > 0;
 159
 160    /// <summary>Gets or sets the logger interface.</summary>
 370161    private ILog LogImpl { get; set; }
 162
 163    /// <summary>Log file extension (suffix) including the period.</summary>
 164    public const string cExtension = ".log";
 165
 166    #endregion
 167
 168    #region Constructors and Initialization
 169
 170    /// <summary>
 171    /// Initializes a new instance of the Logger class using an optional configuration file name.
 172    /// </summary>
 173    /// <param name="configFile">Logging configuration file name to use.</param>
 174    /// <exception cref="NLog.NLogConfigurationException">Thrown if the NLog configuration is invalid.</exception>
 175    /// <exception cref="TargetException">Thrown when an attempt is made to invoke an invalid target.</exception>
 41176    public Logger( string configFile = "" )
 41177    {
 41178      Initialize( Assembly.GetCallingAssembly(), MethodBase.GetCurrentMethod().DeclaringType, configFile );
 41179    }
 180
 181    /// <summary>
 182    /// Initializes a new instance of the Logger class using a logger type and configuration file name.
 183    /// </summary>
 184    /// <param name="loggerType">Type to be used as the name of the logger to retrieve.</param>
 185    /// <param name="configFile">Logging configuration file name to use.</param>
 186    /// <exception cref="NLog.NLogConfigurationException">Thrown if the NLog configuration is invalid.</exception>
 2187    public Logger( Type loggerType, string configFile = "" )
 2188    {
 2189      Initialize( Assembly.GetCallingAssembly(), loggerType, configFile );
 2190    }
 191
 192    private void Initialize( Assembly assembly, Type loggerType, string configFile )
 43193    {
 194      try
 43195      {
 43196        if( configFile.Length > 0 )
 24197        {
 198          // Set the configuration file name
 24199          ConfigFile = Path.GetFullPath( configFile );
 200
 201          // Check if the configuration file exists
 26202          if( !File.Exists( ConfigFile ) ) { ConfigFile = string.Empty; }
 23203        }
 204        else
 19205        {
 206          // If no configuration file supplied check if an app.config file exists
 19207          configFile = assembly.Location + ".config";
 76208          if( File.Exists( configFile ) ) { ConfigFile = configFile; }
 19209        }
 42210      }
 4211      catch { ConfigFile = string.Empty; }
 212
 213      // Initialize the logging implementation
 214      //LogImpl = new ImplBasicLog();
 215
 216      // Requires an assembly reference for NLog.dll
 43217      LogImpl = new ImplNLog( loggerType, ConfigFile );
 218
 219      // Requires an assembly reference for log4net.dll
 220      //LogImpl = new ImplLog4Net( assembly, loggerType, ConfigFile );
 43221    }
 222
 223    /// <summary>Converts the value of this instance to a string.</summary>
 224    /// <returns>Instance value.</returns>
 225    public override string ToString()
 1226    {
 1227      return LogImpl.ToString();
 1228    }
 229
 230    #endregion
 231
 232    #region Private Methods
 233
 234    /// <summary>Cleans a string value.</summary>
 235    /// <param name="strToClean">String to clean.</param>
 236    /// <returns>Trimmed string.</returns>
 237    internal static string CleanString( string strToClean )
 71238    {
 71239      return string.IsNullOrWhiteSpace( strToClean ) ? string.Empty : strToClean.Trim();
 71240    }
 241
 242    private bool CanLog( LogSeverity severity )
 262243    {
 262244      switch( severity )
 245      {
 246        case LogSeverity.Error:
 74247          return LogImpl.IsErrorEnabled;
 248        case LogSeverity.Fatal:
 39249          return LogImpl.IsFatalEnabled;
 250        case LogSeverity.Information:
 54251          return LogImpl.IsInfoEnabled;
 252        case LogSeverity.Warning:
 42253          return LogImpl.IsWarnEnabled;
 254        default:
 53255          return LogImpl.IsDebugEnabled;
 256      }
 262257    }
 258
 259    #endregion
 260
 261    #region Log Event Handler Methods
 262
 263    /// <summary>Event handler for the logging process.</summary>
 264    /// <param name="sender">Sender object triggering the event.</param>
 265    /// <param name="e">Instance of LogEventArgs class with addition details about the logging event.</param>
 266    public void OnRaiseLog( object sender, LoggerEventArgs e )
 1267    {
 1268      Log( e.Message, e.Severity );
 1269    }
 270
 271    /// <summary>Log a message.</summary>
 272    /// <param name="msg">Message text.</param>
 273    /// <param name="severity">Identifies the type of trace event.</param>
 274    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 275    /// <exception cref="NotImplementedException"></exception>
 276    public bool Log( string msg, LogSeverity severity = LogSeverity.Information )
 6277    {
 278      bool retValue;
 6279      switch( severity )
 280      {
 281        case LogSeverity.Fatal:
 2282          retValue = Fatal( msg );
 2283          break;
 284        case LogSeverity.Error:
 1285          retValue = Error( msg );
 1286          break;
 287        case LogSeverity.Warning:
 1288          retValue = Warn( msg );
 1289          break;
 290        case LogSeverity.Information:
 1291          retValue = Info( msg );
 1292          break;
 293        default:
 1294          retValue = Debug( msg );
 1295          break;
 296      }
 297
 6298      return retValue;
 6299    }
 300
 301    #endregion
 302
 303    #region Message Logging
 304
 305    #region Logging Information
 306
 307    /// <summary>Logs an informational message.</summary>
 308    /// <param name="message">Message text to log.</param>
 309    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 310    public bool Info( string message )
 23311    {
 40312      if( !CanLog( LogSeverity.Information ) ) return false;
 313
 6314      message = CleanString( message );
 11315      if( message.Length <= 0 ) return false;
 316
 1317      LogImpl.Info( message );
 1318      return true;
 23319    }
 320
 321    /// <summary>Logs an informational message with arguments.</summary>
 322    /// <param name="message">Composite format message string to log.</param>
 323    /// <param name="args">An object array that contains zero or more objects to format.</param>
 324    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 325    public bool Info( string message, params object[] args )
 31326    {
 47327      if( !CanLog( LogSeverity.Information ) ) return false;
 328
 15329      message = CleanString( message );
 25330      if( message.Length <= 0 || null == args ) return false;
 331
 5332      LogImpl.Info( string.Format( message, args ) );
 5333      return true;
 31334    }
 335
 336    #endregion
 337
 338    #region Logging Warning
 339
 340    /// <summary>Logs a warning message.</summary>
 341    /// <param name="message">Message text to log.</param>
 342    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 343    public bool Warn( string message )
 23344    {
 23345      WarnCount++;
 39346      if( !CanLog( LogSeverity.Warning ) ) return false;
 347
 7348      message = CleanString( message );
 8349      if( message.Length <= 0 ) return false;
 350
 6351      LogImpl.Warn( message );
 6352      return true;
 23353    }
 354
 355    /// <summary>Logs a warning message with arguments.</summary>
 356    /// <param name="message">Composite format message string to log.</param>
 357    /// <param name="args">An object array that contains zero or more objects to format.</param>
 358    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 359    public bool Warn( string message, params object[] args )
 19360    {
 19361      WarnCount++;
 35362      if( !CanLog( LogSeverity.Warning ) ) return false;
 363
 3364      message = CleanString( message );
 5365      if( message.Length <= 0 || null == args ) return false;
 366
 1367      LogImpl.Warn( string.Format( message, args ) );
 1368      return true;
 19369    }
 370
 371    #endregion
 372
 373    #region Logging Error
 374
 375    /// <summary>Logs an error message.</summary>
 376    /// <param name="message">Message text to log.</param>
 377    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 378    public bool Error( string message )
 19379    {
 19380      ErrorCount++;
 35381      if( !CanLog( LogSeverity.Error ) ) return false;
 382
 3383      message = CleanString( message );
 4384      if( message.Length <= 0 ) return false;
 385
 2386      LogImpl.Error( message );
 2387      return true;
 19388    }
 389
 390    /// <summary>Logs an error message with arguments.</summary>
 391    /// <param name="message">Composite format message string to log.</param>
 392    /// <param name="args">An object array that contains zero or more objects to format.</param>
 393    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 394    public bool Error( string message, params object[] args )
 19395    {
 19396      ErrorCount++;
 35397      if( !CanLog( LogSeverity.Error ) ) return false;
 398
 3399      message = CleanString( message );
 5400      if( message.Length <= 0 || null == args ) return false;
 401
 1402      LogImpl.Error( string.Format( message, args ) );
 1403      return true;
 19404    }
 405
 406    /// <summary>Logs an error message with an exception.</summary>
 407    /// <param name="message">Message text to log.</param>
 408    /// <param name="exception">Exception to log.</param>
 409    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 410    public bool Error( string message, Exception exception )
 18411    {
 18412      ErrorCount++;
 34413      if( !CanLog( LogSeverity.Error ) ) return false;
 2414      message = CleanString( message );
 415
 2416      LogImpl.Error( message, exception );
 2417      return true;
 18418    }
 419
 420    /// <summary>Logs an exception.</summary>
 421    /// <param name="exception">Exception to log.</param>
 422    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 423    public bool Error( Exception exception )
 18424    {
 18425      ErrorCount++;
 34426      if( !CanLog( LogSeverity.Error ) ) return false;
 427
 2428      LogImpl.Error( exception );
 2429      return true;
 18430    }
 431
 432    #endregion
 433
 434    #region Logging Fatal
 435
 436    /// <summary>Logs a fatal error message.</summary>
 437    /// <param name="message">Message text to log.</param>
 438    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 439    public bool Fatal( string message )
 20440    {
 20441      FatalCount++;
 36442      if( !CanLog( LogSeverity.Fatal ) ) return false;
 443
 4444      message = CleanString( message );
 5445      if( message.Length <= 0 ) return false;
 446
 3447      LogImpl.Fatal( message );
 3448      return true;
 20449    }
 450
 451    /// <summary>Logs a fatal error message with arguments.</summary>
 452    /// <param name="message">Composite format message string to log.</param>
 453    /// <param name="args">An object array that contains zero or more objects to format.</param>
 454    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 455    public bool Fatal( string message, params object[] args )
 19456    {
 19457      FatalCount++;
 35458      if( !CanLog( LogSeverity.Fatal ) ) return false;
 459
 3460      message = CleanString( message );
 5461      if( message.Length <= 0 || null == args ) return false;
 462
 1463      LogImpl.Fatal( string.Format( message, args ) );
 1464      return true;
 19465    }
 466
 467    /// <summary>Logs a fatal exception.</summary>
 468    /// <param name="exception">Exception to log.</param>
 469    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 470    public bool Fatal( Exception exception )
 1471    {
 1472      return Log( GenericException.FormatException( exception ), LogSeverity.Fatal );
 1473    }
 474
 475    #endregion
 476
 477    #region Logging Debug
 478
 479    /// <summary>Logs a debugging message.</summary>
 480    /// <param name="message">Message text to log.</param>
 481    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 482    public bool Debug( string message )
 22483    {
 38484      if( !CanLog( LogSeverity.Debug ) ) return false;
 485
 6486      message = CleanString( message );
 11487      if( message.Length <= 0 ) return false;
 488
 1489      LogImpl.Debug( message );
 1490      return true;
 22491    }
 492
 493    /// <summary>Logs a debugging message with arguments.</summary>
 494    /// <param name="message">Composite format message string to log.</param>
 495    /// <param name="args">An object array that contains zero or more objects to format.</param>
 496    /// <returns><see langword="true"/> if the message was logged, otherwise <see langword="false"/> is returned.</retur
 497    public bool Debug( string message, params object[] args )
 31498    {
 47499      if( !CanLog( LogSeverity.Debug ) ) return false;
 500
 15501      message = CleanString( message );
 25502      if( message.Length <= 0 || null == args ) return false;
 503
 5504      LogImpl.Debug( string.Format( message.Trim(), args ) );
 5505      return true;
 31506    }
 507
 508    #endregion
 509
 510    #endregion
 511
 512    #region Log File Methods
 513
 514    /// <summary>Sets the location of the log file and optionally, the log file name.</summary>
 515    /// <param name="logDirectory">Location of the log file.</param>
 516    /// <param name="logFileName">Name of the log file.</param>
 517    /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid.</excepti
 518    /// <exception cref="IOException">Thrown when an I/O error occurs.</exception>
 519    /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported, or when there
 520    /// is an attempt to read, seek, or write to a stream that does not support the invoked functionality.</exception>
 521    /// <exception cref="SecurityException">Thrown when a security error is detected.</exception>
 522    public void SetLogFile( string logDirectory, string logFileName = "" )
 2523    {
 524      // Check the parameter values
 2525      logDirectory = CleanString( logDirectory );
 2526      logFileName = CleanString( logFileName );
 527
 528      // Check that the directory path is valid
 2529      _ = new DirectoryInfo( logDirectory );
 530
 531      // Process the directory first as it could contain the file name as well
 1532      if( logDirectory.Length > 0 )
 1533      {
 1534        logDirectory = Path.GetFullPath( logDirectory );
 535
 536        // If a file extension is found then a file name is also present
 1537        string ext = Path.GetExtension( logDirectory );
 1538        if( ext.Length > 0 & logFileName.Length == 0 )
 1539        {
 1540          logFileName = Path.GetFileName( logDirectory );
 1541          logDirectory = Path.GetDirectoryName( logDirectory );
 1542        }
 1543      }
 544
 1545      if( logFileName.Length > 0 )
 1546      {
 547        // Check that the log file name is valid
 1548        logFileName = Path.GetFileName( logFileName );
 1549      }
 550
 551      // Set the implementation log file location and name
 1552      LogImpl.SetLogFile( logDirectory, logFileName );
 1553    }
 554
 555    private static List<FileInfo> GetFileList( DirectoryInfo dir, string logNameMask )
 3556    {
 3557      List<FileInfo> rtn = new List<FileInfo>();
 558
 559      // Check if the directory contains any log files
 3560      FileInfo[] logFiles = dir.GetFiles( logNameMask );
 3561      if( logFiles.Length == 0 )
 1562      {
 1563        return rtn;
 564      }
 565
 566      // Create list of log files that are not read-only
 12567      foreach( var fi in logFiles )
 3568      {
 569        // Exclude read-only files from deletion
 3570        if( !fi.Attributes.HasFlag( FileAttributes.ReadOnly ) )
 3571        {
 3572          rtn.Add( fi );
 3573        }
 3574      }
 575
 2576      return rtn;
 3577    }
 578
 579    /// <summary>Removes the oldest non-read-only log files in a directory.</summary>
 580    /// <param name="directory">Directory containing the log files.</param>
 581    /// <param name="logNameMask">Search pattern in the form [LogFile]*.[ext] of the log file names.</param>
 582    /// <param name="maxFiles">Maximum number of log files to keep.</param>
 583    /// <returns><see langword="true"/> if any log files have been removed, otherwise <see langword="false"/> is returne
 584    /// <example>
 585    /// In a method that needs to remove old log files:
 586    /// <code lang="C#">
 587    /// var directory = @"C:\Temp\Logs" );
 588    /// const string mask = "LogfileName*.log";
 589    /// const int maxLogFiles = 50;
 590    /// logging.RemoveLogs( directory, mask, maxLogFiles );
 591    /// </code>
 592    /// </example>
 593    /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid.</excepti
 594    /// <exception cref="IOException">Thrown when an I/O error occurs.</exception>
 595    /// <exception cref="SecurityException">Thrown when a security error is detected.</exception>
 596    /// <exception cref="UnauthorizedAccessException">Thrown when the operating system denies access because of an I/O e
 597    public bool RemoveLogs( string directory, string logNameMask, int maxFiles = 0 )
 8598    {
 8599      DirectoryInfo dir = new DirectoryInfo( directory );
 600
 601      // Check the required parameters have been passed
 7602      if( !dir.Exists || string.IsNullOrEmpty( logNameMask ) || maxFiles <= 0 )
 4603      {
 4604        return false;
 605      }
 606
 3607      List<FileInfo> list = GetFileList( dir, logNameMask );
 5608      if( list.Count == 0 ) { return false; }
 609
 610      // Check that file count is greater than maximum number
 2611      if( list.Count <= maxFiles )
 1612      {
 1613        return false;
 614      }
 615
 616      // Sort in ascending sequence by last written date/time
 2617      list.Sort( ( x, y ) => x.LastWriteTime.CompareTo( y.LastWriteTime ) );
 618
 619      // Delete old log files
 1620      maxFiles = list.Count - maxFiles;
 1621      int count = 0;
 4622      for( var i = 0; i < maxFiles; i++ )
 1623      {
 1624        FileInfo fi = list[i];
 1625        fi.Delete();
 1626        count++;
 1627      }
 628
 1629      return count > 0;
 7630    }
 631
 632    #endregion
 633  }
 634}