| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 | using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;using System.IO;using System.Text.RegularExpressions;using System.Threading.Tasks;using System.Timers;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Input;using System.Windows.Media;using System.Windows.Threading;using H.Pipes;using InABox.Logging;using InABox.Wpf;using Microsoft.Win32;namespace PRSServer{    public static class ItemsControlExtensions    {        public static void ScrollIntoView(            this ItemsControl control,            object item)        {            var framework =                control.ItemContainerGenerator.ContainerFromItem(item)                    as FrameworkElement;            if (framework == null) return;            framework.BringIntoView();        }        public static void ScrollIntoView(this ItemsControl control)        {            var count = control.Items.Count;            if (count == 0) return;            var item = control.Items[count - 1];            control.ScrollIntoView(item);        }    }    /// <summary>    ///     Interaction logic for Console.xaml    /// </summary>    public partial class Console : ThemableWindow    {        private PipeClient<string> _client;        public CollectionViewSource _filtered;        private readonly ObservableCollection<LogEntry> _logentries;        private readonly bool _monitoronly = true;        private PRSService _service;        public string ServiceName { get; private set; }        private readonly string description;        private readonly TimeSpan regexTimeOut = TimeSpan.FromMilliseconds(100);        private Timer? RefreshTimer;        private Regex? searchRegex;        public Console(string servicename, string description, bool monitoronly = true)        {            ServiceName = servicename;            _monitoronly = monitoronly;            InitializeComponent();            _logentries = new ObservableCollection<LogEntry>();            _filtered = new CollectionViewSource();            _filtered.Source = _logentries;            _filtered.Filter += (sender, args) =>            {                var logEntry = (LogEntry)args.Item;                if (ShowImportant.IsChecked == true && !IsImportant(logEntry))                {                    args.Accepted = false;                    return;                }                if (UseRegEx.IsChecked == true && searchRegex != null)                    args.Accepted = string.IsNullOrWhiteSpace(Search.Text)                                    || searchRegex.IsMatch(logEntry.DateTime)                                    || searchRegex.IsMatch(logEntry.Type)                                    || searchRegex.IsMatch(logEntry.User)                                    || searchRegex.IsMatch(logEntry.Message);                else                    args.Accepted = string.IsNullOrWhiteSpace(Search.Text)                                    || logEntry.DateTime.Contains(Search.Text)                                    || logEntry.Type.Contains(Search.Text)                                    || logEntry.User.Contains(Search.Text)                                    || logEntry.Message.Contains(Search.Text);            };            DataContext = _filtered;            Title = description;            this.description = description;        }        private bool IsImportant(LogEntry entry)        {            return entry.Type == "IMPTNT";        }        private LogEntry ParseLogMessage(string logLine)        {            var datetime = logLine.Length > 32 ? logLine.Substring(0, 12) : string.Format("{0:HH:mm:ss.fff}", DateTime.Now);            var type = logLine.Length > 32 ? logLine.Substring(13, 6).Trim() : "INFO";            var user = logLine.Length > 32 ? logLine.Substring(20, 12) : "";            var msg = logLine.Length > 32 ? logLine.Substring(33) : logLine;            return new LogEntry            {                DateTime = datetime,                Type = type,                User = user,                Message = msg            };        }        private void Console_Loaded(object sender, RoutedEventArgs e)        {            _client = new PipeClient<string>(ServiceName,".");            _client.MessageReceived += (o, args) =>            {                var m = args.Message;                var logEntry = ParseLogMessage(args.Message ?? "");                var logType = logEntry.Type;                if (logType == "INFO" || logType == "ERROR" || logType == "IMPTNT")                    Dispatcher.BeginInvoke((Action)(() => { _logentries.Insert(0, logEntry); }));            };            _client.Connected += (o, args) =>            {                Dispatcher.Invoke(() => LogBorder.Background = new SolidColorBrush(Colors.LightYellow));            };            _client.Disconnected += (o, args) =>            {                Dispatcher.Invoke(() => LogBorder.Background = new SolidColorBrush(Colors.WhiteSmoke));                if (RefreshTimer == null)                {                    RefreshTimer = new Timer(1000);                    RefreshTimer.Elapsed += RefreshTimer_Elapsed;                }                RefreshTimer.Start();            };            _client.ExceptionOccurred += (o, args) =>            {                            };            if (!_client.IsConnecting)            {                _client.ConnectAsync();            }            if (!_monitoronly)            {                var timer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 3) };                timer.Tick += (o, args) =>                {                    timer.IsEnabled = false;                    _service = new PRSService(ServiceName, null);                    _service.Run(ServiceName);                };                timer.IsEnabled = true;            }        }        private void RefreshTimer_Elapsed(object? sender, ElapsedEventArgs e)        {            if(!_client.IsConnected)            {                if (!_client.IsConnecting)                {                    _client.ConnectAsync();                }            }            else            {                RefreshTimer?.Stop();            }        }        private void Window_Closing(object sender, CancelEventArgs e)        {            if (_monitoronly)            {                _client.DisposeAsync().AsTask().Wait();                RefreshTimer?.Stop();            }            else                _service?.Halt();        }        private void Search_KeyDown(object sender, KeyEventArgs e)        {            if (e.Key == Key.Enter && UseRegEx.IsChecked == true)            {                try                {                    searchRegex = new Regex(Search.Text, RegexOptions.Compiled, regexTimeOut);                }                catch (ArgumentException ex)                {                    searchRegex = null;                }                _filtered.View.Refresh();                SetSearchStyleNormal();            }        }        private void SetSearchStyleChanged()        {            Search.Background = Brushes.White;        }        private void SetSearchStyleNormal()        {            Search.Background = Brushes.LightYellow;        }        private void Search_TextChanged(object sender, TextChangedEventArgs e)        {            if (UseRegEx.IsChecked != true)            {                _filtered.View.Refresh();            }            else            {                if (string.IsNullOrWhiteSpace(Search.Text))                {                    searchRegex = null;                    _filtered.View.Refresh();                    SetSearchStyleNormal();                }                else                {                    SetSearchStyleChanged();                }            }        }        private void UseRegEx_Checked(object sender, RoutedEventArgs e)        {            try            {                searchRegex = new Regex(Search.Text, RegexOptions.Compiled, regexTimeOut);            }            catch (ArgumentException ex)            {                searchRegex = null;            }            _filtered.View.Refresh();        }        private void UseRegEx_Unchecked(object sender, RoutedEventArgs e)        {            searchRegex = null;            _filtered.View.Refresh();            SetSearchStyleNormal();        }        private void SetErrorMessage(string? error)        {            if (string.IsNullOrWhiteSpace(error))            {                Error.Content = "";                Error.Visibility = Visibility.Collapsed;            }            else            {                Error.Content = error;                Error.Visibility = Visibility.Visible;            }        }        private void LoadLog_Click(object sender, RoutedEventArgs e)        {            var dialog = new OpenFileDialog();            dialog.InitialDirectory = DatabaseEngine.GetPath(ServiceName);            if (dialog.ShowDialog() == true)            {                var logEntries = new List<LogEntry>();                var numberSkipped = 0;                var lines = File.ReadLines(dialog.FileName);                foreach (var line in lines)                {                    var logEntry = ParseLogMessage(line ?? "");                    var logType = logEntry.Type;                    if (logType == "ERROR" || logType == "INFO" || logType == "IMPTNT")                        logEntries.Add(logEntry);                    else if (string.IsNullOrWhiteSpace(logType)) numberSkipped++;                }                if (numberSkipped > 0)                {                    if (logEntries.Count == 0)                        SetErrorMessage("File does not contain valid log information!");                    else                        SetErrorMessage(string.Format("Skipped {0} lines that did not contain valid log information", numberSkipped));                }                Title = dialog.FileName;                _filtered.Source = logEntries;                LoadLog.Visibility = Visibility.Collapsed;                CloseLog.Visibility = Visibility.Visible;            }        }        private void CloseLog_Click(object sender, RoutedEventArgs e)        {            _filtered.Source = _logentries;            CloseLog.Visibility = Visibility.Collapsed;            LoadLog.Visibility = Visibility.Visible;            Title = description;        }        private void ShowImportant_Checked(object sender, RoutedEventArgs e)        {            _filtered.View.Refresh();        }        private void ShowImportant_Unchecked(object sender, RoutedEventArgs e)        {            _filtered.View.Refresh();        }    }}
 |