diff --git a/src/ColumnizerLib.UnitTests/ColumnTests.cs b/src/ColumnizerLib.UnitTests/ColumnTests.cs index 649b132a..98830505 100644 --- a/src/ColumnizerLib.UnitTests/ColumnTests.cs +++ b/src/ColumnizerLib.UnitTests/ColumnTests.cs @@ -1,5 +1,7 @@ -using LogExpert; +using LogExpert; + using NUnit.Framework; + using System; using System.Text; @@ -9,44 +11,30 @@ namespace ColumnizerLib.UnitTests; public class ColumnTests { [Test] - public void Column_LineCutOf() + public void Column_LineCutOff () { - Column column = new(); - - StringBuilder builder = new(); + var expectedFullValue = new StringBuilder().Append('6', 4675).Append("1234").ToString(); + var expectedDisplayValue = expectedFullValue[..4675] + "..."; // Using substring shorthand - for (var i = 0; i < 4675; i++) + Column column = new() { - builder.Append("6"); - } - - var expected = builder + "..."; - builder.Append("1234"); - - column.FullValue = builder.ToString(); + FullValue = expectedFullValue + }; - Assert.That(column.DisplayValue, Is.EqualTo(expected)); - Assert.That(column.FullValue, Is.EqualTo(builder.ToString())); + Assert.That(column.DisplayValue, Is.EqualTo(expectedDisplayValue)); + Assert.That(column.FullValue, Is.EqualTo(expectedFullValue)); } [Test] - public void Column_NoLineCutOf() + public void Column_NoLineCutOff () { - Column column = new(); - - StringBuilder builder = new(); - - for (var i = 0; i < 4675; i++) + var expected = new StringBuilder().Append('6', 4675).ToString(); + Column column = new() { - builder.Append("6"); - } - - var expected = builder.ToString(); - - column.FullValue = expected; + FullValue = expected + }; - Assert.That(column.DisplayValue, Is.EqualTo(expected)); - Assert.That(column.FullValue, Is.EqualTo(expected)); + Assert.That(column.DisplayValue, Is.EqualTo(column.FullValue)); } [Test] diff --git a/src/ColumnizerLib/Column.cs b/src/ColumnizerLib/Column.cs index 7cabf065..87bfdd69 100644 --- a/src/ColumnizerLib/Column.cs +++ b/src/ColumnizerLib/Column.cs @@ -10,7 +10,15 @@ public class Column : IColumn private const int MAXLENGTH = 4678 - 3; private const string REPLACEMENT = "..."; - private static readonly IEnumerable> _replacements; + private static readonly List> _replacements = [ + //replace tab with 3 spaces, from old coding. Needed??? + input => input.Replace("\t", " ", StringComparison.Ordinal), + + //shorten string if it exceeds maxLength + input => input.Length > MAXLENGTH + ? string.Concat(input.AsSpan(0, MAXLENGTH), REPLACEMENT) + : input + ]; private string _fullValue; @@ -20,32 +28,19 @@ public class Column : IColumn static Column () { - var replacements = new List>( - [ - //replace tab with 3 spaces, from old coding. Needed??? - input => input.Replace("\t", " ", StringComparison.Ordinal), - - //shorten string if it exceeds maxLength - input => input.Length > MAXLENGTH - ? string.Concat(input.AsSpan(0, MAXLENGTH), REPLACEMENT) - : input - ]); - if (Environment.Version >= Version.Parse("6.2")) { //Win8 or newer support full UTF8 chars with the preinstalled fonts. //Replace null char with UTF8 Symbol U+2400 (␀) - replacements.Add(input => input.Replace("\0", "␀", StringComparison.Ordinal)); + _replacements.Add(input => input.Replace("\0", "␀", StringComparison.Ordinal)); } else { //Everything below Win8 the installed fonts seems to not to support reliabel //Replace null char with space - replacements.Add(input => input.Replace("\0", " ", StringComparison.Ordinal)); + _replacements.Add(input => input.Replace("\0", " ", StringComparison.Ordinal)); } - _replacements = replacements; - EmptyColumn = new Column { FullValue = string.Empty }; } @@ -77,7 +72,7 @@ public string FullValue public string DisplayValue { get; private set; } - string ITextValue.Text => DisplayValue; + public string Text => DisplayValue; #endregion diff --git a/src/ColumnizerLib/Extensions/LogLineExtensions.cs b/src/ColumnizerLib/Extensions/LogLineExtensions.cs index 659ff75e..de081a34 100644 --- a/src/ColumnizerLib/Extensions/LogLineExtensions.cs +++ b/src/ColumnizerLib/Extensions/LogLineExtensions.cs @@ -1,9 +1,11 @@ namespace LogExpert.Extensions; +//TODO: Move this to LogExpert.UI, change to internal and fix tests public static class LogLineExtensions { - public static string ToClipBoardText(this ILogLine logLine) + //TOOD: check if the callers are checking for null before calling + public static string ToClipBoardText (this ILogLine logLine) { - return "\t" + (logLine.LineNumber + 1).ToString() + "\t" + logLine.FullLine; + return logLine == null ? string.Empty : $"\t{logLine.LineNumber + 1}\t{logLine.FullLine}"; } } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogExpertLogger.cs b/src/ColumnizerLib/ILogExpertLogger.cs index cb9405d2..cfbbd884 100644 --- a/src/ColumnizerLib/ILogExpertLogger.cs +++ b/src/ColumnizerLib/ILogExpertLogger.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Globalization; using System.Text; namespace LogExpert; @@ -17,6 +18,7 @@ public interface ILogExpertLogger /// /// A message to be logged. void Info(string msg); + void Info (IFormatProvider formatProvider, string msg); /// /// Logs a message on DEBUG level to LogExpert#s log file. The logfile is only active in debug builds. diff --git a/src/ColumnizerLib/IXmlLogConfiguration.cs b/src/ColumnizerLib/IXmlLogConfiguration.cs index c48d7535..b65422ed 100644 --- a/src/ColumnizerLib/IXmlLogConfiguration.cs +++ b/src/ColumnizerLib/IXmlLogConfiguration.cs @@ -30,7 +30,7 @@ public interface IXmlLogConfiguration /// Example: {"log4j", "http://jakarta.apache.org/log4j"} /// /// - string[] Namespace { get; } + string[] GetNamespaceDeclaration (); #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/LineEntry.cs b/src/ColumnizerLib/LineEntry.cs index 3869767c..e59c1791 100644 --- a/src/ColumnizerLib/LineEntry.cs +++ b/src/ColumnizerLib/LineEntry.cs @@ -1,3 +1,5 @@ +using System; + namespace LogExpert; /// @@ -5,7 +7,7 @@ namespace LogExpert; /// This struct is used by . /// /// -public struct LineEntry +public struct LineEntry : IEquatable { /// /// The content of the line. @@ -16,4 +18,22 @@ public struct LineEntry /// The line number. See for an explanation of the line number. /// public int LineNum { get; set; } + + public override bool Equals(object obj) + { + return obj is LineEntry other && Equals(other); + } + + public readonly bool Equals(LineEntry other) + { + return LineNum == other.LineNum && Equals(LogLine, other.LogLine); + } + + public override readonly int GetHashCode() + { + return HashCode.Combine(LineNum, LogLine); + } + + public static bool operator == (LineEntry left, LineEntry right) => left.Equals(right); + public static bool operator != (LineEntry left, LineEntry right) => !left.Equals(right); } \ No newline at end of file diff --git a/src/GlassfishColumnizer/XmlConfig.cs b/src/GlassfishColumnizer/XmlConfig.cs index 0d81e05a..925be273 100644 --- a/src/GlassfishColumnizer/XmlConfig.cs +++ b/src/GlassfishColumnizer/XmlConfig.cs @@ -1,4 +1,4 @@ -using LogExpert; +using LogExpert; namespace GlassfishColumnizer; @@ -12,7 +12,7 @@ internal class XmlConfig : IXmlLogConfiguration public string Stylesheet { get; } - public string[] Namespace => null; + public string[] GetNamespaceDeclaration () => null; #endregion } \ No newline at end of file diff --git a/src/Log4jXmlColumnizer/XmlConfig.cs b/src/Log4jXmlColumnizer/XmlConfig.cs index 24620b82..ed852699 100644 --- a/src/Log4jXmlColumnizer/XmlConfig.cs +++ b/src/Log4jXmlColumnizer/XmlConfig.cs @@ -1,4 +1,4 @@ -using LogExpert; +using LogExpert; namespace Log4jXmlColumnizer; @@ -26,7 +26,7 @@ internal class XmlConfig : IXmlLogConfiguration "" + ""; - public string[] Namespace => ["log4j", "http://jakarta.apache.org/log4j"]; + public string[] GetNamespaceDeclaration () => ["log4j", "http://jakarta.apache.org/log4j"]; #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Bookmark/BookmarkDataProvider.cs b/src/LogExpert.Core/Classes/Bookmark/BookmarkDataProvider.cs index bf098ffc..e8b7373c 100644 --- a/src/LogExpert.Core/Classes/Bookmark/BookmarkDataProvider.cs +++ b/src/LogExpert.Core/Classes/Bookmark/BookmarkDataProvider.cs @@ -1,3 +1,5 @@ +using System.Globalization; + using LogExpert.Core.Entities; using LogExpert.Core.Interface; @@ -27,21 +29,11 @@ public BookmarkDataProvider (SortedList bookmarkList) #endregion - #region Delegates - - public delegate void AllBookmarksRemovedEventHandler (object sender, EventArgs e); - - public delegate void BookmarkAddedEventHandler (object sender, EventArgs e); - - public delegate void BookmarkRemovedEventHandler (object sender, EventArgs e); - - #endregion - #region Events - public event BookmarkAddedEventHandler BookmarkAdded; - public event BookmarkRemovedEventHandler BookmarkRemoved; - public event AllBookmarksRemovedEventHandler AllBookmarksRemoved; + public event EventHandler BookmarkAdded; + public event EventHandler BookmarkRemoved; + public event EventHandler AllBookmarksRemoved; #endregion @@ -141,8 +133,11 @@ public void RemoveBookmarkForLine (int lineNum) OnBookmarkRemoved(); } - public void RemoveBookmarksForLines (List lineNumList) + //TOOD: check if the callers are checking for null before calling + public void RemoveBookmarksForLines (IEnumerable lineNumList) { + ArgumentNullException.ThrowIfNull(lineNumList, nameof(lineNumList)); + foreach (var lineNum in lineNumList) { _ = BookmarkList.Remove(lineNum); @@ -152,16 +147,18 @@ public void RemoveBookmarksForLines (List lineNumList) OnBookmarkRemoved(); } - + //TOOD: check if the callers are checking for null before calling public void AddBookmark (Entities.Bookmark bookmark) { + ArgumentNullException.ThrowIfNull(bookmark, nameof(bookmark)); + BookmarkList.Add(bookmark.LineNum, bookmark); OnBookmarkAdded(); } public void ClearAllBookmarks () { - _logger.Debug("Removing all bookmarks"); + _logger.Debug(CultureInfo.InvariantCulture, "Removing all bookmarks"); BookmarkList.Clear(); OnAllBookmarksRemoved(); } diff --git a/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs b/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs index 227fe06e..22c859dc 100644 --- a/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs +++ b/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs @@ -4,7 +4,7 @@ namespace LogExpert.Core.Classes.Columnizer; -public class ColumnizerPicker +public static class ColumnizerPicker { public static ILogLineColumnizer FindColumnizerByName (string name, IList list) { @@ -86,6 +86,7 @@ public static ILogLineColumnizer FindBetterColumnizer (string fileName, return newColumnizer; } + //TOOD: check if the callers are checking for null before calling /// /// This method will search all registered columnizer and return one according to the priority that returned /// by the each columnizer. @@ -93,13 +94,15 @@ public static ILogLineColumnizer FindBetterColumnizer (string fileName, /// /// /// - public static ILogLineColumnizer FindColumnizer (string fileName, IAutoLogLineColumnizerCallback logFileReader, IList list) + public static ILogLineColumnizer FindColumnizer (string fileName, IAutoLogLineColumnizerCallback logFileReader, IList registeredColumnizer) { if (string.IsNullOrEmpty(fileName)) { return new DefaultLogfileColumnizer(); } + ArgumentNullException.ThrowIfNull(registeredColumnizer, nameof(registeredColumnizer)); + List loglines = []; if (logFileReader != null) @@ -120,9 +123,7 @@ public static ILogLineColumnizer FindColumnizer (string fileName, IAutoLogLineCo ]; } - var registeredColumnizer = list; - - List> priorityListOfColumnizers = []; + List<(Priority priority, ILogLineColumnizer columnizer)> priorityListOfColumnizers = []; foreach (ILogLineColumnizer logLineColumnizer in registeredColumnizer) { @@ -132,10 +133,10 @@ public static ILogLineColumnizer FindColumnizer (string fileName, IAutoLogLineCo priority = columnizerPriority.GetPriority(fileName, loglines); } - priorityListOfColumnizers.Add(new Tuple(priority, logLineColumnizer)); + priorityListOfColumnizers.Add((priority, logLineColumnizer)); } - ILogLineColumnizer lineColumnizer = priorityListOfColumnizers.OrderByDescending(a => a.Item1).Select(a => a.Item2).First(); + ILogLineColumnizer lineColumnizer = priorityListOfColumnizers.OrderByDescending(item => item.priority).Select(item => item.columnizer).First(); return lineColumnizer; } diff --git a/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs b/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs index 36c733ca..123db94b 100644 --- a/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs +++ b/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Text.RegularExpressions; using static LogExpert.Core.Classes.Columnizer.TimeFormatDeterminer; @@ -142,13 +143,13 @@ public string[] GetColumnNames () var i = 1; while (columnNames.Count < GetColumnCount()) { - columnNames.Insert(columnNames.Count - 1, "Source" + i++.ToString()); + columnNames.Insert(columnNames.Count - 1, $"Source{i++}"); } return columnNames.ToArray(); } - public IColumnizedLogLine SplitLine (LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + public IColumnizedLogLine SplitLine (ILogLineColumnizerCallback callback, ILogLine line) { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 diff --git a/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs b/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs index b0277ee5..9c85f936 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs @@ -3,6 +3,7 @@ namespace LogExpert.Core.Classes.DateTimeParser; +//TODO: This should be moved into LogExpert.UI and changed to internal // Ensures we have constant width (number of characters) date formats public static class DateFormatPartAdjuster { @@ -18,6 +19,8 @@ public static class DateFormatPartAdjuster public static string AdjustDateTimeFormatPart(string part) { + ArgumentNullException.ThrowIfNull(part, nameof(part)); + if (!_dateTimePartReplacements.TryGetValue(part, out var adjustedPart)) { return part; diff --git a/src/LogExpert.Core/Classes/DateTimeParser/Token.cs b/src/LogExpert.Core/Classes/DateTimeParser/Token.cs index a9869b55..3db40686 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/Token.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/Token.cs @@ -4,14 +4,16 @@ namespace LogExpert.Core.Classes.DateTimeParser; public static class Token { + //TOOD: check if the callers are checking for null before calling public static bool IsDatePart(string token) { + ArgumentNullException.ThrowIfNull(token, nameof(token)); return token.StartsWith("y", StringComparison.OrdinalIgnoreCase) || token.StartsWith("m", StringComparison.OrdinalIgnoreCase) || token.StartsWith("d", StringComparison.OrdinalIgnoreCase) || token.StartsWith("s", StringComparison.OrdinalIgnoreCase) || token.StartsWith("h", StringComparison.OrdinalIgnoreCase) || - string.Compare(token, "tt", StringComparison.OrdinalIgnoreCase) == 0; + token.Equals("tt", StringComparison.OrdinalIgnoreCase); } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs b/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs index ae68743c..864b96f3 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs @@ -1,37 +1,37 @@ -using System; +using System; +using System.Globalization; namespace LogExpert.Core.Classes.DateTimeParser; internal class Tokenizer { - private string formatString; - private int formatStringPosition; + private readonly string formatString; - public Tokenizer(string fmt) + public Tokenizer (string fmt) { formatString = fmt; } - public int Position => formatStringPosition; + public int Position { get; private set; } public int Length => formatString.Length; - public string Substring(int startIndex, int length) + public string Substring (int startIndex, int length) { return formatString.Substring(startIndex, length); } - public int Peek(int offset = 0) + public int Peek (int offset = 0) { - if (formatStringPosition + offset >= formatString.Length) + if (Position + offset >= formatString.Length) { return -1; } - return formatString[formatStringPosition + offset]; + return formatString[Position + offset]; } - public int PeekUntil(int startOffset, int until) + public int PeekUntil (int startOffset, int until) { var offset = startOffset; while (true) @@ -50,7 +50,7 @@ public int PeekUntil(int startOffset, int until) return 0; } - public bool PeekOneOf(int offset, string s) + public bool PeekOneOf (int offset, string s) { foreach (var c in s) { @@ -62,12 +62,12 @@ public bool PeekOneOf(int offset, string s) return false; } - public void Advance(int characters = 1) + public void Advance (int characters = 1) { - formatStringPosition = Math.Min(formatStringPosition + characters, formatString.Length); + Position = Math.Min(Position + characters, formatString.Length); } - public bool ReadOneOrMore(int c) + public bool ReadOneOrMore (int c) { if (Peek() != c) { @@ -82,7 +82,7 @@ public bool ReadOneOrMore(int c) return true; } - public bool ReadOneOf(string s) + public bool ReadOneOf (string s) { if (PeekOneOf(0, s)) { @@ -92,38 +92,29 @@ public bool ReadOneOf(string s) return false; } - public bool ReadString(string s, bool ignoreCase = false) + public bool ReadString (string str, bool ignoreCase = false) { - if (formatStringPosition + s.Length > formatString.Length) + if (Position + str.Length > formatString.Length) { return false; } - for (var i = 0; i < s.Length; i++) + for (var i = 0; i < str.Length; i++) { - var c1 = s[i]; + var c1 = str[i]; var c2 = (char)Peek(i); - if (ignoreCase) - { - if (char.ToLower(c1) != char.ToLower(c2)) - { - return false; - } - } - else + + if ((ignoreCase && char.ToUpperInvariant(c1) != char.ToUpperInvariant(c2)) || (!ignoreCase && c1 != c2)) { - if (c1 != c2) - { - return false; - } + return false; } } - Advance(s.Length); + Advance(str.Length); return true; } - public bool ReadEnclosed(char open, char close) + public bool ReadEnclosed (char open, char close) { if (Peek() == open) { diff --git a/src/LogExpert.Core/Classes/FileSystemCallback.cs b/src/LogExpert.Core/Classes/FileSystemCallback.cs index 008f2b29..ca8d6688 100644 --- a/src/LogExpert.Core/Classes/FileSystemCallback.cs +++ b/src/LogExpert.Core/Classes/FileSystemCallback.cs @@ -1,4 +1,6 @@ -using NLog; +using System.Globalization; + +using NLog; namespace LogExpert.Core.Classes; @@ -28,6 +30,11 @@ public void Info(string msg) _logger.Info(msg); } + public void Info (IFormatProvider formatProvider, string msg) + { + _logger.Info(formatProvider, msg); + } + public void Debug(string msg) { _logger.Debug(msg); diff --git a/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs b/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs index 18b7dd50..8fd32c11 100644 --- a/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs +++ b/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs @@ -1,4 +1,6 @@ -using LogExpert.Core.Interface; +using System.Globalization; + +using LogExpert.Core.Interface; using NLog; @@ -26,7 +28,7 @@ public FilterCancelHandler(FilterStarter filterStarter) public void EscapePressed() { - _logger.Info("FilterCancelHandler called."); + _logger.Info(CultureInfo.InvariantCulture, "FilterCancelHandler called."); _filterStarter.CancelFilter(); } diff --git a/src/LogExpert.Core/Classes/Filter/FilterPipe.cs b/src/LogExpert.Core/Classes/Filter/FilterPipe.cs index 1b847c4b..fa3a5b52 100644 --- a/src/LogExpert.Core/Classes/Filter/FilterPipe.cs +++ b/src/LogExpert.Core/Classes/Filter/FilterPipe.cs @@ -1,46 +1,41 @@ +using System.Globalization; using System.Text; - using LogExpert.Core.Interface; - using NLog; namespace LogExpert.Core.Classes.Filter; -public class FilterPipe +public class FilterPipe : IDisposable { #region Fields private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); - private IList _lineMappingList = []; + private List _lineMappingList = []; private StreamWriter _writer; private readonly object _fileNameLock = new(); + private bool _disposed; #endregion #region cTor - public FilterPipe (FilterParams filterParams, ILogWindow logWindow) + public FilterPipe(FilterParams filterParams, ILogWindow logWindow) { FilterParams = filterParams; LogWindow = logWindow; IsStopped = false; FileName = Path.GetTempFileName(); + _disposed = false; _logger.Info($"Created temp file: {FileName}"); } #endregion - #region Delegates - - public delegate void ClosedEventHandler (object sender, EventArgs e); - - #endregion - #region Events - public event ClosedEventHandler Closed; + public event EventHandler Closed; #endregion @@ -141,7 +136,7 @@ public void ShiftLineNums (int offset) public void ClearLineNums () { - _logger.Debug("FilterPipe.ClearLineNums()"); + _logger.Debug(CultureInfo.InvariantCulture, "FilterPipe.ClearLineNums()"); lock (_lineMappingList) { for (var i = 0; i < _lineMappingList.Count; ++i) @@ -191,5 +186,24 @@ private void OnClosed () Closed?.Invoke(this, EventArgs.Empty); } + public void Dispose () + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose (bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _writer?.Dispose(); + } + + _disposed = true; + } + } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Filter/FilterStarter.cs b/src/LogExpert.Core/Classes/Filter/FilterStarter.cs index efa6a886..90d8dbce 100644 --- a/src/LogExpert.Core/Classes/Filter/FilterStarter.cs +++ b/src/LogExpert.Core/Classes/Filter/FilterStarter.cs @@ -1,3 +1,5 @@ +using System.Globalization; + using LogExpert.Core.Callback; using LogExpert.Core.Classes.Filter; @@ -97,7 +99,7 @@ public async void DoFilter (FilterParams filterParams, int startLine, int maxCou break; } } - _logger.Info("FilterStarter starts worker for line {0}, lineCount {1}", workStartLine, interval); + _logger.Info(CultureInfo.InvariantCulture, "FilterStarter starts worker for line {0}, lineCount {1}", workStartLine, interval); await Task.Run(() => DoWork(filterParams, workStartLine, interval, ThreadProgressCallback)).ContinueWith(FilterDoneCallback); workStartLine += interval; @@ -122,8 +124,8 @@ public void CancelFilter () _shouldStop = true; lock (_filterWorkerList) { - _logger.Info("Filter cancel requested. Stopping all {0} threads.", _filterWorkerList.Count); - foreach (Filter filter in _filterWorkerList) + _logger.Info(CultureInfo.InvariantCulture, "Filter cancel requested. Stopping all {0} threads.", _filterWorkerList.Count); + foreach (var filter in _filterWorkerList) { filter.ShouldCancel = true; } @@ -142,7 +144,7 @@ private void ThreadProgressCallback (int lineCount) private Filter DoWork (FilterParams filterParams, int startLine, int maxCount, ProgressCallback progressCallback) { - _logger.Info("Started Filter worker [{0}] for line {1}", Environment.CurrentManagedThreadId, startLine); + _logger.Info(CultureInfo.InvariantCulture, "Started Filter worker [{0}] for line {1}", Environment.CurrentManagedThreadId, startLine); // Give every thread own copies of ColumnizerCallback and FilterParams, because the state of the objects changes while filtering FilterParams threadFilterParams = filterParams.CloneWithCurrentColumnizer(); @@ -160,7 +162,7 @@ private Filter DoWork (FilterParams filterParams, int startLine, int maxCount, P } _ = filter.DoFilter(threadFilterParams, startLine, maxCount, progressCallback); - _logger.Info("Filter worker [{0}] for line {1} has completed.", Environment.CurrentManagedThreadId, startLine); + _logger.Info(CultureInfo.InvariantCulture, "Filter worker [{0}] for line {1} has completed.", Environment.CurrentManagedThreadId, startLine); lock (_filterReadyList) { @@ -185,7 +187,7 @@ private void FilterDoneCallback (Task filterTask) private void MergeResults () { - _logger.Info("Merging filter results."); + _logger.Info(CultureInfo.InvariantCulture, "Merging filter results."); foreach (Filter filter in _filterReadyList) { foreach (var lineNum in filter.FilterHitList) @@ -213,7 +215,7 @@ private void MergeResults () FilterHitList.AddRange(_filterHitDict.Keys); FilterResultLines.AddRange(_filterResultDict.Keys); LastFilterLinesList.AddRange(_lastFilterLinesDict.Keys); - _logger.Info("Merging done."); + _logger.Info(CultureInfo.InvariantCulture, "Merging done."); } #endregion diff --git a/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs b/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs index d5800faf..58b0b0bf 100644 --- a/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs +++ b/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs @@ -35,7 +35,7 @@ protected LogStreamReaderBase() /// /// Indicates whether or not the stream reader has already been disposed. /// - public bool IsDisposed { get; private set; } + public abstract bool IsDisposed { get; protected set; } #endregion @@ -46,15 +46,8 @@ protected LogStreamReaderBase() /// public void Dispose() { - try - { - Dispose(true); - GC.SuppressFinalize(this); - } - finally - { - IsDisposed = true; - } + Dispose(true); + GC.SuppressFinalize(this); } /// /// Destroy and release the current stream reader. diff --git a/src/LogExpert.Core/Classes/Log/LogfileReader.cs b/src/LogExpert.Core/Classes/Log/LogfileReader.cs index 279b9668..445ffd1e 100644 --- a/src/LogExpert.Core/Classes/Log/LogfileReader.cs +++ b/src/LogExpert.Core/Classes/Log/LogfileReader.cs @@ -1,16 +1,16 @@ +using System.Globalization; using System.Text; using LogExpert.Core.Classes.xml; using LogExpert.Core.Entities; using LogExpert.Core.EventArguments; -using LogExpert.Core.EventHandlers; using LogExpert.Core.Interface; using NLog; namespace LogExpert.Core.Classes.Log; -public class LogfileReader : IAutoLogLineColumnizerCallback +public class LogfileReader : IAutoLogLineColumnizerCallback, IDisposable { #region Fields @@ -27,7 +27,6 @@ public class LogfileReader : IAutoLogLineColumnizerCallback private readonly IPluginRegistry _pluginRegistry; private IList _bufferList; private ReaderWriterLock _bufferListLock; - private IList _bufferLru; private bool _contentDeleted; private int _currLineCount; private ReaderWriterLock _disposeLock; @@ -36,7 +35,7 @@ public class LogfileReader : IAutoLogLineColumnizerCallback private Task _garbageCollectorTask; private Task _monitorTask; - private readonly CancellationTokenSource cts = new(); + private readonly CancellationTokenSource _cts = new(); private bool _isDeleted; private bool _isFailModeCheckCallPending; @@ -48,6 +47,7 @@ public class LogfileReader : IAutoLogLineColumnizerCallback private ReaderWriterLock _lruCacheDictLock; private bool _shouldStop; + private bool _disposed; private ILogFileInfo _watchedILogFileInfo; #endregion @@ -69,13 +69,15 @@ public LogfileReader (string fileName, EncodingOptions encodingOptions, bool mul _multiFileOptions = multiFileOptions; _pluginRegistry = pluginRegistry; _logLineFx = GetLogLineInternal; + _disposed = false; + InitLruBuffers(); if (multiFile) { - ILogFileInfo info = GetLogFileInfo(fileName); + var info = GetLogFileInfo(fileName); RolloverFilenameHandler rolloverHandler = new(info, _multiFileOptions); - LinkedList nameList = rolloverHandler.GetNameList(_pluginRegistry); + var nameList = rolloverHandler.GetNameList(_pluginRegistry); ILogFileInfo fileInfo = null; foreach (var name in nameList) @@ -107,6 +109,7 @@ public LogfileReader (string[] fileNames, EncodingOptions encodingOptions, int b _multiFileOptions = multiFileOptions; _pluginRegistry = pluginRegistry; _logLineFx = GetLogLineInternal; + _disposed = false; InitLruBuffers(); @@ -126,23 +129,18 @@ public LogfileReader (string[] fileNames, EncodingOptions encodingOptions, int b #region Delegates - public delegate void BlockLoadedEventHandler (object sender, LoadFileEventArgs e); - public delegate void FileNotFoundEventHandler (object sender, EventArgs e); - public delegate void FileRespawnedEventHandler (object sender, EventArgs e); - public delegate void FinishedLoadingEventHandler (object sender, EventArgs e); private delegate Task GetLogLineFx (int lineNum); - public delegate void LoadingStartedEventHandler (object sender, LoadFileEventArgs e); #endregion #region Events - public event FileSizeChangedEventHandler FileSizeChanged; - public event BlockLoadedEventHandler LoadFile; - public event LoadingStartedEventHandler LoadingStarted; - public event FinishedLoadingEventHandler LoadingFinished; - public event FileNotFoundEventHandler FileNotFound; - public event FileRespawnedEventHandler Respawned; + public event EventHandler FileSizeChanged; + public event EventHandler LoadFile; + public event EventHandler LoadingStarted; + public event EventHandler LoadingFinished; + public event EventHandler FileNotFound; + public event EventHandler Respawned; #endregion @@ -258,7 +256,7 @@ public void ReadFiles () /// public int ShiftBuffers () { - _logger.Info("ShiftBuffers() begin for {0}{1}", _fileName, IsMultiFile ? " (MultiFile)" : ""); + _logger.Info(CultureInfo.InvariantCulture, "ShiftBuffers() begin for {0}{1}", _fileName, IsMultiFile ? " (MultiFile)" : ""); AcquireBufferListWriterLock(); var offset = 0; _isLineCountDirty = true; @@ -276,11 +274,11 @@ public int ShiftBuffers () { ILogFileInfo logFileInfo = enumerator.Current; var fileName = logFileInfo.FullName; - _logger.Debug("Testing file {0}", fileName); + _logger.Debug(CultureInfo.InvariantCulture, "Testing file {0}", fileName); LinkedListNode node = fileNameList.Find(fileName); if (node == null) { - _logger.Warn("File {0} not found", fileName); + _logger.Warn(CultureInfo.InvariantCulture, "File {0} not found", fileName); continue; } @@ -288,7 +286,7 @@ public int ShiftBuffers () { fileName = node.Previous.Value; ILogFileInfo newILogFileInfo = GetLogFileInfo(fileName); - _logger.Debug("{0} exists\r\nOld size={1}, new size={2}", fileName, logFileInfo.OriginalLength, newILogFileInfo.Length); + _logger.Debug(CultureInfo.InvariantCulture, "{0} exists\r\nOld size={1}, new size={2}", fileName, logFileInfo.OriginalLength, newILogFileInfo.Length); // is the new file the same as the old buffer info? if (newILogFileInfo.Length == logFileInfo.OriginalLength) { @@ -297,7 +295,7 @@ public int ShiftBuffers () } else { - _logger.Debug("Buffer for {0} must be re-read.", fileName); + _logger.Debug(CultureInfo.InvariantCulture, "Buffer for {0} must be re-read.", fileName); // not the same. so must read the rest of the list anew from the files readNewILogFileInfoList.Add(newILogFileInfo); while (enumerator.MoveNext()) @@ -306,26 +304,26 @@ public int ShiftBuffers () node = fileNameList.Find(fileName); if (node == null) { - _logger.Warn("File {0} not found", fileName); + _logger.Warn(CultureInfo.InvariantCulture, "File {0} not found", fileName); continue; } if (node.Previous != null) { fileName = node.Previous.Value; - _logger.Debug("New name is {0}", fileName); + _logger.Debug(CultureInfo.InvariantCulture, "New name is {0}", fileName); readNewILogFileInfoList.Add(GetLogFileInfo(fileName)); } else { - _logger.Warn("No previous file for {0} found", fileName); + _logger.Warn(CultureInfo.InvariantCulture, "No previous file for {0} found", fileName); } } } } else { - _logger.Info("{0} does not exist", fileName); + _logger.Info(CultureInfo.InvariantCulture, "{0} does not exist", fileName); lostILogFileInfoList.Add(logFileInfo); #if DEBUG // for better overview in logfile: //ILogFileInfo newILogFileInfo = new ILogFileInfo(fileName); @@ -336,7 +334,7 @@ public int ShiftBuffers () if (lostILogFileInfoList.Count > 0) { - _logger.Info("Deleting buffers for lost files"); + _logger.Info(CultureInfo.InvariantCulture, "Deleting buffers for lost files"); foreach (ILogFileInfo ILogFileInfo in lostILogFileInfoList) { //this.ILogFileInfoList.Remove(ILogFileInfo); @@ -348,7 +346,7 @@ public int ShiftBuffers () } _lruCacheDictLock.AcquireWriterLock(Timeout.Infinite); - _logger.Info("Adjusting StartLine values in {0} buffers by offset {1}", _bufferList.Count, offset); + _logger.Info(CultureInfo.InvariantCulture, "Adjusting StartLine values in {0} buffers by offset {1}", _bufferList.Count, offset); foreach (LogBuffer buffer in _bufferList) { SetNewStartLineForBuffer(buffer, buffer.StartLine - offset); @@ -358,23 +356,23 @@ public int ShiftBuffers () #if DEBUG if (_bufferList.Count > 0) { - _logger.Debug("First buffer now has StartLine {0}", _bufferList[0].StartLine); + _logger.Debug(CultureInfo.InvariantCulture, "First buffer now has StartLine {0}", _bufferList[0].StartLine); } #endif } // Read anew all buffers following a buffer info that couldn't be matched with the corresponding existing file - _logger.Info("Deleting buffers for files that must be re-read"); + _logger.Info(CultureInfo.InvariantCulture, "Deleting buffers for files that must be re-read"); foreach (ILogFileInfo ILogFileInfo in readNewILogFileInfoList) { DeleteBuffersForInfo(ILogFileInfo, true); //this.ILogFileInfoList.Remove(ILogFileInfo); } - _logger.Info("Deleting buffers for the watched file"); + _logger.Info(CultureInfo.InvariantCulture, "Deleting buffers for the watched file"); DeleteBuffersForInfo(_watchedILogFileInfo, true); var startLine = LineCount - 1; - _logger.Info("Re-Reading files"); + _logger.Info(CultureInfo.InvariantCulture, "Re-Reading files"); foreach (ILogFileInfo ILogFileInfo in readNewILogFileInfoList) { //ILogFileInfo.OpenFile(); @@ -387,11 +385,11 @@ public int ShiftBuffers () _logFileInfoList = newFileInfoList; _watchedILogFileInfo = GetLogFileInfo(_watchedILogFileInfo.FullName); _logFileInfoList.Add(_watchedILogFileInfo); - _logger.Info("Reading watched file"); + _logger.Info(CultureInfo.InvariantCulture, "Reading watched file"); ReadToBufferList(_watchedILogFileInfo, 0, LineCount); } - _logger.Info("ShiftBuffers() end. offset={0}", offset); + _logger.Info(CultureInfo.InvariantCulture, "ShiftBuffers() end. offset={0}", offset); ReleaseBufferListWriterLock(); return offset; } @@ -433,12 +431,12 @@ public async Task GetLogLineWithWait (int lineNum) else { _isFastFailOnGetLogLine = true; - _logger.Debug("No result after {0}ms. Returning .", WAIT_TIME); + _logger.Debug(CultureInfo.InvariantCulture, "No result after {0}ms. Returning .", WAIT_TIME); } } else { - _logger.Debug("Fast failing GetLogLine()"); + _logger.Debug(CultureInfo.InvariantCulture, "Fast failing GetLogLine()"); if (!_isFailModeCheckCallPending) { _isFailModeCheckCallPending = true; @@ -563,14 +561,14 @@ public int GetRealLineNumForVirtualLineNum (int lineNum) public void StartMonitoring () { - _logger.Info("startMonitoring()"); - _monitorTask = Task.Run(MonitorThreadProc, cts.Token); + _logger.Info(CultureInfo.InvariantCulture, "startMonitoring()"); + _monitorTask = Task.Run(MonitorThreadProc, _cts.Token); _shouldStop = false; } public void StopMonitoring () { - _logger.Info("stopMonitoring()"); + _logger.Info(CultureInfo.InvariantCulture, "stopMonitoring()"); _shouldStop = true; Thread.Sleep(_watchedILogFileInfo.PollInterval); // leave time for the threads to stop by themselves @@ -579,7 +577,7 @@ public void StopMonitoring () { if (_monitorTask.Status == TaskStatus.Running) // if thread has not finished, abort it { - cts.Cancel(); + _cts.Cancel(); } } @@ -587,7 +585,7 @@ public void StopMonitoring () { if (_garbageCollectorTask.Status == TaskStatus.Running) // if thread has not finished, abort it { - cts.Cancel(); + _cts.Cancel(); } } @@ -620,11 +618,11 @@ public void DeleteAllContent () { if (_contentDeleted) { - _logger.Debug("Buffers for {0} already deleted.", Util.GetNameFromPath(_fileName)); + _logger.Debug(CultureInfo.InvariantCulture, "Buffers for {0} already deleted.", Util.GetNameFromPath(_fileName)); return; } - _logger.Info("Deleting all log buffers for {0}. Used mem: {1:N0}", Util.GetNameFromPath(_fileName), GC.GetTotalMemory(true)); //TODO [Z] uh GC collect calls creepy + _logger.Info(CultureInfo.InvariantCulture, "Deleting all log buffers for {0}. Used mem: {1:N0}", Util.GetNameFromPath(_fileName), GC.GetTotalMemory(true)); //TODO [Z] uh GC collect calls creepy AcquireBufferListWriterLock(); _lruCacheDictLock.AcquireWriterLock(Timeout.Infinite); _disposeLock.AcquireWriterLock(Timeout.Infinite); @@ -645,7 +643,7 @@ public void DeleteAllContent () ReleaseBufferListWriterLock(); GC.Collect(); _contentDeleted = true; - _logger.Info("Deleting complete. Used mem: {0:N0}", GC.GetTotalMemory(true)); //TODO [Z] uh GC collect calls creepy + _logger.Info(CultureInfo.InvariantCulture, "Deleting complete. Used mem: {0:N0}", GC.GetTotalMemory(true)); //TODO [Z] uh GC collect calls creepy } /// @@ -695,13 +693,13 @@ public void LogBufferInfoForLine (int lineNum) return; } - _logger.Info("-----------------------------------"); + _logger.Info(CultureInfo.InvariantCulture, "-----------------------------------"); _disposeLock.AcquireReaderLock(Timeout.Infinite); - _logger.Info("Buffer info for line {0}", lineNum); + _logger.Info(CultureInfo.InvariantCulture, "Buffer info for line {0}", lineNum); DumpBufferInfos(buffer); - _logger.Info("File pos for current line: {0}", buffer.GetFilePosForLineOfBlock(lineNum - buffer.StartLine)); + _logger.Info(CultureInfo.InvariantCulture, "File pos for current line: {0}", buffer.GetFilePosForLineOfBlock(lineNum - buffer.StartLine)); _disposeLock.ReleaseReaderLock(); - _logger.Info("-----------------------------------"); + _logger.Info(CultureInfo.InvariantCulture, "-----------------------------------"); ReleaseBufferListReaderLock(); } #endif @@ -709,14 +707,14 @@ public void LogBufferInfoForLine (int lineNum) #if DEBUG public void LogBufferDiagnostic () { - _logger.Info("-------- Buffer diagnostics -------"); + _logger.Info(CultureInfo.InvariantCulture, "-------- Buffer diagnostics -------"); _lruCacheDictLock.AcquireReaderLock(Timeout.Infinite); var cacheCount = _lruCacheDict.Count; - _logger.Info("LRU entries: {0}", cacheCount); + _logger.Info(CultureInfo.InvariantCulture, "LRU entries: {0}", cacheCount); _lruCacheDictLock.ReleaseReaderLock(); AcquireBufferListReaderLock(); - _logger.Info("File: {0}\r\nBuffer count: {1}\r\nDisposed buffers: {2}", _fileName, _bufferList.Count, _bufferList.Count - cacheCount); + _logger.Info(CultureInfo.InvariantCulture, "File: {0}\r\nBuffer count: {1}\r\nDisposed buffers: {2}", _fileName, _bufferList.Count, _bufferList.Count - cacheCount); var lineNum = 0; long disposeSum = 0; long maxDispose = 0; @@ -728,7 +726,7 @@ public void LogBufferDiagnostic () if (buffer.StartLine != lineNum) { _logger.Error("Start line of buffer is: {0}, expected: {1}", buffer.StartLine, lineNum); - _logger.Info("Info of buffer follows:"); + _logger.Info(CultureInfo.InvariantCulture, "Info of buffer follows:"); DumpBufferInfos(buffer); } @@ -740,7 +738,7 @@ public void LogBufferDiagnostic () } ReleaseBufferListReaderLock(); - _logger.Info("Dispose count sum is: {0}\r\nMin dispose count is: {1}\r\nMax dispose count is: {2}\r\n-----------------------------------", disposeSum, minDispose, maxDispose); + _logger.Info(CultureInfo.InvariantCulture, "Dispose count sum is: {0}\r\nMin dispose count is: {1}\r\nMax dispose count is: {2}\r\n-----------------------------------", disposeSum, minDispose, maxDispose); } #endif @@ -751,7 +749,7 @@ public void LogBufferDiagnostic () private ILogFileInfo AddFile (string fileName) { - _logger.Info("Adding file to ILogFileInfoList: " + fileName); + _logger.Info(CultureInfo.InvariantCulture, "Adding file to ILogFileInfoList: " + fileName); ILogFileInfo info = GetLogFileInfo(fileName); _logFileInfoList.Add(info); return info; @@ -761,7 +759,7 @@ private Task GetLogLineInternal (int lineNum) { if (_isDeleted) { - _logger.Debug("Returning null for line {0} because file is deleted.", lineNum); + _logger.Debug(CultureInfo.InvariantCulture, "Returning null for line {0} because file is deleted.", lineNum); // fast fail if dead file was detected. Prevents repeated lags in GUI thread caused by callbacks from control (e.g. repaint) return null; @@ -799,7 +797,7 @@ private Task GetLogLineInternal (int lineNum) private void InitLruBuffers () { _bufferList = []; - _bufferLru = new List(_max_buffers + 1); + //_bufferLru = new List(_max_buffers + 1); //this.lruDict = new Dictionary(this.MAX_BUFFERS + 1); // key=startline, value = index in bufferLru _lruCacheDict = new Dictionary(_max_buffers + 1); _lruCacheDictLock = new ReaderWriterLock(); @@ -809,7 +807,7 @@ private void InitLruBuffers () private void StartGCThread () { - _garbageCollectorTask = Task.Run(GarbageCollectorThreadProc, cts.Token); + _garbageCollectorTask = Task.Run(GarbageCollectorThreadProc, _cts.Token); //_garbageCollectorThread = new Thread(new ThreadStart(GarbageCollectorThreadProc)); //_garbageCollectorThread.IsBackground = true; //_garbageCollectorThread.Start(); @@ -847,9 +845,9 @@ private ILogFileInfo GetLogFileInfo (string fileNameOrUri) //TODO: I changed to private void ReplaceBufferInfos (ILogFileInfo oldLogFileInfo, ILogFileInfo newLogFileInfo) { - _logger.Debug("ReplaceBufferInfos() " + oldLogFileInfo.FullName + " -> " + newLogFileInfo.FullName); + _logger.Debug(CultureInfo.InvariantCulture, "ReplaceBufferInfos() " + oldLogFileInfo.FullName + " -> " + newLogFileInfo.FullName); AcquireBufferListReaderLock(); - foreach (LogBuffer buffer in _bufferList) + foreach (var buffer in _bufferList) { if (buffer.FileInfo == oldLogFileInfo) { @@ -900,24 +898,24 @@ private LogBuffer DeleteBuffersForInfo (ILogFileInfo ILogFileInfo, bool matchNam ReleaseBufferListWriterLock(); if (lastRemovedBuffer == null) { - _logger.Info("lastRemovedBuffer is null"); + _logger.Info(CultureInfo.InvariantCulture, "lastRemovedBuffer is null"); } else { - _logger.Info("lastRemovedBuffer: startLine={0}", lastRemovedBuffer.StartLine); + _logger.Info(CultureInfo.InvariantCulture, "lastRemovedBuffer: startLine={0}", lastRemovedBuffer.StartLine); } return lastRemovedBuffer; } /// - /// The caller must have writer locks for lruCache and buffer list! + /// The caller must have _writer locks for lruCache and buffer list! /// /// private void RemoveFromBufferList (LogBuffer buffer) { - Util.AssertTrue(_lruCacheDictLock.IsWriterLockHeld, "No writer lock for lru cache"); - Util.AssertTrue(_bufferListLock.IsWriterLockHeld, "No writer lock for buffer list"); + Util.AssertTrue(_lruCacheDictLock.IsWriterLockHeld, "No _writer lock for lru cache"); + Util.AssertTrue(_bufferListLock.IsWriterLockHeld, "No _writer lock for buffer list"); _lruCacheDict.Remove(buffer.StartLine); _bufferList.Remove(buffer); } @@ -1050,7 +1048,7 @@ private void ReadToBufferList (ILogFileInfo logFileInfo, long filePos, int start private void AddBufferToList (LogBuffer logBuffer) { #if DEBUG - _logger.Debug("AddBufferToList(): {0}/{1}/{2}", logBuffer.StartLine, logBuffer.LineCount, logBuffer.FileInfo.FullName); + _logger.Debug(CultureInfo.InvariantCulture, "AddBufferToList(): {0}/{1}/{2}", logBuffer.StartLine, logBuffer.LineCount, logBuffer.FileInfo.FullName); #endif _bufferList.Add(logBuffer); //UpdateLru(logBuffer); @@ -1068,7 +1066,7 @@ private void UpdateLruCache (LogBuffer logBuffer) { LockCookie cookie = _lruCacheDictLock.UpgradeToWriterLock(Timeout.Infinite); if (!_lruCacheDict.TryGetValue(logBuffer.StartLine, out cacheEntry) - ) // #536: re-test, because multiple threads may have been waiting for writer lock + ) // #536: re-test, because multiple threads may have been waiting for _writer lock { cacheEntry = new LogBufferCacheEntry(); cacheEntry.LogBuffer = logBuffer; @@ -1081,16 +1079,16 @@ private void UpdateLruCache (LogBuffer logBuffer) _logger.Error(e, "Error in LRU cache: " + e.Message); #if DEBUG // there seems to be a bug with double added key - _logger.Info("Added buffer:"); + _logger.Info(CultureInfo.InvariantCulture, "Added buffer:"); DumpBufferInfos(logBuffer); if (_lruCacheDict.TryGetValue(logBuffer.StartLine, out LogBufferCacheEntry existingEntry)) { - _logger.Info("Existing buffer: "); + _logger.Info(CultureInfo.InvariantCulture, "Existing buffer: "); DumpBufferInfos(existingEntry.LogBuffer); } else { - _logger.Warn("Ooops? Cannot find the already existing entry in LRU."); + _logger.Warn(CultureInfo.InvariantCulture, "Ooops? Cannot find the already existing entry in LRU."); } #endif _lruCacheDictLock.ReleaseLock(); @@ -1112,7 +1110,7 @@ private void UpdateLruCache (LogBuffer logBuffer) /// private void SetNewStartLineForBuffer (LogBuffer logBuffer, int newLineNum) { - Util.AssertTrue(_lruCacheDictLock.IsWriterLockHeld, "No writer lock for lru cache"); + Util.AssertTrue(_lruCacheDictLock.IsWriterLockHeld, "No _writer lock for lru cache"); if (_lruCacheDict.ContainsKey(logBuffer.StartLine)) { _lruCacheDict.Remove(logBuffer.StartLine); @@ -1132,7 +1130,7 @@ private void GarbageCollectLruCache () #if DEBUG long startTime = Environment.TickCount; #endif - _logger.Debug("Starting garbage collection"); + _logger.Debug(CultureInfo.InvariantCulture, "Starting garbage collection"); var threshold = 10; _lruCacheDictLock.AcquireWriterLock(Timeout.Infinite); var diff = 0; @@ -1142,7 +1140,7 @@ private void GarbageCollectLruCache () #if DEBUG if (diff > 0) { - _logger.Info("Removing {0} entries from LRU cache for {1}", diff, Util.GetNameFromPath(_fileName)); + _logger.Info(CultureInfo.InvariantCulture, "Removing {0} entries from LRU cache for {1}", diff, Util.GetNameFromPath(_fileName)); } #endif SortedList useSorterList = []; @@ -1178,7 +1176,7 @@ private void GarbageCollectLruCache () if (diff > 0) { long endTime = Environment.TickCount; - _logger.Info("Garbage collector time: " + (endTime - startTime) + " ms."); + _logger.Info(CultureInfo.InvariantCulture, "Garbage collector time: " + (endTime - startTime) + " ms."); } #endif } @@ -1286,7 +1284,7 @@ private void ClearLru () // this.bufferLru.Clear(); // this.lruDict.Clear(); //} - _logger.Info("Clearing LRU cache."); + _logger.Info(CultureInfo.InvariantCulture, "Clearing LRU cache."); _lruCacheDictLock.AcquireWriterLock(Timeout.Infinite); _disposeLock.AcquireWriterLock(Timeout.Infinite); foreach (LogBufferCacheEntry entry in _lruCacheDict.Values) @@ -1297,13 +1295,13 @@ private void ClearLru () _lruCacheDict.Clear(); _disposeLock.ReleaseWriterLock(); _lruCacheDictLock.ReleaseWriterLock(); - _logger.Info("Clearing done."); + _logger.Info(CultureInfo.InvariantCulture, "Clearing done."); } private void ReReadBuffer (LogBuffer logBuffer) { #if DEBUG - _logger.Info("re-reading buffer: {0}/{1}/{2}", logBuffer.StartLine, logBuffer.LineCount, logBuffer.FileInfo.FullName); + _logger.Info(CultureInfo.InvariantCulture, "re-reading buffer: {0}/{1}/{2}", logBuffer.StartLine, logBuffer.LineCount, logBuffer.FileInfo.FullName); #endif try { @@ -1356,12 +1354,12 @@ private void ReReadBuffer (LogBuffer logBuffer) if (maxLinesCount != logBuffer.LineCount) { - _logger.Warn("LineCount in buffer differs after re-reading. old={0}, new={1}", maxLinesCount, logBuffer.LineCount); + _logger.Warn(CultureInfo.InvariantCulture, "LineCount in buffer differs after re-reading. old={0}, new={1}", maxLinesCount, logBuffer.LineCount); } if (dropCount - logBuffer.PrevBuffersDroppedLinesSum != logBuffer.DroppedLinesCount) { - _logger.Warn("DroppedLinesCount in buffer differs after re-reading. old={0}, new={1}", logBuffer.DroppedLinesCount, dropCount); + _logger.Warn(CultureInfo.InvariantCulture, "DroppedLinesCount in buffer differs after re-reading. old={0}, new={1}", logBuffer.DroppedLinesCount, dropCount); logBuffer.DroppedLinesCount = dropCount - logBuffer.PrevBuffersDroppedLinesSum; } @@ -1425,11 +1423,11 @@ private void GetLineFinishedCallback (ILogLine line) _isFailModeCheckCallPending = false; if (line != null) { - _logger.Debug("'isFastFailOnGetLogLine' flag was reset"); + _logger.Debug(CultureInfo.InvariantCulture, "'isFastFailOnGetLogLine' flag was reset"); _isFastFailOnGetLogLine = false; } - _logger.Debug("'isLogLineCallPending' flag was reset."); + _logger.Debug(CultureInfo.InvariantCulture, "'isLogLineCallPending' flag was reset."); } private LogBuffer GetFirstBufferForFileByLogBuffer (LogBuffer logBuffer) @@ -1463,7 +1461,7 @@ private void MonitorThreadProc () { Thread.CurrentThread.Name = "MonitorThread"; //IFileSystemPlugin fs = PluginRegistry.GetInstance().FindFileSystemForUri(this.watchedILogFileInfo.FullName); - _logger.Info("MonitorThreadProc() for file {0}", _watchedILogFileInfo.FullName); + _logger.Info(CultureInfo.InvariantCulture, "MonitorThreadProc() for file {0}", _watchedILogFileInfo.FullName); long oldSize; try @@ -1532,7 +1530,7 @@ private void MonitoredFileNotFound () long oldSize; if (!_isDeleted) { - _logger.Debug("File not FileNotFoundException catched. Switching to 'deleted' mode."); + _logger.Debug(CultureInfo.InvariantCulture, "File not FileNotFoundException catched. Switching to 'deleted' mode."); _isDeleted = true; oldSize = _fileLength = -1; FileSize = 0; @@ -1541,7 +1539,7 @@ private void MonitoredFileNotFound () #if DEBUG else { - _logger.Debug("File not FileNotFoundException catched. Already in deleted mode."); + _logger.Debug(CultureInfo.InvariantCulture, "File not FileNotFoundException catched. Already in deleted mode."); } #endif } @@ -1558,7 +1556,7 @@ private void FileChanged () var newSize = _fileLength; //if (this.currFileSize != newSize) { - _logger.Info("file size changed. new size={0}, file: {1}", newSize, _fileName); + _logger.Info(CultureInfo.InvariantCulture, "file size changed. new size={0}, file: {1}", newSize, _fileName); FireChangeEvent(); } } @@ -1571,7 +1569,7 @@ private void FireChangeEvent () var newSize = _fileLength; if (newSize < FileSize || _isDeleted) { - _logger.Info("File was created anew: new size={0}, oldSize={1}", newSize, FileSize); + _logger.Info(CultureInfo.InvariantCulture, "File was created anew: new size={0}, oldSize={1}", newSize, FileSize); // Fire "New File" event FileSize = 0; LineCount = 0; @@ -1772,7 +1770,7 @@ private void DumpBufferInfos (LogBuffer buffer) { if (_logger.IsTraceEnabled) { - _logger.Trace("StartLine: {0}\r\nLineCount: {1}\r\nStartPos: {2}\r\nSize: {3}\r\nDisposed: {4}\r\nDisposeCount: {5}\r\nFile: {6}", + _logger.Trace(CultureInfo.InvariantCulture, "StartLine: {0}\r\nLineCount: {1}\r\nStartPos: {2}\r\nSize: {3}\r\nDisposed: {4}\r\nDisposeCount: {5}\r\nFile: {6}", buffer.StartLine, buffer.LineCount, buffer.StartPos, @@ -1787,9 +1785,30 @@ private void DumpBufferInfos (LogBuffer buffer) #endregion + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); // Suppress finalization (not needed but best practice) + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + DeleteAllContent(); + _cts.Dispose(); // Dispose managed resources + } + + _disposed = true; + } + } + + //TODO: Seems that this can be deleted. Need to verify. ~LogfileReader () { - DeleteAllContent(); + Dispose (false); } protected virtual void OnFileSizeChanged (LogEventArgs e) @@ -1819,7 +1838,7 @@ protected virtual void OnFileNotFound () protected virtual void OnRespawned () { - _logger.Info("OnRespawned()"); + _logger.Info(CultureInfo.InvariantCulture, "OnRespawned()"); Respawned?.Invoke(this, EventArgs.Empty); } diff --git a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs index 0cd74d6d..5f072c27 100644 --- a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs +++ b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs @@ -88,13 +88,14 @@ protected override void Dispose (bool disposing) { _stream.Dispose(); _reader.Dispose(); - } + IsDisposed = true; +} } //TODO This is unsafe and should be refactored public override unsafe int ReadChar () { - ObjectDisposedException.ThrowIf(IsDisposed, GetType().ToString()); + ObjectDisposedException.ThrowIf(IsDisposed, GetType()); try { @@ -126,7 +127,7 @@ protected virtual void ResetReader () protected StreamReader GetStreamReader () { - ObjectDisposedException.ThrowIf(IsDisposed, GetType().ToString()); + ObjectDisposedException.ThrowIf(IsDisposed, GetType()); return _reader; } diff --git a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs index 8b8f7c9d..a47eaa0d 100644 --- a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs +++ b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs @@ -11,6 +11,8 @@ public class PositionAwareStreamReaderLegacy : PositionAwareStreamReaderBase private int _charBufferPos; private bool _crDetect; + public override bool IsDisposed { get; protected set; } + #endregion #region cTor diff --git a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs index 354703a0..a4f8b4a0 100644 --- a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs +++ b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs @@ -17,6 +17,8 @@ public class PositionAwareStreamReaderSystem : PositionAwareStreamReaderBase private int _newLineSequenceLength; + public override bool IsDisposed { get; protected set; } + #endregion #region cTor diff --git a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs index c6eab62c..ae276817 100644 --- a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs +++ b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs @@ -1,3 +1,4 @@ +using System; using System.Globalization; using System.Text; using System.Text.RegularExpressions; @@ -140,24 +141,26 @@ private void ParseFormatString (string formatString) { var fmt = EscapeNonvarRegions(formatString); var datePos = formatString.IndexOf("$D(", StringComparison.Ordinal); + if (datePos != -1) { var endPos = formatString.IndexOf(')', datePos); if (endPos != -1) { - _dateTimeFormat = formatString.Substring(datePos + 3, endPos - datePos - 3); - _dateTimeFormat = _dateTimeFormat.ToUpper(); - _dateTimeFormat = _dateTimeFormat.Replace('D', 'd').Replace('Y', 'y'); - - var dtf = _dateTimeFormat; - dtf = dtf.ToUpper(); - dtf = dtf.Replace("D", "\\d", StringComparison.Ordinal); - dtf = dtf.Replace("Y", "\\d", StringComparison.Ordinal); - dtf = dtf.Replace("M", "\\d", StringComparison.Ordinal); - fmt = fmt.Remove(datePos, 2); // remove $D - fmt = fmt.Remove(datePos + 1, _dateTimeFormat.Length); // replace with regex version of format - fmt = fmt.Insert(datePos + 1, dtf); - fmt = fmt.Insert(datePos + 1, "?'date'"); // name the regex group + _dateTimeFormat = formatString.Substring(datePos + 3, endPos - datePos - 3) + .ToUpperInvariant() + .Replace('D', 'd') + .Replace('Y', 'y'); + + var dtf = _dateTimeFormat.ToUpper(CultureInfo.InvariantCulture) + .Replace("D", "\\d", StringComparison.Ordinal) + .Replace("Y", "\\d", StringComparison.Ordinal) + .Replace("M", "\\d", StringComparison.Ordinal); + + fmt = fmt.Remove(datePos, 2) // remove $D + .Remove(datePos + 1, _dateTimeFormat.Length) // replace with regex version of format + .Insert(datePos + 1, dtf) + .Insert(datePos + 1, "?'date'"); // name the regex group } } diff --git a/src/LogExpert.Core/Classes/SysoutPipe.cs b/src/LogExpert.Core/Classes/SysoutPipe.cs index 86460221..4068cf1c 100644 --- a/src/LogExpert.Core/Classes/SysoutPipe.cs +++ b/src/LogExpert.Core/Classes/SysoutPipe.cs @@ -1,18 +1,20 @@ -using NLog; +using NLog; using System.Diagnostics; +using System.Globalization; using System.Text; namespace LogExpert.Core.Classes; -public class SysoutPipe +public class SysoutPipe : IDisposable { #region Fields - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); - private readonly StreamReader sysout; - private StreamWriter writer; + private readonly StreamReader _sysout; + private StreamWriter _writer; + private bool _disposed; #endregion @@ -20,12 +22,13 @@ public class SysoutPipe public SysoutPipe(StreamReader sysout) { - this.sysout = sysout; + _disposed = false; + this._sysout = sysout; FileName = Path.GetTempFileName(); - _logger.Info("sysoutPipe created temp file: {0}", FileName); + _logger.Info(CultureInfo.InvariantCulture, "sysoutPipe created temp file: {0}", FileName); FileStream fStream = new(FileName, FileMode.Append, FileAccess.Write, FileShare.Read); - writer = new StreamWriter(fStream, Encoding.Unicode); + _writer = new StreamWriter(fStream, Encoding.Unicode); Thread thread = new(new ThreadStart(ReaderThread)) { @@ -46,14 +49,14 @@ public SysoutPipe(StreamReader sysout) public void ClosePipe() { - writer.Close(); - writer = null; + _writer.Close(); + _writer = null; } public void DataReceivedEventHandler(object sender, DataReceivedEventArgs e) { - writer.WriteLine(e.Data); + _writer.WriteLine(e.Data); } public void ProcessExitedEventHandler(object sender, System.EventArgs e) @@ -76,12 +79,12 @@ protected void ReaderThread() { try { - var read = sysout.Read(buff, 0, 256); + var read = _sysout.Read(buff, 0, 256); if (read == 0) { break; } - writer.Write(buff, 0, read); + _writer.Write(buff, 0, read); } catch (IOException e) { @@ -92,4 +95,23 @@ protected void ReaderThread() ClosePipe(); } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); // Suppress finalization (not needed but best practice) + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _writer.Dispose(); // Dispose managed resources + } + + _disposed = true; + } + } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs b/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs index 469f5ab2..1188c203 100644 --- a/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs +++ b/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs @@ -24,6 +24,8 @@ public class XmlBlockSplitter : LogStreamReaderBase private string _stylesheet; private XslCompiledTransform _xslt; + public override bool IsDisposed { get; protected set; } + #endregion #region cTor @@ -39,9 +41,10 @@ public XmlBlockSplitter(XmlLogReader reader, IXmlLogConfiguration xmlLogConfig) // Create the XmlNamespaceManager. NameTable nt = new(); XmlNamespaceManager nsmgr = new(nt); - if (xmlLogConfig.Namespace != null) + var namespaceDeclaration = xmlLogConfig.GetNamespaceDeclaration(); + if (namespaceDeclaration != null) { - nsmgr.AddNamespace(xmlLogConfig.Namespace[0], xmlLogConfig.Namespace[1]); + nsmgr.AddNamespace(namespaceDeclaration[0], namespaceDeclaration[1]); } // Create the XmlParserContext. _context = new XmlParserContext(nt, nsmgr, null, XmlSpace.None); @@ -135,6 +138,7 @@ protected override void Dispose(bool disposing) if (disposing) { _reader.Dispose(); + IsDisposed = true; } } diff --git a/src/LogExpert.Core/Classes/xml/XmlLogReader.cs b/src/LogExpert.Core/Classes/xml/XmlLogReader.cs index 9334cbbd..43c4e2c7 100644 --- a/src/LogExpert.Core/Classes/xml/XmlLogReader.cs +++ b/src/LogExpert.Core/Classes/xml/XmlLogReader.cs @@ -10,6 +10,7 @@ public class XmlLogReader : LogStreamReaderBase #region Fields private readonly ILogStreamReader reader; + public override bool IsDisposed { get; protected set; } #endregion @@ -47,6 +48,7 @@ protected override void Dispose(bool disposing) if (disposing) { reader.Dispose(); + IsDisposed = true; } } diff --git a/src/LogExpert.Core/Entities/DebugOptions.cs b/src/LogExpert.Core/Entities/DebugOptions.cs index f6e1fcfd..fbd4b084 100644 --- a/src/LogExpert.Core/Entities/DebugOptions.cs +++ b/src/LogExpert.Core/Entities/DebugOptions.cs @@ -1,6 +1,6 @@ namespace LogExpert.Core.Entities; -public class DebugOptions +public static class DebugOptions { public static bool DisableWordHighlight { get; set; } } \ No newline at end of file diff --git a/src/LogExpert.Core/EventHandlers/EventHandlers.cs b/src/LogExpert.Core/EventHandlers/EventHandlers.cs deleted file mode 100644 index 63f44923..00000000 --- a/src/LogExpert.Core/EventHandlers/EventHandlers.cs +++ /dev/null @@ -1,7 +0,0 @@ -using LogExpert.Core.Entities; -using LogExpert.Core.EventArguments; - -namespace LogExpert.Core.EventHandlers; - -public delegate void ConfigChangedEventHandler(object sender, ConfigChangedEventArgs e); -public delegate void FileSizeChangedEventHandler(object sender, LogEventArgs e); diff --git a/src/LogExpert.Core/Interface/IBookmarkView.cs b/src/LogExpert.Core/Interface/IBookmarkView.cs index d22a7791..963c7c41 100644 --- a/src/LogExpert.Core/Interface/IBookmarkView.cs +++ b/src/LogExpert.Core/Interface/IBookmarkView.cs @@ -9,6 +9,7 @@ public interface IBookmarkView { #region Properties + //TODO: After all refactoring is done, take care of this warning. bool LineColumnVisible { set; } #endregion diff --git a/src/LogExpert.Core/Interface/IConfigManager.cs b/src/LogExpert.Core/Interface/IConfigManager.cs index 57638394..d921e9b4 100644 --- a/src/LogExpert.Core/Interface/IConfigManager.cs +++ b/src/LogExpert.Core/Interface/IConfigManager.cs @@ -1,6 +1,5 @@ using LogExpert.Core.Config; using LogExpert.Core.EventArguments; -using LogExpert.Core.EventHandlers; namespace LogExpert.Core.Interface; @@ -16,6 +15,6 @@ public interface IConfigManager void Export(FileInfo fileInfo); void Import(FileInfo fileInfo, ExportImportFlags importFlags); void ImportHighlightSettings(FileInfo fileInfo, ExportImportFlags importFlags); - event ConfigChangedEventHandler ConfigChanged; //TODO: All handlers that are public shoulld be in Core + event EventHandler ConfigChanged; //TODO: All handlers that are public shoulld be in Core void Save(SettingsFlags flags); } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/ILogWindow.cs b/src/LogExpert.Core/Interface/ILogWindow.cs index 9072cdcb..a0181219 100644 --- a/src/LogExpert.Core/Interface/ILogWindow.cs +++ b/src/LogExpert.Core/Interface/ILogWindow.cs @@ -1,7 +1,6 @@ - using LogExpert.Core.Classes.Log; using LogExpert.Core.Classes.Persister; -using LogExpert.Core.EventHandlers; +using LogExpert.Core.Entities; namespace LogExpert.Core.Interface; @@ -36,8 +35,8 @@ public interface ILogWindow string FileName { get; } - event FileSizeChangedEventHandler FileSizeChanged; //TODO: All handlers should be moved to Core + //event EventHandler FileSizeChanged; //TODO: All handlers should be moved to Core - event EventHandler TailFollowed; + //event EventHandler TailFollowed; //LogExpert.UI.Controls.LogTabWindow.LogTabWindow.LogWindowData Tag { get; } } \ No newline at end of file diff --git a/src/LogExpert.UI/Controls/BufferedDataGridView.cs b/src/LogExpert.UI/Controls/BufferedDataGridView.cs index cc249ece..fb93a84c 100644 --- a/src/LogExpert.UI/Controls/BufferedDataGridView.cs +++ b/src/LogExpert.UI/Controls/BufferedDataGridView.cs @@ -1,4 +1,5 @@ using System.Drawing.Drawing2D; +using System.Globalization; using System.Runtime.Versioning; using LogExpert.Core.Entities; @@ -265,7 +266,7 @@ private void PaintOverlays (PaintEventArgs e) if (_logger.IsDebugEnabled) { - _logger.Debug($"ClipRgn: {myBuffer.Graphics.ClipBounds.Left},{myBuffer.Graphics.ClipBounds.Top},{myBuffer.Graphics.ClipBounds.Width},{myBuffer.Graphics.ClipBounds.Height}"); + _logger.Debug(CultureInfo.InvariantCulture, $"ClipRgn: {myBuffer.Graphics.ClipBounds.Left},{myBuffer.Graphics.ClipBounds.Top},{myBuffer.Graphics.ClipBounds.Width},{myBuffer.Graphics.ClipBounds.Height}"); } } } @@ -326,7 +327,7 @@ private void OnControlKeyDown (object sender, KeyEventArgs e) } else { - _logger.Warn("Edit control was null, to be checked"); + _logger.Warn(CultureInfo.InvariantCulture, "Edit control was null, to be checked"); } } } diff --git a/src/LogExpert.UI/Controls/DateTimeDragControl.cs b/src/LogExpert.UI/Controls/DateTimeDragControl.cs index 0d4dd777..cd804dff 100644 --- a/src/LogExpert.UI/Controls/DateTimeDragControl.cs +++ b/src/LogExpert.UI/Controls/DateTimeDragControl.cs @@ -234,16 +234,15 @@ private void InitCustomRects (Section dateSection) .Select(DateFormatPartAdjuster.AdjustDateTimeFormatPart) .ToArray(); - Rectangle rect = ClientRectangle; - var oneCharWidth = rect.Width / _dateParts.Sum(s => s.Length); - var left = rect.Left; + var oneCharWidth = ClientRectangle.Width / _dateParts.Sum(s => s.Length); + var left = ClientRectangle.Left; _digitRects.Clear(); foreach (var datePart in _dateParts) { var s = datePart.Length * oneCharWidth; - _digitRects.Add(new Rectangle(left, rect.Top, s, rect.Height)); + _digitRects.Add(new Rectangle(left, ClientRectangle.Top, s, ClientRectangle.Height)); left += s; } diff --git a/src/LogExpert.UI/Controls/KnobControl.cs b/src/LogExpert.UI/Controls/KnobControl.cs index f0893f18..6aec9072 100644 --- a/src/LogExpert.UI/Controls/KnobControl.cs +++ b/src/LogExpert.UI/Controls/KnobControl.cs @@ -1,5 +1,6 @@ using NLog; +using System.Globalization; using System.Runtime.Versioning; namespace LogExpert.UI.Controls; @@ -147,7 +148,7 @@ protected override void OnMouseMove(MouseEventArgs e) var sense = _isShiftPressed ? DragSensitivity * 2 : DragSensitivity; var diff = _startMouseY - e.Y; - _logger.Debug("KnobDiff: {0}", diff); + _logger.Debug(CultureInfo.InvariantCulture, "KnobDiff: {0}", diff); var range = MaxValue - MinValue; _value = _oldValue + diff / sense; diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs index c593387e..cbaea090 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs @@ -9,7 +9,6 @@ using LogExpert.Core.Config; using LogExpert.Core.Entities; using LogExpert.Core.EventArguments; -using LogExpert.Core.EventHandlers; using LogExpert.Core.Interface; using LogExpert.Dialogs; using LogExpert.UI.Dialogs; @@ -98,8 +97,6 @@ internal partial class LogWindow : DockContent, ILogPaintContextUI, ILogView, IL private int _filterPipeNameCounter; private List _filterResultList = []; - private EventWaitHandle _filterUpdateEvent = new ManualResetEvent(false); - private ILogLineColumnizer _forcedColumnizer; private ILogLineColumnizer _forcedColumnizerForLoading; private bool _isDeadFile; @@ -401,7 +398,7 @@ public void ChangeTheme (Control.ControlCollection container) #region Events - public event FileSizeChangedEventHandler FileSizeChanged; + public event EventHandler FileSizeChanged; public event ProgressBarEventHandler ProgressBarUpdate; @@ -507,17 +504,17 @@ public bool IsMultiFile LogfileReader ILogWindow.LogFileReader => _logFileReader; - event FileSizeChangedEventHandler ILogWindow.FileSizeChanged - { - add => FileSizeChanged += new FileSizeChangedEventHandler(value); - remove => FileSizeChanged -= new FileSizeChangedEventHandler(value); - } - - event EventHandler ILogWindow.TailFollowed - { - add => TailFollowed += new TailFollowedEventHandler(value); - remove => TailFollowed -= new TailFollowedEventHandler(value); - } + //public event EventHandler ILogWindow.FileSizeChanged + //{ + // add => FileSizeChanged += new EventHandler(value); + // remove => FileSizeChanged -= new EventHandler(value); + //} + + //event EventHandler ILogWindow.TailFollowed + //{ + // add => TailFollowed += new TailFollowedEventHandler(value); + // remove => TailFollowed -= new TailFollowedEventHandler(value); + //} #endregion diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs index 2b8e367a..17cfed51 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using System.Globalization; using System.Runtime.Versioning; using LogExpert.Core.Classes; @@ -132,7 +133,7 @@ private void OnLogFileReaderLoadingStarted (object sender, LoadFileEventArgs e) private void OnLogFileReaderFinishedLoading (object sender, EventArgs e) { //Thread.CurrentThread.Name = "FinishedLoading event thread"; - _logger.Info("Finished loading."); + _logger.Info(CultureInfo.InvariantCulture, "Finished loading."); _isLoading = false; _isDeadFile = false; if (!_waitingForClose) @@ -151,7 +152,7 @@ private void OnLogFileReaderFinishedLoading (object sender, EventArgs e) if (filterTailCheckBox.Checked) { - _logger.Info("Refreshing filter view because of reload."); + _logger.Info(CultureInfo.InvariantCulture, "Refreshing filter view because of reload."); Invoke(new MethodInvoker(FilterSearch)); // call on proper thread } @@ -166,7 +167,7 @@ private void OnLogFileReaderFileNotFound (object sender, EventArgs e) { if (!IsDisposed && !Disposing) { - _logger.Info("Handling file not found event."); + _logger.Info(CultureInfo.InvariantCulture, "Handling file not found event."); _isDeadFile = true; BeginInvoke(new MethodInvoker(LogfileDead)); } @@ -209,7 +210,7 @@ private void OnLogFileReaderLoadFile (object sender, LoadFileEventArgs e) { if (e.NewFile) { - _logger.Info("File created anew."); + _logger.Info(CultureInfo.InvariantCulture, "File created anew."); // File was new created (e.g. rollover) _isDeadFile = false; @@ -219,7 +220,7 @@ private void OnLogFileReaderLoadFile (object sender, LoadFileEventArgs e) BeginInvoke(invoker); //Thread loadThread = new Thread(new ThreadStart(ReloadNewFile)); //loadThread.Start(); - _logger.Debug("Reloading invoked."); + _logger.Debug(CultureInfo.InvariantCulture, "Reloading invoked."); } else if (_isLoading) { @@ -230,7 +231,7 @@ private void OnLogFileReaderLoadFile (object sender, LoadFileEventArgs e) private void OnFileSizeChanged (object sender, LogEventArgs e) { //OnFileSizeChanged(e); // now done in UpdateGrid() - _logger.Info("Got FileSizeChanged event. prevLines:{0}, curr lines: {1}", e.PrevLineCount, e.LineCount); + _logger.Info(CultureInfo.InvariantCulture, "Got FileSizeChanged event. prevLines:{0}, curr lines: {1}", e.PrevLineCount, e.LineCount); // - now done in the thread that works on the event args list //if (e.IsRollover) @@ -690,7 +691,7 @@ private void OnSelectionChangedTriggerSignal (object sender, EventArgs e) var selCount = 0; try { - _logger.Debug("Selection changed trigger"); + _logger.Debug(CultureInfo.InvariantCulture, "Selection changed trigger"); selCount = dataGridView.SelectedRows.Count; if (selCount > 1) { diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs index e484a366..c50fee65 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs @@ -156,7 +156,7 @@ private bool LoadPersistenceOptions () if (persistenceData.MultiFileNames.Count > 0) { - _logger.Info("Detected MultiFile name list in persistence options"); + _logger.Info(CultureInfo.InvariantCulture, "Detected MultiFile name list in persistence options"); _fileNames = new string[persistenceData.MultiFileNames.Count]; persistenceData.MultiFileNames.CopyTo(_fileNames); } @@ -331,7 +331,7 @@ private void ReInitFilterParams (FilterParams filterParams) private void EnterLoadFileStatus () { - _logger.Debug("EnterLoadFileStatus begin"); + _logger.Debug(CultureInfo.InvariantCulture, "EnterLoadFileStatus begin"); if (InvokeRequired) { @@ -356,7 +356,7 @@ private void EnterLoadFileStatus () ClearBookmarkList(); dataGridView.ClearSelection(); dataGridView.RowCount = 0; - _logger.Debug("EnterLoadFileStatus end"); + _logger.Debug(CultureInfo.InvariantCulture, "EnterLoadFileStatus end"); } [SupportedOSPlatform("windows")] @@ -376,7 +376,7 @@ private void PositionAfterReload (ReloadMemento reloadMemento) [SupportedOSPlatform("windows")] private void LogfileDead () { - _logger.Info("File not found."); + _logger.Info(CultureInfo.InvariantCulture, "File not found."); _isDeadFile = true; //this.logFileReader.FileSizeChanged -= this.FileSizeChangedHandler; @@ -403,7 +403,7 @@ private void LogfileDead () [SupportedOSPlatform("windows")] private void LogfileRespawned () { - _logger.Info("LogfileDead(): Reloading file because it has been respawned."); + _logger.Info(CultureInfo.InvariantCulture, "LogfileDead(): Reloading file because it has been respawned."); _isDeadFile = false; dataGridView.Enabled = true; StatusLineText(""); @@ -529,7 +529,7 @@ private void ReloadNewFile () } else { - _logger.Debug("Preventing reload because of recursive calls."); + _logger.Debug(CultureInfo.InvariantCulture, "Preventing reload because of recursive calls."); } _reloadOverloadCounter--; @@ -539,9 +539,9 @@ private void ReloadNewFile () [SupportedOSPlatform("windows")] private void ReloadFinishedThreadFx () { - _logger.Info("Waiting for loading to be complete."); + _logger.Info(CultureInfo.InvariantCulture, "Waiting for loading to be complete."); _loadingFinishedEvent.WaitOne(); - _logger.Info("Refreshing filter view because of reload."); + _logger.Info(CultureInfo.InvariantCulture, "Refreshing filter view because of reload."); Invoke(new MethodInvoker(FilterSearch)); LoadFilterPipes(); } @@ -552,7 +552,7 @@ private void UpdateProgress (LoadFileEventArgs e) { if (e.ReadPos >= e.FileSize) { - //_logger.Warn("UpdateProgress(): ReadPos (" + e.ReadPos + ") is greater than file size (" + e.FileSize + "). Aborting Update"); + //_logger.Warn(CultureInfo.InvariantCulture, "UpdateProgress(): ReadPos (" + e.ReadPos + ") is greater than file size (" + e.FileSize + "). Aborting Update"); return; } @@ -589,7 +589,7 @@ private void LoadingStarted (LoadFileEventArgs e) private void LoadingFinished () { - _logger.Info("File loading complete."); + _logger.Info(CultureInfo.InvariantCulture, "File loading complete."); StatusLineText(""); _logFileReader.FileSizeChanged += OnFileSizeChanged; @@ -629,16 +629,16 @@ private void LogEventWorker () Thread.CurrentThread.Name = "LogEventWorker"; while (true) { - _logger.Debug("Waiting for signal"); + _logger.Debug(CultureInfo.InvariantCulture, "Waiting for signal"); _logEventArgsEvent.WaitOne(); - _logger.Debug("Wakeup signal received."); + _logger.Debug(CultureInfo.InvariantCulture, "Wakeup signal received."); while (true) { LogEventArgs e; var lastLineCount = 0; lock (_logEventArgsList) { - _logger.Info("{0} events in queue", _logEventArgsList.Count); + _logger.Info(CultureInfo.InvariantCulture, "{0} events in queue", _logEventArgsList.Count); if (_logEventArgsList.Count == 0) { _logEventArgsEvent.Reset(); @@ -717,7 +717,7 @@ private void UpdateGrid (LogEventArgs e) dataGridView.RowCount = e.LineCount; } - _logger.Debug("UpdateGrid(): new RowCount={0}", dataGridView.RowCount); + _logger.Debug(CultureInfo.InvariantCulture, "UpdateGrid(): new RowCount={0}", dataGridView.RowCount); if (e.IsRollover) { @@ -732,7 +732,7 @@ private void UpdateGrid (LogEventArgs e) currentLineNum = 0; } - _logger.Debug("UpdateGrid(): Rollover=true, Rollover offset={0}, currLineNum was {1}, new currLineNum={2}", e.RolloverOffset, dataGridView.CurrentCellAddress.Y, currentLineNum); + _logger.Debug(CultureInfo.InvariantCulture, "UpdateGrid(): Rollover=true, Rollover offset={0}, currLineNum was {1}, new currLineNum={2}", e.RolloverOffset, dataGridView.CurrentCellAddress.Y, currentLineNum); firstDisplayedLine -= e.RolloverOffset; if (firstDisplayedLine < 0) { @@ -954,7 +954,7 @@ private void SetColumnizer (ILogLineColumnizer columnizer) private void SetColumnizerInternal (ILogLineColumnizer columnizer) { - _logger.Info("SetColumnizerInternal(): {0}", columnizer.GetName()); + _logger.Info(CultureInfo.InvariantCulture, "SetColumnizerInternal(): {0}", columnizer.GetName()); ILogLineColumnizer oldColumnizer = CurrentColumnizer; var oldColumnizerIsXmlType = CurrentColumnizer is ILogLineXmlColumnizer; @@ -1783,7 +1783,7 @@ private void StartEditMode () } else { - _logger.Warn("Edit control in logWindow was null"); + _logger.Warn(CultureInfo.InvariantCulture, "Edit control in logWindow was null"); } } } @@ -1797,7 +1797,7 @@ private void UpdateEditColumnDisplay (DataGridViewTextBoxEditingControl editCont { var pos = editControl.SelectionStart + editControl.SelectionLength; StatusLineText(" " + pos); - _logger.Debug("SelStart: {0}, SelLen: {1}", editControl.SelectionStart, editControl.SelectionLength); + _logger.Debug(CultureInfo.InvariantCulture, "SelStart: {0}, SelLen: {1}", editControl.SelectionStart, editControl.SelectionLength); } } @@ -2725,7 +2725,7 @@ private void WriteFilterToTab () [SupportedOSPlatform("windows")] private void WritePipeToTab (FilterPipe pipe, IList lineNumberList, string name, PersistenceData persistenceData) { - _logger.Info("WritePipeToTab(): {0} lines.", lineNumberList.Count); + _logger.Info(CultureInfo.InvariantCulture, "WritePipeToTab(): {0} lines.", lineNumberList.Count); StatusLineText("Writing to temp file... Press ESC to cancel."); _guiStateArgs.MenuEnabled = false; SendGuiStateUpdate(); @@ -2769,7 +2769,7 @@ private void WritePipeToTab (FilterPipe pipe, IList lineNumberList, string } pipe.CloseFile(); - _logger.Info("WritePipeToTab(): finished"); + _logger.Info(CultureInfo.InvariantCulture, "WritePipeToTab(): finished"); Invoke(new WriteFilterToTabFinishedFx(WriteFilterToTabFinished), pipe, name, persistenceData); } @@ -3168,7 +3168,7 @@ private void TestStatistic (PatternArgs patternArgs) PatternBlock block; var maxBlockLen = patternArgs.EndLine - patternArgs.StartLine; //int searchLine = i + 1; - _logger.Debug("TestStatistic(): i={0} searchLine={1}", i, searchLine); + _logger.Debug(CultureInfo.InvariantCulture, "TestStatistic(): i={0} searchLine={1}", i, searchLine); //bool firstBlock = true; searchLine++; UpdateProgressBar(searchLine); @@ -3178,7 +3178,7 @@ private void TestStatistic (PatternArgs patternArgs) _patternArgs.MaxMisses, processedLinesDict)) != null) { - _logger.Debug("Found block: {0}", block); + _logger.Debug(CultureInfo.InvariantCulture, "Found block: {0}", block); if (block.Weigth >= _patternArgs.MinWeight) { //PatternBlock existingBlock = FindExistingBlock(block, blockList); @@ -3224,7 +3224,7 @@ private void TestStatistic (PatternArgs patternArgs) // this.Invoke(new MethodInvoker(CreatePatternWindow)); //} _patternWindow.SetBlockList(blockList, _patternArgs); - _logger.Info("TestStatistics() ended"); + _logger.Info(CultureInfo.InvariantCulture, "TestStatistics() ended"); } private void AddBlockTargetLinesToDict (Dictionary dict, PatternBlock block) diff --git a/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs b/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs index 4a46be2a..68b4d258 100644 --- a/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs +++ b/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs @@ -1,4 +1,6 @@ -using LogExpert.Core.Callback; +using System.Globalization; + +using LogExpert.Core.Callback; using LogExpert.Core.Classes; using LogExpert.Core.Classes.Filter; using LogExpert.Core.Entities; @@ -29,12 +31,12 @@ public Range FindRange(int startLine) if (_filterParams.RangeSearchText == null || _filterParams.RangeSearchText.Trim().Length == 0) { - _logger.Info("Range search text not set. Cancelling range search."); + _logger.Info(CultureInfo.InvariantCulture, "Range search text not set. Cancelling range search."); return null; } if (_filterParams.SearchText == null || _filterParams.SearchText.Trim().Length == 0) { - _logger.Info("Search text not set. Cancelling range search."); + _logger.Info(CultureInfo.InvariantCulture, "Search text not set. Cancelling range search."); return null; } @@ -74,7 +76,7 @@ public Range FindRange(int startLine) if (!foundStartLine) { - _logger.Info("Range start not found"); + _logger.Info(CultureInfo.InvariantCulture, "Range start not found"); return null; } diff --git a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs index 58c71e58..791e6797 100644 --- a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs +++ b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs @@ -1,4 +1,4 @@ -using LogExpert.Core.Callback; +using LogExpert.Core.Callback; using LogExpert.Core.Classes; using LogExpert.Core.Interface; @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Threading; using System.Threading.Tasks; @@ -186,11 +187,11 @@ private void WorkerFx() while (!_shouldStop) { // wait for unbusy moments - _logger.Debug("TimeSpreadCalculator: wait for unbusy moments"); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator: wait for unbusy moments"); var signaled = _calcEvent.WaitOne(INACTIVITY_TIME, false); if (signaled == false) { - _logger.Debug("TimeSpreadCalculator: unbusy. starting calc."); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator: unbusy. starting calc."); if (TimeMode) { DoCalc_via_Time(); @@ -202,7 +203,7 @@ private void WorkerFx() break; } - _logger.Debug("TimeSpreadCalculator: signalled. no calc."); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator: signalled. no calc."); _calcEvent.Reset(); } _lineCountEvent.Reset(); @@ -212,12 +213,12 @@ private void WorkerFx() private void DoCalc() { OnStartCalc(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() begin"); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc() begin"); if (_callback.GetLineCount() < 1) { OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() end because of line count < 1"); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc() end because of line count < 1"); return; } @@ -245,7 +246,7 @@ private void DoCalc() step = 1; } - _logger.Debug("TimeSpreadCalculator.DoCalc() collecting data for {0} lines with step size {1}", lastLineNum, step); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc() collecting data for {0} lines with step size {1}", lastLineNum, step); List newDiffList = []; List maxList = []; @@ -262,7 +263,7 @@ private void DoCalc() timePerLineSum += (int)(span.Ticks / TimeSpan.TicksPerMillisecond); newDiffList.Add(new SpreadEntry(i, 0, time)); oldTime = time; - _logger.Debug("TimeSpreadCalculator.DoCalc() time diff {0}", span); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc() time diff {0}", span); } } @@ -278,7 +279,7 @@ private void DoCalc() _timePerLine = (int)Math.Round(timePerLineSum / ((double)(lastLineNum + 1) / step)); CalcValuesViaLines(_timePerLine, _maxSpan); OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() end"); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc() end"); } } } @@ -287,12 +288,12 @@ private void DoCalc() private void DoCalc_via_Time() { OnStartCalc(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() begin"); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc_via_Time() begin"); if (_callback.GetLineCount() < 1) { OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() end because of line count < 1"); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc() end because of line count < 1"); return; } @@ -318,7 +319,7 @@ private void DoCalc_via_Time() step = 1; } - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() time range is {0} ms", overallSpanMillis); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc_via_Time() time range is {0} ms", overallSpanMillis); lineNum = 0; DateTime searchTimeStamp = _startTimestamp; @@ -339,7 +340,7 @@ private void DoCalc_via_Time() } var lineDiff = lineNum - oldLineNum; - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() test time {0:HH:mm:ss.fff} line diff={1}", searchTimeStamp, lineDiff); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc_via_Time() test time {0:HH:mm:ss.fff} line diff={1}", searchTimeStamp, lineDiff); if (lineDiff >= 0) { @@ -372,7 +373,7 @@ private void DoCalc_via_Time() _average = lineDiffSum / (double)loopCount; //double average = maxList[maxList.Count / 2]; - _logger.Debug("Average diff={0} minDiff={1} maxDiff={2}", _average, minDiff, _maxDiff); + _logger.Debug(CultureInfo.InvariantCulture, "Average diff={0} minDiff={1} maxDiff={2}", _average, minDiff, _maxDiff); lock (_diffListLock) { @@ -389,7 +390,7 @@ private void DoCalc_via_Time() DiffList = newDiffList; CalcValuesViaTime(_maxDiff, _average); OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() end"); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc_via_Time() end"); } } } @@ -435,7 +436,7 @@ private void CalcValuesViaTime(int maxDiff, double average) var value = (int)(diffFromAverage / maxDiff * _contrast); entry.Value = 255 - value; - _logger.Debug("TimeSpreadCalculator.DoCalc() test time {0:HH:mm:ss.fff} line diff={1} value={2}", entry.Timestamp, lineDiff, value); + _logger.Debug(CultureInfo.InvariantCulture, "TimeSpreadCalculator.DoCalc() test time {0:HH:mm:ss.fff} line diff={1} value={2}", entry.Timestamp, lineDiff, value); } } diff --git a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs index 7aea14ed..d3c97f17 100644 --- a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs +++ b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Runtime.Versioning; using LogExpert.Core.Classes; @@ -146,7 +147,7 @@ private void OnLineSelected (SelectLineEventArgs e) private void TimeSpreadCalc_CalcDone (object sender, EventArgs e) { - _logger.Debug("timeSpreadCalc_CalcDone()"); + _logger.Debug(CultureInfo.InvariantCulture, "timeSpreadCalc_CalcDone()"); lock (_monitor) { diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs index 16e7ed7e..e8beed45 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using System.Diagnostics; +using System.Globalization; using System.Runtime.Versioning; using System.Text; @@ -516,7 +517,7 @@ private void OnLogWindowSyncModeChanged (object sender, SyncModeEventArgs e) } else { - _logger.Warn("Received SyncModeChanged event while disposing. Event ignored."); + _logger.Warn(CultureInfo.InvariantCulture, "Received SyncModeChanged event while disposing. Event ignored."); } } diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs index 3f91c8ca..648298ed 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using System.Diagnostics; +using System.Globalization; using System.Runtime.Versioning; using System.Security; using System.Text; @@ -140,7 +141,7 @@ private void FillDefaultEncodingFromSettings (EncodingOptions encodingOptions) } catch (ArgumentException) { - _logger.Warn("Encoding " + ConfigManager.Settings.Preferences.DefaultEncoding + " is not a valid encoding"); + _logger.Warn(CultureInfo.InvariantCulture, "Encoding " + ConfigManager.Settings.Preferences.DefaultEncoding + " is not a valid encoding"); encodingOptions.DefaultEncoding = null; } } @@ -968,7 +969,7 @@ private void OpenSettings (int tabToOpen) [SupportedOSPlatform("windows")] private void NotifyWindowsForChangedPrefs (SettingsFlags flags) { - _logger.Info("The preferences have changed"); + _logger.Info(CultureInfo.InvariantCulture, "The preferences have changed"); ApplySettings(ConfigManager.Settings, flags); var setLastColumnWidth = ConfigManager.Settings.Preferences.SetLastColumnWidth; @@ -1114,7 +1115,7 @@ private void StartTool (string cmd, string args, bool sysoutPipe, string columni { ILogLineColumnizer columnizer = ColumnizerPicker.DecideColumnizerByName(columnizerName, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - _logger.Info("Starting external tool with sysout redirection: {0} {1}", cmd, args); + _logger.Info(CultureInfo.InvariantCulture, "Starting external tool with sysout redirection: {0} {1}", cmd, args); startInfo.UseShellExecute = false; startInfo.RedirectStandardOutput = true; //process.OutputDataReceived += pipe.DataReceivedEventHandler; @@ -1142,7 +1143,7 @@ private void StartTool (string cmd, string args, bool sysoutPipe, string columni } else { - _logger.Info("Starting external tool: {0} {1}", cmd, args); + _logger.Info(CultureInfo.InvariantCulture, "Starting external tool: {0} {1}", cmd, args); try { @@ -1303,7 +1304,7 @@ private void DumpGCInfo () _logger.Info($"Generation {i} collect count: {GC.CollectionCount(i)}"); } - _logger.Info("----------------------------"); + _logger.Info(CultureInfo.InvariantCulture, "----------------------------"); } private void ThrowExceptionFx () diff --git a/src/LogExpert.UI/Entities/PaintHelper.cs b/src/LogExpert.UI/Entities/PaintHelper.cs index c1f9c9e5..3ba81155 100644 --- a/src/LogExpert.UI/Entities/PaintHelper.cs +++ b/src/LogExpert.UI/Entities/PaintHelper.cs @@ -12,16 +12,13 @@ namespace LogExpert.UI.Entities; //TOOD: This whole class should be refactored and rethought -//TODO: This class should not knoow ConfigManager? +//TODO: This class should not know ConfigManager? internal static class PaintHelper { #region Fields private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); - //TODO Make configurable - private static Color _bookmarkColor = Color.FromArgb(165, 200, 225); - #endregion #region Public methods diff --git a/src/LogExpert.UI/Extensions/BookmarkExporter.cs b/src/LogExpert.UI/Extensions/BookmarkExporter.cs index fbf2f660..70381f9a 100644 --- a/src/LogExpert.UI/Extensions/BookmarkExporter.cs +++ b/src/LogExpert.UI/Extensions/BookmarkExporter.cs @@ -12,9 +12,10 @@ internal static class BookmarkExporter #region Public methods - public static void ExportBookmarkList (SortedList bookmarkList, string logfileName, - string fileName) + //TOOD: check if the callers are checking for null before calling + public static void ExportBookmarkList (SortedList bookmarkList, string logfileName, string fileName) { + ArgumentNullException.ThrowIfNull(bookmarkList, nameof(bookmarkList)); FileStream fs = new(fileName, FileMode.Create, FileAccess.Write); StreamWriter writer = new(fs); writer.WriteLine("Log file name;Line number;Comment"); diff --git a/src/LogExpert/Classes/CommandLine/CmdLine.cs b/src/LogExpert/Classes/CommandLine/CmdLine.cs index 07155cb5..a269f214 100644 --- a/src/LogExpert/Classes/CommandLine/CmdLine.cs +++ b/src/LogExpert/Classes/CommandLine/CmdLine.cs @@ -10,16 +10,22 @@ namespace LogExpert.Classes.CommandLine; /// /// Represents an string command line parameter. /// -public class CmdLineString(string name, bool required, string helpMessage) : CmdLineParameter(name, required, helpMessage) +public class CmdLineString (string name, bool required, string helpMessage) : CmdLineParameter(name, required, helpMessage) { #region Public methods - public static implicit operator string(CmdLineString s) + public static implicit operator string (CmdLineString s) { + ArgumentNullException.ThrowIfNull(s, nameof(s)); return s.Value; } + public override string ToString () + { + return Value; + } + #endregion } diff --git a/src/LogExpert/Classes/LogExpertApplicationContext.cs b/src/LogExpert/Classes/LogExpertApplicationContext.cs index a078f898..1b3940bb 100644 --- a/src/LogExpert/Classes/LogExpertApplicationContext.cs +++ b/src/LogExpert/Classes/LogExpertApplicationContext.cs @@ -1,4 +1,4 @@ -using LogExpert.Core.Interface; +using LogExpert.Core.Interface; using System; using System.Windows.Forms; @@ -17,7 +17,7 @@ internal class LogExpertApplicationContext : ApplicationContext public LogExpertApplicationContext(LogExpertProxy proxy, ILogTabWindow firstLogWin) { _proxy = proxy; - _proxy.LastWindowClosed += new LogExpertProxy.LastWindowClosedEventHandler(OnProxyLastWindowClosed); + _proxy.LastWindowClosed += OnProxyLastWindowClosed; firstLogWin.Show(); } diff --git a/src/LogExpert/Classes/LogExpertProxy.cs b/src/LogExpert/Classes/LogExpertProxy.cs index d85448fb..558899ab 100644 --- a/src/LogExpert/Classes/LogExpertProxy.cs +++ b/src/LogExpert/Classes/LogExpertProxy.cs @@ -1,11 +1,15 @@ -using System.Windows.Forms; - using LogExpert.Config; using LogExpert.Core.Interface; +using LogExpert.UI.Controls.LogWindow; using LogExpert.UI.Extensions.LogWindow; using NLog; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Forms; + namespace LogExpert.Classes; internal class LogExpertProxy : ILogExpertProxy @@ -46,14 +50,11 @@ public LogExpertProxy(ILogTabWindow logTabWindow) // } //} - - public delegate void LastWindowClosedEventHandler(object sender, EventArgs e); - #endregion #region Events - public event LastWindowClosedEventHandler LastWindowClosed; + public event EventHandler LastWindowClosed; #endregion @@ -61,7 +62,7 @@ public LogExpertProxy(ILogTabWindow logTabWindow) public void LoadFiles(string[] fileNames) { - _logger.Info("Loading files into existing LogTabWindow"); + _logger.Info(CultureInfo.InvariantCulture, "Loading files into existing LogTabWindow"); ILogTabWindow logWin = _windowList[^1]; _ = logWin.Invoke(new MethodInvoker(logWin.SetForeground)); logWin.LoadFiles(fileNames); @@ -71,13 +72,13 @@ public void NewWindow(string[] fileNames) { if (_firstLogTabWindow.IsDisposed) { - _logger.Warn("first GUI thread window is disposed. Setting a new one."); + _logger.Warn(CultureInfo.InvariantCulture, "first GUI thread window is disposed. Setting a new one."); // may occur if a window is closed because of unhandled exception. // Determine a new 'firstWindow'. If no window is left, start a new one. RemoveWindow(_firstLogTabWindow); if (_windowList.Count == 0) { - _logger.Info("No windows left. New created window will be the new 'first' GUI window"); + _logger.Info(CultureInfo.InvariantCulture, "No windows left. New created window will be the new 'first' GUI window"); LoadFiles(fileNames); } else @@ -110,7 +111,7 @@ public void NewWindowOrLockedWindow(string[] fileNames) public void NewWindowWorker(string[] fileNames) { - _logger.Info("Creating new LogTabWindow"); + _logger.Info(CultureInfo.InvariantCulture, "Creating new LogTabWindow"); IConfigManager configManager = ConfigManager.Instance; ILogTabWindow logWin = AbstractLogTabWindow.Create(fileNames.Length > 0 ? fileNames : null, _logWindowIndex++, true, configManager); logWin.LogExpertProxy = this; @@ -125,7 +126,7 @@ public void WindowClosed(ILogTabWindow logWin) RemoveWindow(logWin); if (_windowList.Count == 0) { - _logger.Info("Last LogTabWindow was closed"); + _logger.Info(CultureInfo.InvariantCulture, "Last LogTabWindow was closed"); PluginRegistry.PluginRegistry.Instance.CleanupPlugins(); OnLastWindowClosed(); } @@ -155,13 +156,13 @@ public int GetLogWindowCount() private void AddWindow(ILogTabWindow window) { - _logger.Info("Adding window to list"); + _logger.Info(CultureInfo.InvariantCulture, "Adding window to list"); _windowList.Add(window); } private void RemoveWindow(ILogTabWindow window) { - _logger.Info("Removing window from list"); + _logger.Info(CultureInfo.InvariantCulture, "Removing window from list"); _ = _windowList.Remove(window); } diff --git a/src/LogExpert/Config/ConfigManager.cs b/src/LogExpert/Config/ConfigManager.cs index cae55ba6..23213246 100644 --- a/src/LogExpert/Config/ConfigManager.cs +++ b/src/LogExpert/Config/ConfigManager.cs @@ -1,4 +1,5 @@ using System.Drawing; +using System.Globalization; using System.Reflection; using System.Text; using System.Windows.Forms; @@ -8,7 +9,6 @@ using LogExpert.Core.Config; using LogExpert.Core.Entities; using LogExpert.Core.EventArguments; -using LogExpert.Core.EventHandlers; using LogExpert.Core.Interface; using Newtonsoft.Json; @@ -26,7 +26,6 @@ public class ConfigManager : IConfigManager private static readonly object _monitor = new(); private static ConfigManager _instance; private readonly object _loadSaveLock = new(); - private readonly object _saveSaveLock = new(); private Settings _settings; #endregion @@ -42,12 +41,13 @@ private ConfigManager () #region Events - public event ConfigChangedEventHandler ConfigChanged; + public event EventHandler ConfigChanged; #endregion #region Properties + //TODO: Change to init public static ConfigManager Instance { get @@ -117,13 +117,13 @@ public void ImportHighlightSettings (FileInfo fileInfo, ExportImportFlags flags) private Settings Load () { - _logger.Info("Loading settings"); + _logger.Info(CultureInfo.InvariantCulture, "Loading settings"); string dir; - - if (File.Exists(PortableModeDir + Path.DirectorySeparatorChar + PortableModeSettingsFileName) == false) + + if (!File.Exists(Path.Combine(PortableModeDir, PortableModeSettingsFileName))) { - _logger.Info("Load settings standard mode"); + _logger.Info(CultureInfo.InvariantCulture, "Load settings standard mode"); dir = ConfigDir; } else @@ -134,24 +134,33 @@ private Settings Load () if (!Directory.Exists(dir)) { - Directory.CreateDirectory(dir); + _ = Directory.CreateDirectory(dir); } - if (!File.Exists(dir + Path.DirectorySeparatorChar + "settings.json")) + if (!File.Exists(Path.Combine(dir, "settings.json"))) { return LoadOrCreateNew(null); } try { - FileInfo fileInfo = new(dir + Path.DirectorySeparatorChar + "settings.json"); + FileInfo fileInfo = new(Path.Combine(dir, "settings.json")); return LoadOrCreateNew(fileInfo); } - catch (Exception e) + catch (IOException ex) { - _logger.Error($"Error loading settings: {e}"); - return LoadOrCreateNew(null); + _logger.Error($"File system error: {ex.Message}"); } + catch (UnauthorizedAccessException ex) + { + _logger.Error($"Access denied: {ex.Message}"); + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + _logger.Error($"Unexpected error: {ex.Message}"); + } + + return LoadOrCreateNew(null); } @@ -269,7 +278,7 @@ private void Save (Settings settings, SettingsFlags flags) { lock (_loadSaveLock) { - _logger.Info("Saving settings"); + _logger.Info(CultureInfo.InvariantCulture, "Saving settings"); var dir = Settings.Preferences.PortableMode ? Application.StartupPath : ConfigDir; if (!Directory.Exists(dir)) @@ -359,8 +368,8 @@ private List Import (List currentGroups, FileInf /// Flags to indicate which parts shall be imported private Settings Import (Settings currentSettings, FileInfo fileInfo, ExportImportFlags flags) { - Settings importSettings = LoadOrCreateNew(fileInfo); - Settings ownSettings = ObjectClone.Clone(currentSettings); + var importSettings = LoadOrCreateNew(fileInfo); + var ownSettings = ObjectClone.Clone(currentSettings); Settings newSettings; // at first check for 'Other' as this are the most options. diff --git a/src/LogExpert/Program.cs b/src/LogExpert/Program.cs index cbfda99b..53d6678a 100644 --- a/src/LogExpert/Program.cs +++ b/src/LogExpert/Program.cs @@ -1,11 +1,3 @@ -using System.Diagnostics; -using System.IO.Pipes; -using System.Reflection; -using System.Security; -using System.Security.Principal; -using System.Text; -using System.Windows.Forms; - using LogExpert.Classes; using LogExpert.Classes.CommandLine; using LogExpert.Config; @@ -13,6 +5,7 @@ using LogExpert.Core.Config; using LogExpert.Core.Interface; using LogExpert.Dialogs; +using LogExpert.UI.Controls.LogWindow; using LogExpert.UI.Dialogs; using LogExpert.UI.Extensions.LogWindow; @@ -21,6 +14,15 @@ using NLog; +using System.Diagnostics; +using System.Globalization; +using System.IO.Pipes; +using System.Reflection; +using System.Security; +using System.Security.Principal; +using System.Text; +using System.Windows.Forms; + namespace LogExpert; internal static class Program @@ -39,7 +41,7 @@ internal static class Program /// The main entry point for the application. /// [STAThread] - private static void Main (string[] args) + private static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; Application.ThreadException += Application_ThreadException; @@ -49,7 +51,7 @@ private static void Main (string[] args) Application.EnableVisualStyles(); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); - _logger.Info($"\r\n============================================================================\r\nLogExpert {Assembly.GetExecutingAssembly().GetName().Version.ToString(3)} started.\r\n============================================================================"); + _logger.Info(CultureInfo.InvariantCulture, $"\r\n============================================================================\r\nLogExpert {Assembly.GetExecutingAssembly().GetName().Version.ToString(3)} started.\r\n============================================================================"); CancellationTokenSource cts = new(); try @@ -86,7 +88,7 @@ private static void Main (string[] args) // first application instance Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - ILogTabWindow logWin = AbstractLogTabWindow.Create(absoluteFilePaths.Length > 0 ? absoluteFilePaths : null, 1, false, ConfigManager.Instance); + var logWin = AbstractLogTabWindow.Create(absoluteFilePaths.Length > 0 ? absoluteFilePaths : null, 1, false, ConfigManager.Instance); // first instance var wi = WindowsIdentity.GetCurrent(); @@ -156,7 +158,7 @@ private static void Main (string[] args) } } - private static string SerializeCommandIntoNonFormattedJSON (string[] fileNames, bool allowOnlyOneInstance) + private static string SerializeCommandIntoNonFormattedJSON(string[] fileNames, bool allowOnlyOneInstance) { var message = new IpcMessage() { @@ -170,7 +172,7 @@ private static string SerializeCommandIntoNonFormattedJSON (string[] fileNames, // This loop tries to convert relative file names into absolute file names (assuming that platform file names are given). // It tolerates errors, to give file system plugins (e.g. sftp) a change later. // TODO: possibly should be moved to LocalFileSystem plugin - private static string[] GenerateAbsoluteFilePaths (string[] remainingArgs) + private static string[] GenerateAbsoluteFilePaths(string[] remainingArgs) { List argsList = []; @@ -190,44 +192,27 @@ private static string[] GenerateAbsoluteFilePaths (string[] remainingArgs) return [.. argsList]; } - private static void SendMessageToProxy (IpcMessage message, LogExpertProxy proxy) + private static void SendMessageToProxy(IpcMessage message, LogExpertProxy proxy) { - switch (message.Type) - { - case IpcMessageType.Load: - { - LoadPayload payLoad = message.Payload.ToObject(); + var payLoad = message.Payload.ToObject(); - if (CheckPayload(payLoad)) - { - proxy.LoadFiles([.. payLoad.Files]); - } - } - - break; - case IpcMessageType.NewWindow: - { - LoadPayload payLoad = message.Payload.ToObject(); - if (CheckPayload(payLoad)) - { - proxy.NewWindow([.. payLoad.Files]); - } - } - - break; - case IpcMessageType.NewWindowOrLockedWindow: - { - LoadPayload payLoad = message.Payload.ToObject(); - if (CheckPayload(payLoad)) - { - proxy.NewWindowOrLockedWindow([.. payLoad.Files]); - } - } - - break; - default: - _logger.Error($"Unknown IPC Message Type {message.Type}"); - break; + if (CheckPayload(payLoad)) + { + switch (message.Type) + { + case IpcMessageType.Load: + proxy.LoadFiles([.. payLoad.Files]); + break; + case IpcMessageType.NewWindow: + proxy.NewWindow([.. payLoad.Files]); + break; + case IpcMessageType.NewWindowOrLockedWindow: + proxy.NewWindowOrLockedWindow([.. payLoad.Files]); + break; + default: + _logger.Error($"Unknown IPC Message Type: {message.Type}; with payload: {payLoad}"); + break; + } } } @@ -235,14 +220,14 @@ private static bool CheckPayload (LoadPayload payLoad) { if (payLoad == null) { - _logger.Error("Invalid payload for NewWindow command"); + _logger.Error("Invalid payload command: null"); return false; } return true; } - private static void SendCommandToServer (string command) + private static void SendCommandToServer(string command) { using var client = new NamedPipeClientStream(".", PIPE_SERVER_NAME, PipeDirection.Out); @@ -270,7 +255,7 @@ private static void SendCommandToServer (string command) writer.WriteLine(command); } - private static async Task RunServerLoopAsync (Action onCommand, LogExpertProxy proxy, CancellationToken cancellationToken) + private static async Task RunServerLoopAsync(Action onCommand, LogExpertProxy proxy, CancellationToken cancellationToken) { while (cancellationToken.IsCancellationRequested == false) { @@ -305,7 +290,7 @@ private static async Task RunServerLoopAsync (Action } [STAThread] - private static void ShowUnhandledException (object exceptionObject) + private static void ShowUnhandledException(object exceptionObject) { var errorText = string.Empty; string stackTrace; @@ -334,7 +319,7 @@ private static void ShowUnhandledException (object exceptionObject) #region Events handler - private static void Application_ThreadException (object sender, ThreadExceptionEventArgs e) + private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { _logger.Fatal(e); @@ -348,7 +333,7 @@ private static void Application_ThreadException (object sender, ThreadExceptionE thread.Join(); } - private static void CurrentDomain_UnhandledException (object sender, UnhandledExceptionEventArgs e) + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { _logger.Fatal(e); diff --git a/src/PluginRegistry/PluginRegistry.cs b/src/PluginRegistry/PluginRegistry.cs index 24547ff6..0b7a339b 100644 --- a/src/PluginRegistry/PluginRegistry.cs +++ b/src/PluginRegistry/PluginRegistry.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Reflection; using LogExpert.Core.Classes; @@ -87,7 +88,7 @@ public PluginRegistry Create (string applicationConfigurationFolder, int polling internal void LoadPlugins () { - _logger.Info("Loading plugins..."); + _logger.Info(CultureInfo.InvariantCulture, "Loading plugins..."); RegisteredColumnizers = [ @@ -143,7 +144,7 @@ internal void LoadPlugins () } } - _logger.Info("Plugin loading complete."); + _logger.Info(CultureInfo.InvariantCulture, "Plugin loading complete."); } private void LoadPluginAssembly (string dllName, string interfaceName) @@ -215,21 +216,21 @@ public IFileSystemPlugin FindFileSystemForUri (string uriString) { if (_logger.IsDebugEnabled) { - _logger.Debug("Trying to find file system plugin for uri {0}", uriString); + _logger.Debug(CultureInfo.InvariantCulture, "Trying to find file system plugin for uri {0}", uriString); } foreach (IFileSystemPlugin fs in RegisteredFileSystemPlugins) { if (_logger.IsDebugEnabled) { - _logger.Debug("Checking {0}", fs.Text); + _logger.Debug(CultureInfo.InvariantCulture, "Checking {0}", fs.Text); } if (fs.CanHandleUri(uriString)) { if (_logger.IsDebugEnabled) { - _logger.Debug("Found match {0}", fs.Text); + _logger.Debug(CultureInfo.InvariantCulture, "Found match {0}", fs.Text); } return fs; @@ -262,7 +263,7 @@ private bool TryAsContextMenu (Type type) plugin.PluginLoaded(); } - _logger.Info("Added context menu plugin {0}", type); + _logger.Info(CultureInfo.InvariantCulture, "Added context menu plugin {0}", type); return true; } @@ -288,7 +289,7 @@ private bool TryAsKeywordAction (Type type) plugin.PluginLoaded(); } - _logger.Info("Added keyword plugin {0}", type); + _logger.Info(CultureInfo.InvariantCulture, "Added keyword plugin {0}", type); return true; } @@ -317,7 +318,7 @@ private bool TryAsFileSystem (Type type) plugin.PluginLoaded(); } - _logger.Info("Added file system plugin {0}", type); + _logger.Info(CultureInfo.InvariantCulture, "Added file system plugin {0}", type); return true; } diff --git a/src/SftpFileSystemx64/SftpFileSystem.cs b/src/SftpFileSystemx64/SftpFileSystem.cs index bdc86465..4d43af87 100644 --- a/src/SftpFileSystemx64/SftpFileSystem.cs +++ b/src/SftpFileSystemx64/SftpFileSystem.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Windows.Forms; using System.Xml.Serialization; @@ -106,7 +107,7 @@ public void LoadConfig (string configDir) public void SaveConfig (string configDir) { - _logger.Info("Saving SFTP config"); + _logger.Info(CultureInfo.InvariantCulture, "Saving SFTP config"); XmlSerializer xml = new(ConfigData.GetType()); FileStream fs = null;