diff --git a/AppDiagnostic.Logging/AppDiagnostic.Logging.csproj b/AppDiagnostic.Logging/AppDiagnostic.Logging.csproj new file mode 100644 index 000000000..ae4c61c62 --- /dev/null +++ b/AppDiagnostic.Logging/AppDiagnostic.Logging.csproj @@ -0,0 +1,17 @@ + + + + net472 + 7.3 + AppDiagnostic.Logging + AppDiagnostic.Logging + true + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC} + + + + + + + + diff --git a/AppDiagnostic.Logging/AppDiagnosticConnector.cs b/AppDiagnostic.Logging/AppDiagnosticConnector.cs new file mode 100644 index 000000000..0af3396cd --- /dev/null +++ b/AppDiagnostic.Logging/AppDiagnosticConnector.cs @@ -0,0 +1,41 @@ +using NLog; +using NLog.Config; +using NLog.Layouts; + +namespace AppDiagnostic.Logging +{ + public static class AppDiagnosticConnector + { + private static readonly object syncRoot = new object(); + + public static void Register() + { + lock (syncRoot) + { + LoggingConfiguration configuration = LogManager.Configuration ?? new LoggingConfiguration(); + NLog.Targets.Target existingTarget = configuration.FindTargetByName("appDiagnostic"); + + if (existingTarget != null) + { + return; + } + + var target = new AppDiagnosticTarget + { + Name = "appDiagnostic", + PipeName = DiagnosticProtocol.DefaultPipeName, + QueueLimit = DiagnosticProtocol.DefaultQueueLimit, + ReconnectDelayMilliseconds = DiagnosticProtocol.DefaultReconnectDelayMilliseconds, + ConnectTimeoutMilliseconds = DiagnosticProtocol.DefaultConnectTimeoutMilliseconds, + Layout = new SimpleLayout("${message}") + }; + + configuration.AddTarget(target.Name, target); + configuration.AddRule(LogLevel.Trace, LogLevel.Fatal, target, "*"); + + LogManager.Configuration = configuration; + LogManager.ReconfigExistingLoggers(); + } + } + } +} \ No newline at end of file diff --git a/AppDiagnostic.Logging/AppDiagnosticTarget.cs b/AppDiagnostic.Logging/AppDiagnosticTarget.cs new file mode 100644 index 000000000..9136a09f0 --- /dev/null +++ b/AppDiagnostic.Logging/AppDiagnosticTarget.cs @@ -0,0 +1,233 @@ +using NLog; +using NLog.Targets; +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.IO.Pipes; +using System.Threading; +using System.Threading.Tasks; + +namespace AppDiagnostic.Logging +{ + [Target("AppDiagnostic")] + public sealed class AppDiagnosticTarget : TargetWithLayout + { + private readonly object connectionLock = new object(); + private readonly string applicationName; + private readonly int processId; + + private BlockingCollection queue; + private CancellationTokenSource cancellation; + private Task senderTask; + private NamedPipeClientStream pipeClient; + + public AppDiagnosticTarget() + { + using (Process process = Process.GetCurrentProcess()) + { + applicationName = process.ProcessName; + processId = process.Id; + } + + PipeName = DiagnosticProtocol.DefaultPipeName; + QueueLimit = DiagnosticProtocol.DefaultQueueLimit; + ReconnectDelayMilliseconds = + DiagnosticProtocol.DefaultReconnectDelayMilliseconds; + ConnectTimeoutMilliseconds = + DiagnosticProtocol.DefaultConnectTimeoutMilliseconds; + } + + public string PipeName { get; set; } + + public int QueueLimit { get; set; } + + public int ReconnectDelayMilliseconds { get; set; } + + public int ConnectTimeoutMilliseconds { get; set; } + + protected override void InitializeTarget() + { + base.InitializeTarget(); + + int queueLimit = QueueLimit > 0 + ? QueueLimit + : DiagnosticProtocol.DefaultQueueLimit; + + queue = new BlockingCollection(queueLimit); + cancellation = new CancellationTokenSource(); + + senderTask = Task.Factory.StartNew( + ProcessQueue, + cancellation.Token, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + } + + protected override void Write(LogEventInfo logEvent) + { + if (logEvent == null || queue == null || queue.IsAddingCompleted) + { + return; + } + + var entry = new DiagnosticLogEntry + { + TimestampUtc = logEvent.TimeStamp.ToUniversalTime(), + MachineName = Environment.MachineName, + ApplicationName = applicationName, + ProcessId = processId, + LoggerName = logEvent.LoggerName ?? string.Empty, + Level = logEvent.Level?.Name ?? string.Empty, + Message = Layout != null + ? Layout.Render(logEvent) + : logEvent.FormattedMessage, + Exception = logEvent.Exception?.ToString() ?? string.Empty + }; + + try + { + queue.TryAdd(entry); + } + catch (ObjectDisposedException) + { + // A concurrent NLog shutdown may dispose the queue. + } + catch (InvalidOperationException) + { + // A concurrent NLog shutdown may complete the queue. + } + } + + protected override void CloseTarget() + { + BlockingCollection currentQueue = queue; + CancellationTokenSource currentCancellation = cancellation; + + if (currentQueue != null) + { + currentQueue.CompleteAdding(); + } + + if (currentCancellation != null) + { + currentCancellation.Cancel(); + } + + CloseConnection(); + + try + { + senderTask?.Wait(2000); + } + catch (AggregateException) + { + // Cancellation during application shutdown is expected. + } + + currentQueue?.Dispose(); + currentCancellation?.Dispose(); + + queue = null; + cancellation = null; + senderTask = null; + + base.CloseTarget(); + } + + private void ProcessQueue() + { + CancellationToken token = cancellation.Token; + + try + { + foreach (DiagnosticLogEntry entry in + queue.GetConsumingEnumerable(token)) + { + SendWhenConnected(entry, token); + } + } + catch (OperationCanceledException) + { + // Target shutdown is expected to cancel the sender. + } + } + + private void SendWhenConnected( + DiagnosticLogEntry entry, + CancellationToken token) + { + while (!token.IsCancellationRequested) + { + try + { + EnsureConnected(); + DiagnosticMessageSerializer.WriteFramed(pipeClient, entry); + return; + } + catch (Exception exception) when ( + exception is IOException || + exception is TimeoutException || + exception is InvalidOperationException) + { + CloseConnection(); + + int delay = ReconnectDelayMilliseconds > 0 + ? ReconnectDelayMilliseconds + : DiagnosticProtocol.DefaultReconnectDelayMilliseconds; + + if (token.WaitHandle.WaitOne(delay)) + { + return; + } + } + } + } + + private void EnsureConnected() + { + lock (connectionLock) + { + if (pipeClient != null && pipeClient.IsConnected) + { + return; + } + + CloseConnectionWithoutLock(); + + pipeClient = new NamedPipeClientStream( + ".", + string.IsNullOrWhiteSpace(PipeName) + ? DiagnosticProtocol.DefaultPipeName + : PipeName, + PipeDirection.Out, + PipeOptions.Asynchronous); + + int timeout = ConnectTimeoutMilliseconds > 0 + ? ConnectTimeoutMilliseconds + : DiagnosticProtocol.DefaultConnectTimeoutMilliseconds; + + pipeClient.Connect(timeout); + } + } + + private void CloseConnection() + { + lock (connectionLock) + { + CloseConnectionWithoutLock(); + } + } + + private void CloseConnectionWithoutLock() + { + if (pipeClient == null) + { + return; + } + + pipeClient.Dispose(); + pipeClient = null; + } + } +} diff --git a/AppDiagnostic.Logging/DiagnosticLogEntry.cs b/AppDiagnostic.Logging/DiagnosticLogEntry.cs new file mode 100644 index 000000000..517670cb1 --- /dev/null +++ b/AppDiagnostic.Logging/DiagnosticLogEntry.cs @@ -0,0 +1,33 @@ +using System; +using System.Runtime.Serialization; + +namespace AppDiagnostic.Logging +{ + [DataContract] + public sealed class DiagnosticLogEntry + { + [DataMember(Order = 1)] + public DateTime TimestampUtc { get; set; } + + [DataMember(Order = 2)] + public string MachineName { get; set; } + + [DataMember(Order = 3)] + public string ApplicationName { get; set; } + + [DataMember(Order = 4)] + public int ProcessId { get; set; } + + [DataMember(Order = 5)] + public string LoggerName { get; set; } + + [DataMember(Order = 6)] + public string Level { get; set; } + + [DataMember(Order = 7)] + public string Message { get; set; } + + [DataMember(Order = 8)] + public string Exception { get; set; } + } +} diff --git a/AppDiagnostic.Logging/DiagnosticMessageSerializer.cs b/AppDiagnostic.Logging/DiagnosticMessageSerializer.cs new file mode 100644 index 000000000..a4fb35595 --- /dev/null +++ b/AppDiagnostic.Logging/DiagnosticMessageSerializer.cs @@ -0,0 +1,113 @@ +using System; +using System.IO; +using System.Runtime.Serialization.Json; + +namespace AppDiagnostic.Logging +{ + public static class DiagnosticMessageSerializer + { + private static readonly DataContractJsonSerializer Serializer = + new DataContractJsonSerializer(typeof(DiagnosticLogEntry)); + + private static readonly object SerializerLock = new object(); + + public static byte[] Serialize(DiagnosticLogEntry entry) + { + if (entry == null) + { + throw new ArgumentNullException(nameof(entry)); + } + + using (var stream = new MemoryStream()) + { + lock (SerializerLock) + { + Serializer.WriteObject(stream, entry); + } + + return stream.ToArray(); + } + } + + public static DiagnosticLogEntry Deserialize(byte[] payload) + { + if (payload == null) + { + throw new ArgumentNullException(nameof(payload)); + } + + if (payload.Length == 0 || + payload.Length > DiagnosticProtocol.MaximumMessageSize) + { + throw new InvalidDataException("Invalid diagnostic message size."); + } + + using (var stream = new MemoryStream(payload, false)) + { + lock (SerializerLock) + { + return (DiagnosticLogEntry)Serializer.ReadObject(stream); + } + } + } + + public static void WriteFramed(Stream stream, DiagnosticLogEntry entry) + { + if (stream == null) + { + throw new ArgumentNullException(nameof(stream)); + } + + byte[] payload = Serialize(entry); + + if (payload.Length > DiagnosticProtocol.MaximumMessageSize) + { + throw new InvalidDataException("Diagnostic message is too large."); + } + + byte[] length = BitConverter.GetBytes(payload.Length); + stream.Write(length, 0, length.Length); + stream.Write(payload, 0, payload.Length); + stream.Flush(); + } + + public static DiagnosticLogEntry ReadFramed(Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException(nameof(stream)); + } + + byte[] lengthBuffer = ReadExactly(stream, sizeof(int)); + int payloadLength = BitConverter.ToInt32(lengthBuffer, 0); + + if (payloadLength <= 0 || + payloadLength > DiagnosticProtocol.MaximumMessageSize) + { + throw new InvalidDataException("Invalid diagnostic message size."); + } + + return Deserialize(ReadExactly(stream, payloadLength)); + } + + private static byte[] ReadExactly(Stream stream, int count) + { + byte[] buffer = new byte[count]; + int offset = 0; + + while (offset < count) + { + int bytesRead = stream.Read(buffer, offset, count - offset); + + if (bytesRead == 0) + { + throw new EndOfStreamException(); + } + + offset += bytesRead; + } + + return buffer; + } + } +} diff --git a/AppDiagnostic.Logging/DiagnosticProtocol.cs b/AppDiagnostic.Logging/DiagnosticProtocol.cs new file mode 100644 index 000000000..fc4be8e62 --- /dev/null +++ b/AppDiagnostic.Logging/DiagnosticProtocol.cs @@ -0,0 +1,11 @@ +namespace AppDiagnostic.Logging +{ + public static class DiagnosticProtocol + { + public const string DefaultPipeName = "Sensus.AppDiagnostic.LogPipe"; + public const int MaximumMessageSize = 1024 * 1024; + public const int DefaultQueueLimit = 10000; + public const int DefaultReconnectDelayMilliseconds = 500; + public const int DefaultConnectTimeoutMilliseconds = 250; + } +} diff --git a/AppDiagnostic.Logging/README.md b/AppDiagnostic.Logging/README.md new file mode 100644 index 000000000..4c381ac38 --- /dev/null +++ b/AppDiagnostic.Logging/README.md @@ -0,0 +1,37 @@ +# AppDiagnostic.Logging + +Reusable NLog target for sending structured diagnostic events from multiple +.NET Framework processes to `AppDiagnostic.exe` through a local named pipe. + +## Producer integration + +Reference this project from the producer application and add the extension and +target to its NLog configuration: + +```xml + + + + + + + + + + + +``` + +The target writes to a bounded background queue. Producer threads are not +blocked while the diagnostic viewer is unavailable. Queued messages are sent +after the viewer becomes available; new messages are discarded when the queue +limit is reached. + +The receiver can read messages with: + +```csharp +DiagnosticLogEntry entry = + DiagnosticMessageSerializer.ReadFramed(namedPipeServerStream); +``` diff --git a/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.dll b/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.dll new file mode 100644 index 000000000..fa3b3ef1c Binary files /dev/null and b/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.dll differ diff --git a/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.pdb b/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.pdb new file mode 100644 index 000000000..c8da8e1d1 Binary files /dev/null and b/AppDiagnostic.Logging/bin/Debug/net472/AppDiagnostic.Logging.pdb differ diff --git a/AppDiagnostic.Logging/bin/Debug/net472/NLog.dll b/AppDiagnostic.Logging/bin/Debug/net472/NLog.dll new file mode 100644 index 000000000..d519ffc52 Binary files /dev/null and b/AppDiagnostic.Logging/bin/Debug/net472/NLog.dll differ diff --git a/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.dll b/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.dll new file mode 100644 index 000000000..92ba99691 Binary files /dev/null and b/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.dll differ diff --git a/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.pdb b/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.pdb new file mode 100644 index 000000000..20f7774dc Binary files /dev/null and b/AppDiagnostic.Logging/bin/Release/net472/AppDiagnostic.Logging.pdb differ diff --git a/AppDiagnostic.Logging/bin/Release/net472/NLog.dll b/AppDiagnostic.Logging/bin/Release/net472/NLog.dll new file mode 100644 index 000000000..d519ffc52 Binary files /dev/null and b/AppDiagnostic.Logging/bin/Release/net472/NLog.dll differ diff --git a/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.dgspec.json b/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.dgspec.json new file mode 100644 index 000000000..1cec92f33 --- /dev/null +++ b/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.dgspec.json @@ -0,0 +1,65 @@ +{ + "format": 1, + "restore": { + "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj": {} + }, + "projects": { + "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj", + "projectName": "AppDiagnostic.Logging", + "projectPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj", + "packagesPath": "C:\\Users\\MFRNIAK\\.nuget\\packages\\", + "outputPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\MFRNIAK\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net472" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net472": { + "framework": "net472", + "targetAlias": "net472", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "10.0.300" + }, + "frameworks": { + "net472": { + "framework": "net472", + "targetAlias": "net472", + "dependencies": { + "NLog": { + "target": "Package", + "version": "[5.2.2, )" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.303\\RuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.g.props b/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.g.props new file mode 100644 index 000000000..4d5b22437 --- /dev/null +++ b/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.g.props @@ -0,0 +1,16 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\MFRNIAK\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages + PackageReference + 7.0.0 + + + + + + \ No newline at end of file diff --git a/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.g.targets b/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.g.targets new file mode 100644 index 000000000..3dc06ef3c --- /dev/null +++ b/AppDiagnostic.Logging/obj/AppDiagnostic.Logging.csproj.nuget.g.targets @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/AppDiagnostic.Logging/obj/Debug/net472/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/AppDiagnostic.Logging/obj/Debug/net472/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs new file mode 100644 index 000000000..3871b184d --- /dev/null +++ b/AppDiagnostic.Logging/obj/Debug/net472/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagn.CFEA7AC0.Up2Date b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagn.CFEA7AC0.Up2Date new file mode 100644 index 000000000..e69de29bb diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfo.cs b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfo.cs new file mode 100644 index 000000000..a84dbdace --- /dev/null +++ b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("AppDiagnostic.Logging")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1c6f9af2bb6c7dd588e6f0dab0a2836e409c1f93")] +[assembly: System.Reflection.AssemblyProductAttribute("AppDiagnostic.Logging")] +[assembly: System.Reflection.AssemblyTitleAttribute("AppDiagnostic.Logging")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache new file mode 100644 index 000000000..af44c1565 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +328a35425ad6c5261737a98c855c6d7f7d872650a791c2ad21ac4020a96108d0 diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 000000000..9cac7ed56 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,8 @@ +is_global = true +build_property.RootNamespace = AppDiagnostic.Logging +build_property.ProjectDir = C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.CsWinRTUseWindowsUIXamlProjections = false +build_property.EffectiveAnalysisLevelStyle = +build_property.EnableCodeStyleSeverity = diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.assets.cache b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.assets.cache new file mode 100644 index 000000000..7bccc9da2 Binary files /dev/null and b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.assets.cache differ diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache new file mode 100644 index 000000000..6aed440a2 Binary files /dev/null and b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache differ diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.BuildWithSkipAnalyzers b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.BuildWithSkipAnalyzers new file mode 100644 index 000000000..e69de29bb diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.CoreCompileInputs.cache b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.CoreCompileInputs.cache new file mode 100644 index 000000000..eb05a3936 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +551ba94934db30a277a1a9cec2dacbe03f8393107e5d0b2436695f9bd62bd569 diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.FileListAbsolute.txt b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.FileListAbsolute.txt new file mode 100644 index 000000000..2d4eec639 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.csproj.FileListAbsolute.txt @@ -0,0 +1,11 @@ +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Debug\net472\AppDiagnostic.Logging.dll +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Debug\net472\AppDiagnostic.Logging.pdb +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Debug\net472\NLog.dll +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.csproj.AssemblyReference.cache +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.AssemblyInfoInputs.cache +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.AssemblyInfo.cs +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.csproj.CoreCompileInputs.cache +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagn.CFEA7AC0.Up2Date +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.dll +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Debug\net472\AppDiagnostic.Logging.pdb diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.dll b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.dll new file mode 100644 index 000000000..fa3b3ef1c Binary files /dev/null and b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.dll differ diff --git a/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.pdb b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.pdb new file mode 100644 index 000000000..c8da8e1d1 Binary files /dev/null and b/AppDiagnostic.Logging/obj/Debug/net472/AppDiagnostic.Logging.pdb differ diff --git a/AppDiagnostic.Logging/obj/Release/net472/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/AppDiagnostic.Logging/obj/Release/net472/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs new file mode 100644 index 000000000..3871b184d --- /dev/null +++ b/AppDiagnostic.Logging/obj/Release/net472/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagn.CFEA7AC0.Up2Date b/AppDiagnostic.Logging/obj/Release/net472/AppDiagn.CFEA7AC0.Up2Date new file mode 100644 index 000000000..e69de29bb diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfo.cs b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfo.cs new file mode 100644 index 000000000..a53fb10a6 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfo.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("AppDiagnostic.Logging")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+086bb55595ffea5be7adb163ca4c6489903ed67c")] +[assembly: System.Reflection.AssemblyProductAttribute("AppDiagnostic.Logging")] +[assembly: System.Reflection.AssemblyTitleAttribute("AppDiagnostic.Logging")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache new file mode 100644 index 000000000..baac57ee0 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +aad509aee7434678bd40a99ea120dafb7aa8b4f050f239aae2fbef41167a7201 diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 000000000..9cac7ed56 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,8 @@ +is_global = true +build_property.RootNamespace = AppDiagnostic.Logging +build_property.ProjectDir = C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.CsWinRTUseWindowsUIXamlProjections = false +build_property.EffectiveAnalysisLevelStyle = +build_property.EnableCodeStyleSeverity = diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.assets.cache b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.assets.cache new file mode 100644 index 000000000..3e5407a6d Binary files /dev/null and b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.assets.cache differ diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache new file mode 100644 index 000000000..883e6d9b0 Binary files /dev/null and b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.AssemblyReference.cache differ diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.BuildWithSkipAnalyzers b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.BuildWithSkipAnalyzers new file mode 100644 index 000000000..e69de29bb diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.CoreCompileInputs.cache b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.CoreCompileInputs.cache new file mode 100644 index 000000000..c31c2aa80 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +53dfa6175dfb762da95c667a45dfe918166697a8741b3f7c14601d1f62b1886d diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.FileListAbsolute.txt b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.FileListAbsolute.txt new file mode 100644 index 000000000..82c760b66 --- /dev/null +++ b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.csproj.FileListAbsolute.txt @@ -0,0 +1,11 @@ +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Release\net472\AppDiagnostic.Logging.dll +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Release\net472\AppDiagnostic.Logging.pdb +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\bin\Release\net472\NLog.dll +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.csproj.AssemblyReference.cache +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.GeneratedMSBuildEditorConfig.editorconfig +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.AssemblyInfoInputs.cache +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.AssemblyInfo.cs +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.csproj.CoreCompileInputs.cache +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagn.CFEA7AC0.Up2Date +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.dll +C:\Sensus_projects\New\LocalBranch_start_at_6.3.2026\tbf-local\tbf\AppDiagnostic.Logging\obj\Release\net472\AppDiagnostic.Logging.pdb diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.dll b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.dll new file mode 100644 index 000000000..92ba99691 Binary files /dev/null and b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.dll differ diff --git a/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.pdb b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.pdb new file mode 100644 index 000000000..20f7774dc Binary files /dev/null and b/AppDiagnostic.Logging/obj/Release/net472/AppDiagnostic.Logging.pdb differ diff --git a/AppDiagnostic.Logging/obj/project.assets.json b/AppDiagnostic.Logging/obj/project.assets.json new file mode 100644 index 000000000..820b925a7 --- /dev/null +++ b/AppDiagnostic.Logging/obj/project.assets.json @@ -0,0 +1,119 @@ +{ + "version": 4, + "targets": { + "net472": { + "NLog/5.2.2": { + "type": "package", + "frameworkAssemblies": [ + "System", + "System.Configuration", + "System.Core", + "System.IO.Compression", + "System.Xml" + ], + "compile": { + "lib/net46/NLog.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net46/NLog.dll": { + "related": ".xml" + } + } + } + } + }, + "libraries": { + "NLog/5.2.2": { + "sha512": "r6Q9740g29gTwmTWlsgdIFm0mhNsfNZmbvWKX/Fxmi8X89ZrpUowHM2T2X1lP7RVpND+ef+XnfKL5g6Q1iNGXA==", + "type": "package", + "path": "nlog/5.2.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "N.png", + "lib/net35/NLog.dll", + "lib/net35/NLog.xml", + "lib/net45/NLog.dll", + "lib/net45/NLog.xml", + "lib/net46/NLog.dll", + "lib/net46/NLog.xml", + "lib/netstandard1.3/NLog.dll", + "lib/netstandard1.3/NLog.xml", + "lib/netstandard1.5/NLog.dll", + "lib/netstandard1.5/NLog.xml", + "lib/netstandard2.0/NLog.dll", + "lib/netstandard2.0/NLog.xml", + "nlog.5.2.2.nupkg.sha512", + "nlog.nuspec" + ] + } + }, + "projectFileDependencyGroups": { + "net472": [ + "NLog >= 5.2.2" + ] + }, + "packageFolders": { + "C:\\Users\\MFRNIAK\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj", + "projectName": "AppDiagnostic.Logging", + "projectPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj", + "packagesPath": "C:\\Users\\MFRNIAK\\.nuget\\packages\\", + "outputPath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\MFRNIAK\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net472" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net472": { + "framework": "net472", + "targetAlias": "net472", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "10.0.300" + }, + "frameworks": { + "net472": { + "framework": "net472", + "targetAlias": "net472", + "dependencies": { + "NLog": { + "target": "Package", + "version": "[5.2.2, )" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.303\\RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/AppDiagnostic.Logging/obj/project.nuget.cache b/AppDiagnostic.Logging/obj/project.nuget.cache new file mode 100644 index 000000000..ef0bb2527 --- /dev/null +++ b/AppDiagnostic.Logging/obj/project.nuget.cache @@ -0,0 +1,10 @@ +{ + "version": 2, + "dgSpecHash": "ezwKOPZAAXU=", + "success": true, + "projectFilePath": "C:\\Sensus_projects\\New\\LocalBranch_start_at_6.3.2026\\tbf-local\\tbf\\AppDiagnostic.Logging\\AppDiagnostic.Logging.csproj", + "expectedPackageFiles": [ + "C:\\Users\\MFRNIAK\\.nuget\\packages\\nlog\\5.2.2\\nlog.5.2.2.nupkg.sha512" + ], + "logs": [] +} \ No newline at end of file diff --git a/AppDiagnostic/App.config b/AppDiagnostic/App.config index 7f5eaea7b..aad6a5e83 100644 --- a/AppDiagnostic/App.config +++ b/AppDiagnostic/App.config @@ -3,17 +3,4 @@ - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/AppDiagnostic/AppDiagnostic.csproj b/AppDiagnostic/AppDiagnostic.csproj index cef866153..d2ea61617 100644 --- a/AppDiagnostic/AppDiagnostic.csproj +++ b/AppDiagnostic/AppDiagnostic.csproj @@ -33,9 +33,6 @@ 4 - - ..\packages\log4net.3.0.3\lib\net462\log4net.dll - @@ -51,12 +48,15 @@ - - Component + + Form - - - + + + + + + Form @@ -78,7 +78,6 @@ Resources.resx True - SettingsSingleFileGenerator Settings.Designer.cs @@ -93,9 +92,9 @@ - - {8f942729-f454-4c99-ba6c-746962065ae3} - SharedComponents + + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC} + AppDiagnostic.Logging diff --git a/AppDiagnostic/ColorRuleEditorForm.cs b/AppDiagnostic/ColorRuleEditorForm.cs new file mode 100644 index 000000000..a944d7fef --- /dev/null +++ b/AppDiagnostic/ColorRuleEditorForm.cs @@ -0,0 +1,319 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; + +namespace AppDiagnostic +{ + public sealed class ColorRuleEditorForm : Form + { + private readonly List rules; + private readonly ListBox ruleList = new ListBox(); + private readonly TextBox patternTextBox = new TextBox(); + private readonly CheckBox enabledCheckBox = new CheckBox(); + private readonly CheckBox boldCheckBox = new CheckBox(); + private readonly CheckBox backgroundCheckBox = new CheckBox(); + private readonly Button foregroundButton = new Button(); + private readonly Button backgroundButton = new Button(); + private readonly RichTextBox previewBox = new RichTextBox(); + private readonly Font previewBoldFont; + private bool loadingRule; + + public ColorRuleEditorForm(IEnumerable sourceRules) + { + rules = sourceRules.Select(rule => rule.Clone()).ToList(); + InitializeWindow(); + previewBoldFont = new Font(previewBox.Font, FontStyle.Bold); + RefreshRuleList(0); + RefreshPreview(); + } + + public List Rules => rules.Select(rule => rule.Clone()).ToList(); + + protected override void Dispose(bool disposing) + { + if (disposing) + { + previewBoldFont.Dispose(); + } + + base.Dispose(disposing); + } + + private void InitializeWindow() + { + Text = "Log color rules"; + Icon = Properties.Resources.TBF_icon; + StartPosition = FormStartPosition.CenterParent; + MinimumSize = new Size(760, 500); + ClientSize = new Size(860, 560); + + var root = new TableLayoutPanel { Dock = DockStyle.Fill, ColumnCount = 1, RowCount = 3, Padding = new Padding(10) }; + root.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); + root.RowStyles.Add(new RowStyle(SizeType.Absolute, 145F)); + root.RowStyles.Add(new RowStyle(SizeType.Absolute, 42F)); + + var split = new SplitContainer { Dock = DockStyle.Fill, SplitterDistance = 280 }; + split.Panel1.Padding = new Padding(0, 0, 8, 0); + split.Panel2.Padding = new Padding(8, 0, 0, 0); + + ruleList.Dock = DockStyle.Fill; + ruleList.IntegralHeight = false; + ruleList.SelectedIndexChanged += RuleList_SelectedIndexChanged; + + var listButtons = new FlowLayoutPanel { Dock = DockStyle.Bottom, Height = 36, FlowDirection = FlowDirection.LeftToRight }; + listButtons.Controls.Add(CreateButton("Add", AddRule_Click)); + listButtons.Controls.Add(CreateButton("Delete", DeleteRule_Click)); + listButtons.Controls.Add(CreateButton("Up", MoveUp_Click)); + listButtons.Controls.Add(CreateButton("Down", MoveDown_Click)); + split.Panel1.Controls.Add(ruleList); + split.Panel1.Controls.Add(listButtons); + + var editor = new TableLayoutPanel { Dock = DockStyle.Top, AutoSize = true, ColumnCount = 2, Padding = new Padding(4) }; + editor.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 120F)); + editor.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); + + enabledCheckBox.Text = "Rule enabled"; + enabledCheckBox.AutoSize = true; + enabledCheckBox.CheckedChanged += EditorValueChanged; + AddEditorRow(editor, "State", enabledCheckBox); + + patternTextBox.Dock = DockStyle.Fill; + patternTextBox.TextChanged += EditorValueChanged; + AddEditorRow(editor, "Substring", patternTextBox); + + foregroundButton.Text = "Choose text color..."; + foregroundButton.AutoSize = true; + foregroundButton.Click += ForegroundButton_Click; + AddEditorRow(editor, "Text color", foregroundButton); + + var backgroundPanel = new FlowLayoutPanel { Dock = DockStyle.Fill, AutoSize = true }; + backgroundCheckBox.Text = "Use background"; + backgroundCheckBox.AutoSize = true; + backgroundCheckBox.CheckedChanged += EditorValueChanged; + backgroundButton.Text = "Choose..."; + backgroundButton.AutoSize = true; + backgroundButton.Click += BackgroundButton_Click; + backgroundPanel.Controls.Add(backgroundCheckBox); + backgroundPanel.Controls.Add(backgroundButton); + AddEditorRow(editor, "Background", backgroundPanel); + + boldCheckBox.Text = "Bold text"; + boldCheckBox.AutoSize = true; + boldCheckBox.CheckedChanged += EditorValueChanged; + AddEditorRow(editor, "Font", boldCheckBox); + + var resetButton = CreateButton("Restore default rules", RestoreDefaults_Click); + resetButton.AutoSize = true; + AddEditorRow(editor, string.Empty, resetButton); + split.Panel2.Controls.Add(editor); + + previewBox.Dock = DockStyle.Fill; + previewBox.ReadOnly = true; + previewBox.WordWrap = true; + previewBox.Font = new Font("Consolas", 9F); + previewBox.Text = "2026-09-10 14:25:31.042|DEBUG|TBF[14280]|TBF.UI.MainWnd|Device configuration loaded.\n2026-09-10 14:25:31.384|INFO |TBF[14280]|TBF.Rig.StateMachine|Test bench started.\n2026-09-10 14:25:32.018|WARN |TBF[14280]|TBF.Device|Pressure is approaching the limit.\n2026-09-10 14:25:32.611|ERROR|TBF[14280]|TBF.Device|Communication failed."; + + var previewGroup = new GroupBox { Text = "Live preview", Dock = DockStyle.Fill, Padding = new Padding(8) }; + previewGroup.Controls.Add(previewBox); + + var footer = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.RightToLeft, Padding = new Padding(0, 8, 0, 0) }; + var okButton = new Button { Text = "OK", DialogResult = DialogResult.OK, AutoSize = true }; + var cancelButton = new Button { Text = "Cancel", DialogResult = DialogResult.Cancel, AutoSize = true }; + footer.Controls.Add(okButton); + footer.Controls.Add(cancelButton); + + AcceptButton = okButton; + CancelButton = cancelButton; + root.Controls.Add(split, 0, 0); + root.Controls.Add(previewGroup, 0, 1); + root.Controls.Add(footer, 0, 2); + Controls.Add(root); + } + + private static Button CreateButton(string text, EventHandler clickHandler) + { + var button = new Button { Text = text, AutoSize = true }; + button.Click += clickHandler; + return button; + } + + private static void AddEditorRow(TableLayoutPanel panel, string labelText, Control control) + { + int row = panel.RowCount++; + panel.RowStyles.Add(new RowStyle(SizeType.AutoSize)); + var label = new Label { Text = labelText, AutoSize = true, Anchor = AnchorStyles.Left, Margin = new Padding(3, 8, 3, 3) }; + control.Margin = new Padding(3, 5, 3, 5); + panel.Controls.Add(label, 0, row); + panel.Controls.Add(control, 1, row); + } + + private void RefreshRuleList(int selectedIndex) + { + ruleList.BeginUpdate(); + ruleList.Items.Clear(); + foreach (LogColorRule rule in rules) + { + ruleList.Items.Add(rule); + } + ruleList.EndUpdate(); + + if (rules.Count > 0) + { + ruleList.SelectedIndex = Math.Max(0, Math.Min(selectedIndex, rules.Count - 1)); + } + } + + private void RuleList_SelectedIndexChanged(object sender, EventArgs e) + { + LogColorRule rule = ruleList.SelectedItem as LogColorRule; + if (rule == null) + { + return; + } + + loadingRule = true; + enabledCheckBox.Checked = rule.Enabled; + patternTextBox.Text = rule.Pattern; + foregroundButton.BackColor = rule.ForeColor; + backgroundCheckBox.Checked = rule.UseBackColor; + backgroundButton.Enabled = rule.UseBackColor; + backgroundButton.BackColor = rule.UseBackColor ? rule.BackColor : SystemColors.Control; + boldCheckBox.Checked = rule.Bold; + loadingRule = false; + } + + private void EditorValueChanged(object sender, EventArgs e) + { + if (loadingRule) + { + return; + } + + LogColorRule rule = ruleList.SelectedItem as LogColorRule; + if (rule == null) + { + return; + } + + rule.Enabled = enabledCheckBox.Checked; + rule.Pattern = patternTextBox.Text; + rule.UseBackColor = backgroundCheckBox.Checked; + rule.Bold = boldCheckBox.Checked; + backgroundButton.Enabled = rule.UseBackColor; + int index = ruleList.SelectedIndex; + RefreshRuleList(index); + RefreshPreview(); + } + + private void ForegroundButton_Click(object sender, EventArgs e) + { + LogColorRule rule = ruleList.SelectedItem as LogColorRule; + if (rule == null) + { + return; + } + + using (var dialog = new ColorDialog { Color = rule.ForeColor, FullOpen = true }) + { + if (dialog.ShowDialog(this) != DialogResult.OK) + { + return; + } + + rule.ForeColorArgb = dialog.Color.ToArgb(); + foregroundButton.BackColor = dialog.Color; + RefreshPreview(); + } + } + + private void BackgroundButton_Click(object sender, EventArgs e) + { + LogColorRule rule = ruleList.SelectedItem as LogColorRule; + if (rule == null) + { + return; + } + + Color initialColor = rule.UseBackColor ? rule.BackColor : SystemColors.Window; + using (var dialog = new ColorDialog { Color = initialColor, FullOpen = true }) + { + if (dialog.ShowDialog(this) != DialogResult.OK) + { + return; + } + + rule.BackColorArgb = dialog.Color.ToArgb(); + rule.UseBackColor = true; + backgroundCheckBox.Checked = true; + backgroundButton.BackColor = dialog.Color; + RefreshPreview(); + } + } + + private void AddRule_Click(object sender, EventArgs e) + { + rules.Add(new LogColorRule { Pattern = "NEW SUBSTRING", ForeColorArgb = Color.MediumPurple.ToArgb() }); + RefreshRuleList(rules.Count - 1); + patternTextBox.Focus(); + patternTextBox.SelectAll(); + } + + private void DeleteRule_Click(object sender, EventArgs e) + { + int index = ruleList.SelectedIndex; + if (index < 0) + { + return; + } + + rules.RemoveAt(index); + RefreshRuleList(Math.Min(index, rules.Count - 1)); + RefreshPreview(); + } + + private void MoveUp_Click(object sender, EventArgs e) + { + MoveSelectedRule(-1); + } + + private void MoveDown_Click(object sender, EventArgs e) + { + MoveSelectedRule(1); + } + + private void MoveSelectedRule(int offset) + { + int index = ruleList.SelectedIndex; + int newIndex = index + offset; + if (index < 0 || newIndex < 0 || newIndex >= rules.Count) + { + return; + } + + LogColorRule rule = rules[index]; + rules.RemoveAt(index); + rules.Insert(newIndex, rule); + RefreshRuleList(newIndex); + RefreshPreview(); + } + + private void RestoreDefaults_Click(object sender, EventArgs e) + { + rules.Clear(); + rules.AddRange(LogColorRule.CreateDefaults()); + RefreshRuleList(0); + RefreshPreview(); + } + + private void RefreshPreview() + { + int selectionStart = previewBox.SelectionStart; + int selectionLength = previewBox.SelectionLength; + string text = previewBox.Text; + LogColorizer.Apply(previewBox, 0, text.Length, text, rules, previewBox.Font, previewBoldFont); + previewBox.Select(Math.Min(selectionStart, previewBox.TextLength), Math.Min(selectionLength, Math.Max(0, previewBox.TextLength - selectionStart))); + } + } +} diff --git a/AppDiagnostic/DiagnosticLogFormatter.cs b/AppDiagnostic/DiagnosticLogFormatter.cs new file mode 100644 index 000000000..c8d598cce --- /dev/null +++ b/AppDiagnostic/DiagnosticLogFormatter.cs @@ -0,0 +1,24 @@ +using AppDiagnostic.Logging; +using System; + +namespace AppDiagnostic +{ + public static class DiagnosticLogFormatter + { + public static string Format(DiagnosticLogEntry entry) + { + if (entry == null) + { + return string.Empty; + } + + string level = (entry.Level ?? string.Empty).ToUpperInvariant().PadRight(5); + string application = string.IsNullOrWhiteSpace(entry.ApplicationName) ? "Unknown" : entry.ApplicationName; + string logger = entry.LoggerName ?? string.Empty; + string message = entry.Message ?? string.Empty; + string exception = string.IsNullOrWhiteSpace(entry.Exception) ? string.Empty : Environment.NewLine + entry.Exception; + + return $"{entry.TimestampUtc.ToLocalTime():yyyy-MM-dd HH:mm:ss.fff}|{level}|{application}[{entry.ProcessId}]|{logger}|{message}{exception}"; + } + } +} diff --git a/AppDiagnostic/DiagnosticLogStore.cs b/AppDiagnostic/DiagnosticLogStore.cs new file mode 100644 index 000000000..67ddb3437 --- /dev/null +++ b/AppDiagnostic/DiagnosticLogStore.cs @@ -0,0 +1,82 @@ +using AppDiagnostic.Logging; +using System.Collections.Generic; +using System.Linq; + +namespace AppDiagnostic +{ + public sealed class DiagnosticLogStore + { + private const int MaximumLogCount = 10000; + private static readonly DiagnosticLogStore instance = new DiagnosticLogStore(); + private readonly object syncRoot = new object(); + private readonly List entries = new List(); + private long totalReceived; + private long version; + + private DiagnosticLogStore() + { + } + + public static DiagnosticLogStore Instance => instance; + + public long TotalReceived + { + get + { + lock (syncRoot) + { + return totalReceived; + } + } + } + + public long Version + { + get + { + lock (syncRoot) + { + return version; + } + } + } + + public void Add(DiagnosticLogEntry entry) + { + if (entry == null) + { + return; + } + + lock (syncRoot) + { + entries.Add(entry); + totalReceived++; + version++; + + int excessCount = entries.Count - MaximumLogCount; + if (excessCount > 0) + { + entries.RemoveRange(0, excessCount); + } + } + } + + public List GetSnapshot() + { + lock (syncRoot) + { + return entries.ToList(); + } + } + + public void Clear() + { + lock (syncRoot) + { + entries.Clear(); + version++; + } + } + } +} diff --git a/AppDiagnostic/DiagnosticPipeServer.cs b/AppDiagnostic/DiagnosticPipeServer.cs new file mode 100644 index 000000000..4a51550f4 --- /dev/null +++ b/AppDiagnostic/DiagnosticPipeServer.cs @@ -0,0 +1,164 @@ +using AppDiagnostic.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Pipes; +using System.Threading; +using System.Threading.Tasks; + +namespace AppDiagnostic +{ + public sealed class DiagnosticPipeServer : IDisposable + { + private readonly Action messageReceived; + private readonly CancellationTokenSource cancellation = new CancellationTokenSource(); + private readonly object syncRoot = new object(); + private readonly List connectedClients = new List(); + private NamedPipeServerStream waitingServer; + private Task serverTask; + + public DiagnosticPipeServer(Action messageReceived) + { + this.messageReceived = messageReceived ?? throw new ArgumentNullException(nameof(messageReceived)); + } + + public int ConnectedClientCount + { + get + { + lock (syncRoot) + { + return connectedClients.Count; + } + } + } + + public void Start() + { + if (serverTask != null) + { + return; + } + + serverTask = Task.Run((Action)AcceptConnections); + } + + private void AcceptConnections() + { + while (!cancellation.IsCancellationRequested) + { + NamedPipeServerStream server = null; + + try + { + server = new NamedPipeServerStream(DiagnosticProtocol.DefaultPipeName, PipeDirection.In, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); + + lock (syncRoot) + { + waitingServer = server; + } + + server.WaitForConnection(); + + lock (syncRoot) + { + waitingServer = null; + connectedClients.Add(server); + } + + NamedPipeServerStream connectedServer = server; + server = null; + Task.Run(() => ReadClient(connectedServer)); + } + catch (ObjectDisposedException) + { + if (!cancellation.IsCancellationRequested) + { + throw; + } + } + catch (IOException) + { + if (!cancellation.IsCancellationRequested) + { + Thread.Sleep(250); + } + } + finally + { + lock (syncRoot) + { + if (ReferenceEquals(waitingServer, server)) + { + waitingServer = null; + } + } + + server?.Dispose(); + } + } + } + + private void ReadClient(NamedPipeServerStream client) + { + try + { + while (client.IsConnected && !cancellation.IsCancellationRequested) + { + DiagnosticLogEntry entry = DiagnosticMessageSerializer.ReadFramed(client); + messageReceived(entry); + } + } + catch (EndOfStreamException) + { + // The producer application was closed. + } + catch (IOException) + { + // The producer application disconnected. + } + catch (ObjectDisposedException) + { + // The diagnostic application is shutting down. + } + finally + { + lock (syncRoot) + { + connectedClients.Remove(client); + } + + client.Dispose(); + } + } + + public void Dispose() + { + cancellation.Cancel(); + + lock (syncRoot) + { + waitingServer?.Dispose(); + waitingServer = null; + + foreach (NamedPipeServerStream client in connectedClients.ToArray()) + { + client.Dispose(); + } + + connectedClients.Clear(); + } + + try + { + serverTask?.Wait(2000); + } + catch (AggregateException) + { + // Cancellation during shutdown is expected. + } + + cancellation.Dispose(); + } + } +} diff --git a/AppDiagnostic/LogColorRule.cs b/AppDiagnostic/LogColorRule.cs new file mode 100644 index 000000000..e801bc4c9 --- /dev/null +++ b/AppDiagnostic/LogColorRule.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace AppDiagnostic +{ + [Serializable] + public sealed class LogColorRule + { + public bool Enabled { get; set; } = true; + public string Pattern { get; set; } = string.Empty; + public int ForeColorArgb { get; set; } = Color.Black.ToArgb(); + public int BackColorArgb { get; set; } + public bool UseBackColor { get; set; } + public bool Bold { get; set; } + + public Color ForeColor => Color.FromArgb(ForeColorArgb); + public Color BackColor => Color.FromArgb(BackColorArgb); + + public LogColorRule Clone() + { + return new LogColorRule + { + Enabled = Enabled, + Pattern = Pattern, + ForeColorArgb = ForeColorArgb, + BackColorArgb = BackColorArgb, + UseBackColor = UseBackColor, + Bold = Bold + }; + } + + public override string ToString() + { + string state = Enabled ? string.Empty : "[disabled] "; + return state + Pattern; + } + + public static List CreateDefaults() + { + return new List + { + Create("|TRACE|", Color.DimGray, false), + Create("|DEBUG|", Color.RoyalBlue, false), + Create("|INFO |", Color.ForestGreen, false), + Create("|WARN |", Color.DarkOrange, true), + Create("|ERROR|", Color.Crimson, true), + Create("|FATAL|", Color.White, true, Color.DarkRed) + }; + } + + private static LogColorRule Create(string pattern, Color foreground, bool bold, Color? background = null) + { + return new LogColorRule + { + Enabled = true, + Pattern = pattern, + ForeColorArgb = foreground.ToArgb(), + BackColorArgb = background?.ToArgb() ?? Color.Empty.ToArgb(), + UseBackColor = background.HasValue, + Bold = bold + }; + } + } +} diff --git a/AppDiagnostic/LogColorRuleRepository.cs b/AppDiagnostic/LogColorRuleRepository.cs new file mode 100644 index 000000000..7cd86d4f9 --- /dev/null +++ b/AppDiagnostic/LogColorRuleRepository.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; + +namespace AppDiagnostic +{ + public static class LogColorRuleRepository + { + private static readonly string settingsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Sensus", "AppDiagnostic"); + private static readonly string settingsPath = Path.Combine(settingsFolder, "color-rules.xml"); + + public static List Load() + { + try + { + if (!File.Exists(settingsPath)) + { + return LogColorRule.CreateDefaults(); + } + + var serializer = new XmlSerializer(typeof(List)); + using (FileStream stream = File.OpenRead(settingsPath)) + { + var rules = serializer.Deserialize(stream) as List; + return rules == null || rules.Count == 0 ? LogColorRule.CreateDefaults() : rules; + } + } + catch + { + return LogColorRule.CreateDefaults(); + } + } + + public static void Save(IEnumerable rules) + { + Directory.CreateDirectory(settingsFolder); + + var serializer = new XmlSerializer(typeof(List)); + using (FileStream stream = File.Create(settingsPath)) + { + serializer.Serialize(stream, new List(rules)); + } + } + } +} diff --git a/AppDiagnostic/LogColorizer.cs b/AppDiagnostic/LogColorizer.cs new file mode 100644 index 000000000..35891ea5f --- /dev/null +++ b/AppDiagnostic/LogColorizer.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; + +namespace AppDiagnostic +{ + public static class LogColorizer + { + public static void Apply(RichTextBox target, int startIndex, int length, string text, IEnumerable rules, Font regularFont, Font boldFont) + { + if (target == null || length <= 0) + { + return; + } + + target.Select(startIndex, length); + target.SelectionColor = target.ForeColor; + target.SelectionBackColor = target.BackColor; + target.SelectionFont = regularFont; + + foreach (LogColorRule rule in rules) + { + if (rule == null || !rule.Enabled || string.IsNullOrEmpty(rule.Pattern)) + { + continue; + } + + int searchIndex = 0; + while (searchIndex < text.Length) + { + int matchIndex = text.IndexOf(rule.Pattern, searchIndex, StringComparison.OrdinalIgnoreCase); + if (matchIndex < 0) + { + break; + } + + target.Select(startIndex + matchIndex, rule.Pattern.Length); + target.SelectionColor = rule.ForeColor; + target.SelectionBackColor = rule.UseBackColor ? rule.BackColor : target.BackColor; + target.SelectionFont = rule.Bold ? boldFont : regularFont; + searchIndex = matchIndex + rule.Pattern.Length; + } + } + } + } +} diff --git a/AppDiagnostic/MainForm.Designer.cs b/AppDiagnostic/MainForm.Designer.cs index 1eef3958d..7ea3f99c9 100644 --- a/AppDiagnostic/MainForm.Designer.cs +++ b/AppDiagnostic/MainForm.Designer.cs @@ -1,278 +1,309 @@ -using System.Windows.Forms; - namespace AppDiagnostic { partial class MainForm { - /// - /// Required designer variable. - /// private System.ComponentModel.IContainer components = null; + private System.Windows.Forms.ToolStrip mainToolStrip; + private System.Windows.Forms.ToolStripButton pauseButton; + private System.Windows.Forms.ToolStripButton refreshButton; + private System.Windows.Forms.ToolStripButton clearButton; + private System.Windows.Forms.ToolStripButton saveButton; + private System.Windows.Forms.ToolStripButton copyButton; + private System.Windows.Forms.ToolStripButton copyAllButton; + private System.Windows.Forms.ToolStripButton wrapButton; + private System.Windows.Forms.ToolStripButton autoScrollButton; + private System.Windows.Forms.ToolStripButton alwaysOnTopButton; + private System.Windows.Forms.ToolStripButton colorRulesButton; + private System.Windows.Forms.ToolStripButton closeButton; + private System.Windows.Forms.TableLayoutPanel filterPanel; + private System.Windows.Forms.Label filterLabel; + private System.Windows.Forms.TextBox filterTextBox; + private System.Windows.Forms.Label levelLabel; + private System.Windows.Forms.ComboBox levelComboBox; + private System.Windows.Forms.Label applicationLabel; + private System.Windows.Forms.ComboBox applicationComboBox; + private System.Windows.Forms.Button applyFilterButton; + private System.Windows.Forms.Button clearFilterButton; + private System.Windows.Forms.RichTextBox logView; + private System.Windows.Forms.StatusStrip statusStrip; + private System.Windows.Forms.ToolStripStatusLabel receiverStatusLabel; + private System.Windows.Forms.ToolStripStatusLabel statusSpacer; + private System.Windows.Forms.ToolStripStatusLabel countStatusLabel; + private System.Windows.Forms.ContextMenuStrip logContextMenu; + private System.Windows.Forms.ToolStripMenuItem copySelectionMenuItem; + private System.Windows.Forms.ToolStripMenuItem copyLineMenuItem; + private System.Windows.Forms.ToolStripMenuItem copyAllMenuItem; - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { - if (disposing && (components != null)) + if (disposing && components != null) { components.Dispose(); } + base.Dispose(disposing); } - #region Windows Form Designer generated code - //private BufferedListView memoListView; - private System.Windows.Forms.ColumnHeader columnHeaderTime; - private System.Windows.Forms.ColumnHeader columnHeaderMessage; - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// private void InitializeComponent() { - this.columnHeaderTime = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeaderMessage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.panel1 = new System.Windows.Forms.Panel(); - this.refreshMemoButton = new System.Windows.Forms.Button(); - this.button6 = new System.Windows.Forms.Button(); - this.button7 = new System.Windows.Forms.Button(); - this.filterManagementPanel = new System.Windows.Forms.Panel(); - this.button5 = new System.Windows.Forms.Button(); - this.filterButton = new System.Windows.Forms.Button(); + this.components = new System.ComponentModel.Container(); + this.mainToolStrip = new System.Windows.Forms.ToolStrip(); + this.pauseButton = new System.Windows.Forms.ToolStripButton(); + this.refreshButton = new System.Windows.Forms.ToolStripButton(); + this.clearButton = new System.Windows.Forms.ToolStripButton(); + this.saveButton = new System.Windows.Forms.ToolStripButton(); + this.copyButton = new System.Windows.Forms.ToolStripButton(); + this.copyAllButton = new System.Windows.Forms.ToolStripButton(); + this.wrapButton = new System.Windows.Forms.ToolStripButton(); + this.autoScrollButton = new System.Windows.Forms.ToolStripButton(); + this.alwaysOnTopButton = new System.Windows.Forms.ToolStripButton(); + this.colorRulesButton = new System.Windows.Forms.ToolStripButton(); + this.closeButton = new System.Windows.Forms.ToolStripButton(); + this.filterPanel = new System.Windows.Forms.TableLayoutPanel(); + this.filterLabel = new System.Windows.Forms.Label(); this.filterTextBox = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.wndControlPanel = new System.Windows.Forms.Panel(); - this.button2 = new System.Windows.Forms.Button(); - this.flowControlsPanel = new System.Windows.Forms.Panel(); - this.runButton = new System.Windows.Forms.Button(); - this.stopButton = new System.Windows.Forms.Button(); - this.label1 = new System.Windows.Forms.Label(); - this.memoListView = new BufferedListView(); - this.panel1.SuspendLayout(); - this.filterManagementPanel.SuspendLayout(); - this.wndControlPanel.SuspendLayout(); - this.flowControlsPanel.SuspendLayout(); + this.levelLabel = new System.Windows.Forms.Label(); + this.levelComboBox = new System.Windows.Forms.ComboBox(); + this.applicationLabel = new System.Windows.Forms.Label(); + this.applicationComboBox = new System.Windows.Forms.ComboBox(); + this.applyFilterButton = new System.Windows.Forms.Button(); + this.clearFilterButton = new System.Windows.Forms.Button(); + this.logContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.copySelectionMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.copyLineMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.copyAllMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.logView = new System.Windows.Forms.RichTextBox(); + this.statusStrip = new System.Windows.Forms.StatusStrip(); + this.receiverStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.statusSpacer = new System.Windows.Forms.ToolStripStatusLabel(); + this.countStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.mainToolStrip.SuspendLayout(); + this.filterPanel.SuspendLayout(); + this.logContextMenu.SuspendLayout(); + this.statusStrip.SuspendLayout(); this.SuspendLayout(); - // - // columnHeaderTime - // - this.columnHeaderTime.Text = "Time"; - this.columnHeaderTime.Width = 150; - // - // columnHeaderMessage - // - this.columnHeaderMessage.Text = "Message"; - this.columnHeaderMessage.Width = 350; - // - // panel1 - // - this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.panel1.Controls.Add(this.refreshMemoButton); - this.panel1.Controls.Add(this.button6); - this.panel1.Controls.Add(this.button7); - this.panel1.Location = new System.Drawing.Point(189, 356); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(283, 26); - this.panel1.TabIndex = 16; - // - // refreshMemoButton - // - this.refreshMemoButton.Location = new System.Drawing.Point(108, 0); - this.refreshMemoButton.Name = "refreshMemoButton"; - this.refreshMemoButton.Size = new System.Drawing.Size(84, 26); - this.refreshMemoButton.TabIndex = 17; - this.refreshMemoButton.Text = "Refresh memo"; - this.refreshMemoButton.UseVisualStyleBackColor = true; - this.refreshMemoButton.Click += new System.EventHandler(this.refreshMemoButton_Click); - // - // button6 - // - this.button6.Location = new System.Drawing.Point(0, 0); - this.button6.Name = "button6"; - this.button6.Size = new System.Drawing.Size(102, 26); - this.button6.TabIndex = 4; - this.button6.Text = "Clean diag cache"; - this.button6.UseVisualStyleBackColor = true; - this.button6.Click += new System.EventHandler(this.button6_Click); - // - // button7 - // - this.button7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.button7.Location = new System.Drawing.Point(198, 0); - this.button7.Name = "button7"; - this.button7.Size = new System.Drawing.Size(72, 26); - this.button7.TabIndex = 5; - this.button7.Text = "Save logs"; - this.button7.UseVisualStyleBackColor = true; - this.button7.Click += new System.EventHandler(this.button7_Click); - // - // filterManagementPanel - // - this.filterManagementPanel.Controls.Add(this.button5); - this.filterManagementPanel.Controls.Add(this.filterButton); - this.filterManagementPanel.Controls.Add(this.filterTextBox); - this.filterManagementPanel.Controls.Add(this.label2); - this.filterManagementPanel.Location = new System.Drawing.Point(127, 6); - this.filterManagementPanel.Name = "filterManagementPanel"; - this.filterManagementPanel.Size = new System.Drawing.Size(393, 26); - this.filterManagementPanel.TabIndex = 15; - // - // button5 - // - this.button5.Enabled = false; - this.button5.Location = new System.Drawing.Point(294, 4); - this.button5.Name = "button5"; - this.button5.Size = new System.Drawing.Size(81, 20); - this.button5.TabIndex = 11; - this.button5.Text = "Add new filter"; - this.button5.UseVisualStyleBackColor = true; - // - // filterButton - // - this.filterButton.Location = new System.Drawing.Point(225, 4); - this.filterButton.Name = "filterButton"; - this.filterButton.Size = new System.Drawing.Size(64, 20); - this.filterButton.TabIndex = 10; - this.filterButton.Text = "Set filter"; - this.filterButton.UseVisualStyleBackColor = true; - this.filterButton.Click += new System.EventHandler(this.filterButton_Click_1); - // - // filterTextBox - // - this.filterTextBox.Location = new System.Drawing.Point(33, 4); - this.filterTextBox.Name = "filterTextBox"; - this.filterTextBox.Size = new System.Drawing.Size(187, 20); - this.filterTextBox.TabIndex = 7; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(3, 8); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(29, 13); - this.label2.TabIndex = 6; - this.label2.Text = "Filter"; - // - // wndControlPanel - // - this.wndControlPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.wndControlPanel.Controls.Add(this.button2); - this.wndControlPanel.Location = new System.Drawing.Point(831, 356); - this.wndControlPanel.Name = "wndControlPanel"; - this.wndControlPanel.Size = new System.Drawing.Size(70, 26); - this.wndControlPanel.TabIndex = 14; - // - // button2 - // - this.button2.Location = new System.Drawing.Point(3, 0); - this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(64, 26); - this.button2.TabIndex = 2; - this.button2.Text = "Close"; - this.button2.UseVisualStyleBackColor = true; - this.button2.Click += new System.EventHandler(this.button2_Click); - // - // flowControlsPanel - // - this.flowControlsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.flowControlsPanel.Controls.Add(this.runButton); - this.flowControlsPanel.Controls.Add(this.stopButton); - this.flowControlsPanel.Location = new System.Drawing.Point(12, 356); - this.flowControlsPanel.Name = "flowControlsPanel"; - this.flowControlsPanel.Size = new System.Drawing.Size(133, 26); - this.flowControlsPanel.TabIndex = 13; - // - // runButton - // - this.runButton.Enabled = false; - this.runButton.Location = new System.Drawing.Point(0, 0); - this.runButton.Name = "runButton"; - this.runButton.Size = new System.Drawing.Size(64, 26); - this.runButton.TabIndex = 4; - this.runButton.Text = "Run"; - this.runButton.UseVisualStyleBackColor = true; - this.runButton.Click += new System.EventHandler(this.runButton_Click); - // - // stopButton - // - this.stopButton.Location = new System.Drawing.Point(69, 0); - this.stopButton.Name = "stopButton"; - this.stopButton.Size = new System.Drawing.Size(64, 26); - this.stopButton.TabIndex = 5; - this.stopButton.Text = "Stop"; - this.stopButton.UseVisualStyleBackColor = true; - this.stopButton.Click += new System.EventHandler(this.stopButton_Click); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(12, 19); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(76, 13); - this.label1.TabIndex = 12; - this.label1.Text = "Flow of events"; - // - // memoListView - // - this.memoListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.memoListView.FullRowSelect = true; - this.memoListView.GridLines = true; - this.memoListView.HideSelection = false; - this.memoListView.Location = new System.Drawing.Point(12, 38); - this.memoListView.Name = "memoListView"; - this.memoListView.Size = new System.Drawing.Size(889, 312); - this.memoListView.TabIndex = 0; - this.memoListView.UseCompatibleStateImageBehavior = false; - this.memoListView.View = System.Windows.Forms.View.Details; - - this.memoListView.DoubleClick += new System.EventHandler(this.MemoListView_DoubleClick); - // + // + // mainToolStrip + // + this.mainToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.mainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.pauseButton, + this.refreshButton, + this.clearButton, + this.saveButton, + new System.Windows.Forms.ToolStripSeparator(), + this.copyButton, + this.copyAllButton, + new System.Windows.Forms.ToolStripSeparator(), + this.wrapButton, + this.autoScrollButton, + this.alwaysOnTopButton, + this.colorRulesButton, + this.closeButton}); + this.mainToolStrip.Location = new System.Drawing.Point(0, 0); + this.mainToolStrip.Name = "mainToolStrip"; + this.mainToolStrip.Padding = new System.Windows.Forms.Padding(6, 3, 6, 3); + this.mainToolStrip.Size = new System.Drawing.Size(1184, 31); + this.mainToolStrip.TabIndex = 0; + // + // pauseButton + // + this.pauseButton.CheckOnClick = true; + this.pauseButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.pauseButton.Text = "Pause"; + this.pauseButton.ToolTipText = "Pause screen updates while continuing to receive logs"; + this.pauseButton.Click += new System.EventHandler(this.pauseButton_Click); + // + // refreshButton + // + this.refreshButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.refreshButton.Text = "Refresh"; + this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click); + // + // clearButton + // + this.clearButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.clearButton.Text = "Clear"; + this.clearButton.Click += new System.EventHandler(this.clearButton_Click); + // + // saveButton + // + this.saveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.saveButton.Text = "Save..."; + this.saveButton.Click += new System.EventHandler(this.saveButton_Click); + // + // copyButton + // + this.copyButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.copyButton.Text = "Copy"; + this.copyButton.ToolTipText = "Copy selected text or the current log line"; + this.copyButton.Click += new System.EventHandler(this.copyButton_Click); + // + // copyAllButton + // + this.copyAllButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.copyAllButton.Text = "Copy all"; + this.copyAllButton.Click += new System.EventHandler(this.copyAllButton_Click); + // + // wrapButton + // + this.wrapButton.Checked = true; + this.wrapButton.CheckOnClick = true; + this.wrapButton.CheckState = System.Windows.Forms.CheckState.Checked; + this.wrapButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.wrapButton.Text = "Wrap lines"; + this.wrapButton.Click += new System.EventHandler(this.wrapButton_Click); + // + // autoScrollButton + // + this.autoScrollButton.Checked = true; + this.autoScrollButton.CheckOnClick = true; + this.autoScrollButton.CheckState = System.Windows.Forms.CheckState.Checked; + this.autoScrollButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.autoScrollButton.Text = "Auto-scroll"; + // + // alwaysOnTopButton + // + this.alwaysOnTopButton.CheckOnClick = true; + this.alwaysOnTopButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.alwaysOnTopButton.Text = "Always on top"; + this.alwaysOnTopButton.Click += new System.EventHandler(this.alwaysOnTopButton_Click); + // + // colorRulesButton + // + this.colorRulesButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.colorRulesButton.Text = "Color rules..."; + this.colorRulesButton.Click += new System.EventHandler(this.colorRulesButton_Click); + // + // closeButton + // + this.closeButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.closeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.closeButton.Text = "Close"; + this.closeButton.Click += new System.EventHandler(this.closeButton_Click); + // + // filterPanel + // + this.filterPanel.ColumnCount = 8; + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 42F)); + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 42F)); + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 105F)); + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 72F)); + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 180F)); + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 66F)); + this.filterPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 66F)); + this.filterPanel.Controls.Add(this.filterLabel, 0, 0); + this.filterPanel.Controls.Add(this.filterTextBox, 1, 0); + this.filterPanel.Controls.Add(this.levelLabel, 2, 0); + this.filterPanel.Controls.Add(this.levelComboBox, 3, 0); + this.filterPanel.Controls.Add(this.applicationLabel, 4, 0); + this.filterPanel.Controls.Add(this.applicationComboBox, 5, 0); + this.filterPanel.Controls.Add(this.applyFilterButton, 6, 0); + this.filterPanel.Controls.Add(this.clearFilterButton, 7, 0); + this.filterPanel.Dock = System.Windows.Forms.DockStyle.Top; + this.filterPanel.Location = new System.Drawing.Point(0, 31); + this.filterPanel.Name = "filterPanel"; + this.filterPanel.Padding = new System.Windows.Forms.Padding(6, 5, 6, 5); + this.filterPanel.RowCount = 1; + this.filterPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.filterPanel.Size = new System.Drawing.Size(1184, 38); + this.filterPanel.TabIndex = 1; + // + // filter controls + // + this.filterLabel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.filterLabel.AutoSize = true; + this.filterLabel.Text = "Filter"; + this.filterTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.filterTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.filterTextBox_KeyDown); + this.levelLabel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.levelLabel.AutoSize = true; + this.levelLabel.Text = "Level"; + this.levelComboBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.levelComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.levelComboBox.SelectedIndexChanged += new System.EventHandler(this.filterValueChanged); + this.applicationLabel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.applicationLabel.AutoSize = true; + this.applicationLabel.Text = "Application"; + this.applicationComboBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.applicationComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.applicationComboBox.SelectedIndexChanged += new System.EventHandler(this.filterValueChanged); + this.applyFilterButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.applyFilterButton.Text = "Apply"; + this.applyFilterButton.Click += new System.EventHandler(this.applyFilterButton_Click); + this.clearFilterButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.clearFilterButton.Text = "Reset"; + this.clearFilterButton.Click += new System.EventHandler(this.clearFilterButton_Click); + // + // logContextMenu + // + this.logContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.copySelectionMenuItem, + this.copyLineMenuItem, + this.copyAllMenuItem}); + this.copySelectionMenuItem.Text = "Copy selection"; + this.copySelectionMenuItem.Click += new System.EventHandler(this.copySelectionMenuItem_Click); + this.copyLineMenuItem.Text = "Copy current line"; + this.copyLineMenuItem.Click += new System.EventHandler(this.copyLineMenuItem_Click); + this.copyAllMenuItem.Text = "Copy all visible logs"; + this.copyAllMenuItem.Click += new System.EventHandler(this.copyAllButton_Click); + // + // logView + // + this.logView.BackColor = System.Drawing.SystemColors.Window; + this.logView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.logView.ContextMenuStrip = this.logContextMenu; + this.logView.DetectUrls = false; + this.logView.Dock = System.Windows.Forms.DockStyle.Fill; + this.logView.Font = new System.Drawing.Font("Consolas", 9F); + this.logView.HideSelection = false; + this.logView.Location = new System.Drawing.Point(0, 69); + this.logView.Name = "logView"; + this.logView.ReadOnly = true; + this.logView.Size = new System.Drawing.Size(1184, 554); + this.logView.TabIndex = 2; + this.logView.Text = ""; + this.logView.WordWrap = true; + // + // statusStrip + // + this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.receiverStatusLabel, + this.statusSpacer, + this.countStatusLabel}); + this.statusStrip.Location = new System.Drawing.Point(0, 623); + this.statusStrip.Name = "statusStrip"; + this.statusStrip.Size = new System.Drawing.Size(1184, 22); + this.statusStrip.TabIndex = 3; + this.receiverStatusLabel.Text = "Listening"; + this.statusSpacer.Spring = true; + this.countStatusLabel.Text = "Received: 0 | Visible: 0"; + // // MainForm - // + // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(913, 388); - this.Controls.Add(this.memoListView); - this.Controls.Add(this.panel1); - this.Controls.Add(this.filterManagementPanel); - this.Controls.Add(this.wndControlPanel); - this.Controls.Add(this.flowControlsPanel); - this.Controls.Add(this.label1); + this.ClientSize = new System.Drawing.Size(1184, 645); + this.Controls.Add(this.logView); + this.Controls.Add(this.filterPanel); + this.Controls.Add(this.mainToolStrip); + this.Controls.Add(this.statusStrip); + this.KeyPreview = true; + this.MinimumSize = new System.Drawing.Size(860, 480); this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Application live diagnostic"; - this.panel1.ResumeLayout(false); - this.filterManagementPanel.ResumeLayout(false); - this.filterManagementPanel.PerformLayout(); - this.wndControlPanel.ResumeLayout(false); - this.flowControlsPanel.ResumeLayout(false); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MainForm_KeyDown); + this.mainToolStrip.ResumeLayout(false); + this.mainToolStrip.PerformLayout(); + this.filterPanel.ResumeLayout(false); + this.filterPanel.PerformLayout(); + this.logContextMenu.ResumeLayout(false); + this.statusStrip.ResumeLayout(false); + this.statusStrip.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Button button6; - private System.Windows.Forms.Button button7; - private System.Windows.Forms.Panel filterManagementPanel; - private System.Windows.Forms.Button button5; - private System.Windows.Forms.Button filterButton; - private System.Windows.Forms.TextBox filterTextBox; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Panel wndControlPanel; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.Panel flowControlsPanel; - private System.Windows.Forms.Button runButton; - private System.Windows.Forms.Button stopButton; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Button refreshMemoButton; - private BufferedListView memoListView; } } - diff --git a/AppDiagnostic/MainForm.cs b/AppDiagnostic/MainForm.cs index f7c0d093d..15bdaff1e 100644 --- a/AppDiagnostic/MainForm.cs +++ b/AppDiagnostic/MainForm.cs @@ -1,267 +1,445 @@ -using log4net.Config; -using log4net; +using AppDiagnostic.Logging; using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Data; using System.Drawing; +using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; -using log4net.Appender; -using SharedComponents; -using static System.Windows.Forms.VisualStyles.VisualStyleElement; -using System.IO; // Pre File.WriteAllLines a prácu so súbormi -using System.Linq; namespace AppDiagnostic { public partial class MainForm : Form { - private bool stopUpdate = false; // Premenná na zastavenie aktualizácie - private int lastDisplayedLogIndex = 0; - private bool autoScrollEnabled = true; // Automatický posun, predvolene povolený - private MainForm appDiagnosticForm; - private Timer refreshTimer; - private LogAdapter _logAdapter; // Pre LogAdapter - private LogFilter _logFilter; // LogFilter objekt pre filtráciu + private readonly Func connectedClientCountProvider; + private readonly Func activationRequestProvider; + private readonly Timer refreshTimer; + private readonly Font regularLogFont; + private readonly Font boldLogFont; + private List colorRules; + private long lastRenderedVersion = -1; + private int observedEntryCount; + private int visibleEntryCount; + private bool loadingFilters; - public MainForm() + public MainForm() : this(null, null) { - this.Icon = Properties.Resources.TBF_icon; + } + public MainForm(Func connectedClientCountProvider, Func activationRequestProvider) + { + this.connectedClientCountProvider = connectedClientCountProvider; + this.activationRequestProvider = activationRequestProvider; InitializeComponent(); + Icon = Properties.Resources.TBF_icon; - // Inicializujeme LogAdapter a priradíme ho k memoListView - _logAdapter = new LogAdapter(memoListView); + regularLogFont = new Font(logView.Font, FontStyle.Regular); + boldLogFont = new Font(logView.Font, FontStyle.Bold); + colorRules = LogColorRuleRepository.Load(); - RefreshLogView(); + InitializeFilters(); - // Pripojenie na udalosť pri pridaní nového logu - // nakoľko sa memo refreshuje cyklicky, tak refresh na udalosť nepotrebujem - //LiveLogCache.Instance.LogAdded += OnLogAdded; + refreshTimer = new Timer { Interval = 250 }; + refreshTimer.Tick += refreshTimer_Tick; + refreshTimer.Start(); - // Vytvoríme LogFilter objekt - //_logFilter = new LogFilter(memoListView); - } - - private void OnLogAdded(string log) - { - try - { - RefreshLogView(); - } - catch (Exception ex) - { - MessageBox.Show($"Error in OnLogAdded: {ex.Message}"); - throw; - } - } - - private void RefreshLogView() - { - // Skontrolujte, či voláme z iného vlákna - if (InvokeRequired) - { - Invoke((Action)RefreshLogView); - return; - } - - memoListView.BeginUpdate(); // Zabraňuje vizuálnym aktualizáciám počas vykresľovania - - try - { - // Skontrolujte, či je užívateľ na poslednom viditeľnom zázname - if (memoListView.Items.Count > 0) - { - var lastVisibleIndex = memoListView.TopItem.Index + memoListView.ClientRectangle.Height / memoListView.Items[0].Bounds.Height; - autoScrollEnabled = lastVisibleIndex >= memoListView.Items.Count - 1; - } - - // Získajte nové logy od posledného indexu - var logs = LiveLogCache.Instance.GetLogs(lastDisplayedLogIndex, LiveLogCache.Instance.Logs.Count - lastDisplayedLogIndex); - - // Pridajte len nové logy - foreach (var log in logs) - { - memoListView.Items.Add(new ListViewItem(log)); - } - - // Aktualizujte posledný zobrazený index - lastDisplayedLogIndex = LiveLogCache.Instance.Logs.Count; - - // Ak je autoScrollEnabled, posuňte sa na posledný záznam - if (autoScrollEnabled && memoListView.Items.Count > 0) - { - memoListView.EnsureVisible(memoListView.Items.Count - 1); - } - } - finally - { - memoListView.EndUpdate(); // Umožní vizuálne aktualizácie - } - } - - // Táto metóda sa spustí pri scrollovaní v memoListView (tzn. ak sa používateľ dostane na spodok listu) - private void memoListView_Scroll(object sender, EventArgs e) - { - // Skontrolujte, či používateľ dosiahol spodok ListView - if (memoListView.Items.Count > 0 && - memoListView.Items[memoListView.Items.Count - 1].Bounds.Bottom <= memoListView.ClientSize.Height) - { - // Ak áno, načítame ďalšie logy - RefreshLogView(); - } - } - - private void button6_Click(object sender, EventArgs e) - { - //LiveLogCache.Instance.AddLog("Nový log z hlavnej aplikácie"); - - LiveLogCache.Instance.ClearLogs(); - ClearListView(); - } - - private void runButton_Click(object sender, EventArgs e) - { - if (stopUpdate) // Ak je časovač zastavený, spustíme ho - { - stopUpdate = false; // Zastav aktualizáciu - runButton.Enabled = false; // Zakážeme tlačidlo Start počas behu - stopButton.Enabled = true; // Povolenie tlačidla Stop - refreshTimer.Start(); - } - } - - private void stopButton_Click(object sender, EventArgs e) - { - if (!stopUpdate) // Ak časovač beží, môžeme ho zastaviť - { - stopUpdate = true; // Spusti aktualizáciu - runButton.Enabled = true; // Povolenie tlačidla Start - stopButton.Enabled = false; // Zakážeme tlačidlo Stop - refreshTimer.Stop(); - } - } - - private void ClearListView() - { - if (InvokeRequired) - { - Invoke(new Action(ClearListView)); - return; - } - - memoListView.Items.Clear(); - } - - private void refreshMemoButton_Click(object sender, EventArgs e) - { - - } - - private void button7_Click(object sender, EventArgs e) - { - SaveLogsToFile(); - //LiveLogCache.Instance.AddLog("Toto je nový log."); + RefreshView(true); } protected override void OnFormClosing(FormClosingEventArgs e) { - // Odpojenie udalosti, keď sa okno zatvára, inak môže po opätovnom spustení okna a pridaní nového itemu do listu zhhodiť program - // nakoľko sa memo refreshuje cyklicky, tak refresh na udalosť nepotrebujem - //LiveLogCache.Instance.LogAdded -= OnLogAdded; - - _logAdapter = null; - + refreshTimer.Stop(); + refreshTimer.Dispose(); + regularLogFont.Dispose(); + boldLogFont.Dispose(); base.OnFormClosing(e); } - private void filterButton_Click_1(object sender, EventArgs e) + private void InitializeFilters() { - // Aplikujeme filter na základe textu z filterTextBox - string filterText = filterTextBox.Text; - //_logFilter.ApplyFilter(filterText); // Aplikovanie filtra - _logAdapter.ApplyFilter(filterText); + loadingFilters = true; + levelComboBox.Items.AddRange(new object[] { "All levels", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" }); + levelComboBox.SelectedIndex = 0; + applicationComboBox.Items.Add("All applications"); + applicationComboBox.SelectedIndex = 0; + loadingFilters = false; } - private void SubForm_FormClosing(object sender, FormClosingEventArgs e) + + private void refreshTimer_Tick(object sender, EventArgs e) { + ProcessActivationRequest(); + RefreshView(false); + } + + private void ProcessActivationRequest() + { + if (activationRequestProvider == null || !activationRequestProvider()) + { + return; + } + + if (WindowState == FormWindowState.Minimized) + { + WindowState = FormWindowState.Normal; + } + + Show(); + BringToFront(); + Activate(); + } + + private void RefreshView(bool forceFullRefresh) + { + List snapshot = DiagnosticLogStore.Instance.GetSnapshot(); + UpdateApplicationFilter(snapshot); + + if (pauseButton.Checked) + { + UpdateStatus(snapshot.Count); + return; + } + + long currentVersion = DiagnosticLogStore.Instance.Version; + if (!forceFullRefresh && currentVersion == lastRenderedVersion) + { + UpdateStatus(snapshot.Count); + return; + } + + bool canAppend = !forceFullRefresh && snapshot.Count > observedEntryCount; + if (canAppend) + { + AppendEntries(snapshot.Skip(observedEntryCount)); + } + else + { + RebuildView(snapshot); + } + + observedEntryCount = snapshot.Count; + lastRenderedVersion = currentVersion; + UpdateStatus(snapshot.Count); + } + + private void RebuildView(IEnumerable entries) + { + logView.SuspendLayout(); + logView.Clear(); + visibleEntryCount = 0; + AppendEntries(entries, false); + logView.ResumeLayout(); + + if (autoScrollButton.Checked) + { + ScrollToEnd(); + } + } + + private void AppendEntries(IEnumerable entries, bool scrollAfterAppend = true) + { + int originalSelectionStart = logView.SelectionStart; + int originalSelectionLength = logView.SelectionLength; + + foreach (DiagnosticLogEntry entry in entries) + { + if (!MatchesFilter(entry)) + { + continue; + } + + AppendEntry(entry); + visibleEntryCount++; + } + + if (scrollAfterAppend && autoScrollButton.Checked) + { + ScrollToEnd(); + } + else if (!autoScrollButton.Checked) + { + int safeStart = Math.Min(originalSelectionStart, logView.TextLength); + int safeLength = Math.Min(originalSelectionLength, logView.TextLength - safeStart); + logView.Select(safeStart, safeLength); + } + } + + private void AppendEntry(DiagnosticLogEntry entry) + { + string text = DiagnosticLogFormatter.Format(entry); + + if (logView.TextLength > 0) + { + logView.AppendText(Environment.NewLine); + } + + int startIndex = logView.TextLength; + logView.AppendText(text); + LogColorizer.Apply(logView, startIndex, text.Length, text, colorRules, regularLogFont, boldLogFont); + logView.Select(logView.TextLength, 0); + } + + private bool MatchesFilter(DiagnosticLogEntry entry) + { + string selectedLevel = levelComboBox.SelectedItem as string; + if (!string.IsNullOrEmpty(selectedLevel) && selectedLevel != "All levels" && !string.Equals(entry.Level, selectedLevel, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + string selectedApplication = applicationComboBox.SelectedItem as string; + if (!string.IsNullOrEmpty(selectedApplication) && selectedApplication != "All applications" && !string.Equals(entry.ApplicationName, selectedApplication, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + string filter = filterTextBox.Text.Trim(); + return filter.Length == 0 || DiagnosticLogFormatter.Format(entry).IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0; + } + + private void UpdateApplicationFilter(IEnumerable entries) + { + string selectedApplication = applicationComboBox.SelectedItem as string ?? "All applications"; + List applications = entries.Select(entry => entry.ApplicationName).Where(name => !string.IsNullOrWhiteSpace(name)).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(name => name).ToList(); + List currentApplications = applicationComboBox.Items.Cast().Skip(1).ToList(); + + if (applications.SequenceEqual(currentApplications, StringComparer.OrdinalIgnoreCase)) + { + return; + } + + loadingFilters = true; + applicationComboBox.BeginUpdate(); + applicationComboBox.Items.Clear(); + applicationComboBox.Items.Add("All applications"); + applicationComboBox.Items.AddRange(applications.Cast().ToArray()); + applicationComboBox.SelectedItem = applicationComboBox.Items.Cast().FirstOrDefault(item => string.Equals(item, selectedApplication, StringComparison.OrdinalIgnoreCase)) ?? "All applications"; + applicationComboBox.EndUpdate(); + loadingFilters = false; + } + + private void UpdateStatus(int storedCount) + { + int clients = connectedClientCountProvider?.Invoke() ?? 0; + receiverStatusLabel.Text = pauseButton.Checked ? $"Paused | Connected sources: {clients}" : $"Listening | Connected sources: {clients}"; + countStatusLabel.Text = $"Received: {DiagnosticLogStore.Instance.TotalReceived:N0} | Stored: {storedCount:N0} | Visible: {visibleEntryCount:N0}"; + } + + private void ScrollToEnd() + { + logView.Select(logView.TextLength, 0); + logView.ScrollToCaret(); + } + + private void pauseButton_Click(object sender, EventArgs e) + { + pauseButton.Text = pauseButton.Checked ? "Resume" : "Pause"; + + if (!pauseButton.Checked) + { + RefreshView(true); + } + else + { + UpdateStatus(DiagnosticLogStore.Instance.GetSnapshot().Count); + } + } + + private void refreshButton_Click(object sender, EventArgs e) + { + RefreshView(true); + } + + private void clearButton_Click(object sender, EventArgs e) + { + DiagnosticLogStore.Instance.Clear(); + observedEntryCount = 0; + visibleEntryCount = 0; + RefreshView(true); + } + + private void saveButton_Click(object sender, EventArgs e) + { + using (var dialog = new SaveFileDialog()) + { + dialog.Filter = "Text files (*.txt)|*.txt|Log files (*.log)|*.log|All files (*.*)|*.*"; + dialog.Title = "Save visible diagnostic logs"; + dialog.DefaultExt = "log"; + dialog.FileName = $"AppDiagnostic_{DateTime.Now:yyyyMMdd_HHmmss}.log"; + + if (dialog.ShowDialog(this) != DialogResult.OK) + { + return; + } + + try + { + File.WriteAllText(dialog.FileName, logView.Text); + } + catch (Exception exception) + { + MessageBox.Show(this, $"Unable to save diagnostic logs: {exception.Message}", "Save error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void copyButton_Click(object sender, EventArgs e) + { + CopySelectionOrCurrentLine(); + } + + private void copySelectionMenuItem_Click(object sender, EventArgs e) + { + if (logView.SelectionLength > 0) + { + CopyText(logView.SelectedText); + } + } + + private void copyLineMenuItem_Click(object sender, EventArgs e) + { + CopyCurrentLine(); + } + + private void copyAllButton_Click(object sender, EventArgs e) + { + CopyText(logView.Text); + } + + private void CopySelectionOrCurrentLine() + { + if (logView.SelectionLength > 0) + { + CopyText(logView.SelectedText); + } + else + { + CopyCurrentLine(); + } + } + + private void CopyCurrentLine() + { + if (logView.Lines.Length == 0) + { + return; + } + + int lineIndex = logView.GetLineFromCharIndex(logView.SelectionStart); + if (lineIndex >= 0 && lineIndex < logView.Lines.Length) + { + CopyText(logView.Lines[lineIndex]); + } + } + + private void CopyText(string text) + { + if (string.IsNullOrEmpty(text)) + { + return; + } + try { - // Vaša logika pri uzatváraní formy - // this.Hide(); // Podforma sa len skryje + Clipboard.SetText(text); } - catch (Exception ex) + catch (Exception exception) { - // Ošetrenie výnimky - MessageBox.Show("Chyba pri zatváraní pod-aplikácie: " + ex.Message); + MessageBox.Show(this, $"Unable to copy text: {exception.Message}", "Clipboard error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } - private void SaveLogsToFile() + private void wrapButton_Click(object sender, EventArgs e) { - using (SaveFileDialog saveFileDialog = new SaveFileDialog()) - { - saveFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"; - saveFileDialog.Title = "Save TBF live logs"; - saveFileDialog.DefaultExt = "txt"; - saveFileDialog.FileName = "TBFLiveLogs.txt"; + logView.WordWrap = wrapButton.Checked; + } - if (saveFileDialog.ShowDialog() == DialogResult.OK) + private void alwaysOnTopButton_Click(object sender, EventArgs e) + { + TopMost = alwaysOnTopButton.Checked; + } + + private void colorRulesButton_Click(object sender, EventArgs e) + { + using (var editor = new ColorRuleEditorForm(colorRules)) + { + if (editor.ShowDialog(this) != DialogResult.OK) { - try - { - // Načítanie všetkých logov z LiveLogCache - var logs = LiveLogCache.Instance.GetLogs(0, LiveLogCache.Instance.GetCount()); - - // Uloženie logov do vybraného súboru - File.WriteAllLines(saveFileDialog.FileName, logs); - - MessageBox.Show("Logs saved successfully.", "Save TBF live logs", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - catch (Exception ex) - { - MessageBox.Show($"An error occurred while saving TBF live logs: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + return; } + + colorRules = editor.Rules; + + try + { + LogColorRuleRepository.Save(colorRules); + } + catch (Exception exception) + { + MessageBox.Show(this, $"Unable to save color rules: {exception.Message}", "Settings error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + RefreshView(true); } } - private void button2_Click(object sender, EventArgs e) + private void applyFilterButton_Click(object sender, EventArgs e) { - this.Close(); - //this.Hide(); // Podforma sa len skryje + RefreshView(true); } - private void MemoListView_DoubleClick(object sender, EventArgs e) + private void clearFilterButton_Click(object sender, EventArgs e) { - if (memoListView.SelectedItems.Count > 0) + loadingFilters = true; + filterTextBox.Clear(); + levelComboBox.SelectedIndex = 0; + applicationComboBox.SelectedIndex = 0; + loadingFilters = false; + RefreshView(true); + } + + private void filterValueChanged(object sender, EventArgs e) + { + if (!loadingFilters) { - var selectedItem = memoListView.SelectedItems[0]; - int selectedIndex = memoListView.Items.IndexOf(selectedItem); + RefreshView(true); + } + } - if (selectedIndex >= 0) - { - // Zrušenie filtra - _logAdapter._filterText = string.Empty; + private void filterTextBox_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + RefreshView(true); + e.SuppressKeyPress = true; + } + else if (e.KeyCode == Keys.Escape) + { + clearFilterButton_Click(sender, EventArgs.Empty); + e.SuppressKeyPress = true; + } + } - // Načítanie logov od indexu vybraného riadku - var logs = LiveLogCache.Instance.GetLogs(selectedIndex, LiveLogCache.Instance.GetCount() - selectedIndex); + private void closeButton_Click(object sender, EventArgs e) + { + Close(); + } - // Obnovenie ListView s novými údajmi - memoListView.BeginUpdate(); - memoListView.Items.Clear(); - foreach (var log in logs) - { - var item = new ListViewItem(log) - { - BackColor = memoListView.Items.Count % 2 == 0 ? Color.White : Color.FromArgb(240, 240, 240) - }; - memoListView.Items.Add(item); - } - memoListView.EndUpdate(); - } + private void MainForm_KeyDown(object sender, KeyEventArgs e) + { + if (e.Control && e.KeyCode == Keys.F) + { + filterTextBox.Focus(); + filterTextBox.SelectAll(); + e.SuppressKeyPress = true; + } + else if (e.Control && e.KeyCode == Keys.S) + { + saveButton_Click(sender, EventArgs.Empty); + e.SuppressKeyPress = true; + } + else if (e.KeyCode == Keys.F5) + { + RefreshView(true); + e.SuppressKeyPress = true; } } } diff --git a/AppDiagnostic/Program.cs b/AppDiagnostic/Program.cs index 6aaa9c232..eb17585bf 100644 --- a/AppDiagnostic/Program.cs +++ b/AppDiagnostic/Program.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -14,9 +15,26 @@ namespace AppDiagnostic [STAThread] static void Main() { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainForm()); + bool isFirstInstance; + + using (var instanceMutex = new Mutex(true, "Sensus.AppDiagnostic.SingleInstance", out isFirstInstance)) + using (var activationEvent = new EventWaitHandle(false, EventResetMode.AutoReset, "Sensus.AppDiagnostic.Activate")) + { + if (!isFirstInstance) + { + activationEvent.Set(); + return; + } + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + using (var diagnosticServer = new DiagnosticPipeServer(DiagnosticLogStore.Instance.Add)) + { + diagnosticServer.Start(); + Application.Run(new MainForm(() => diagnosticServer.ConnectedClientCount, () => activationEvent.WaitOne(0))); + } + } } } } diff --git a/TBF.sln b/TBF.sln index 999adf46f..cc5c09bef 100644 --- a/TBF.sln +++ b/TBF.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.5.11723.231 stable +VisualStudioVersion = 18.5.11723.231 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TBF", "TBF\TBF.csproj", "{8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}" ProjectSection(ProjectDependencies) = postProject @@ -106,11 +106,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabelPrinting", "LabelPrint EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TBFTests", "TBFTests\TBFTests.csproj", "{77EB589F-C670-4489-AAD6-2A3C02061FD1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppDiagnostic", "AppDiagnostic\AppDiagnostic.csproj", "{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}" - ProjectSection(ProjectDependencies) = postProject - {8F942729-F454-4C99-BA6C-746962065AE3} = {8F942729-F454-4C99-BA6C-746962065AE3} - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedComponents", "SharedComponents\SharedComponents.csproj", "{8F942729-F454-4C99-BA6C-746962065AE3}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sensus.iPerl.RfidCom", "..\iPerlHead\Sensus.iPerl.RfidCom\Sensus.iPerl.RfidCom.csproj", "{A3E14180-7F00-42E5-94A9-8DB62EAD6EE8}" @@ -208,6 +203,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools.JsonToXlsHelper", "Ex EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagFluxConfig", "ExternalProjects\Laatzen\Genesis\Common\Hardware\WaterMeter\MagFlux\MagFluxConfig\MagFluxConfig.csproj", "{70398B99-B134-4BBD-968B-7399B70C3CE2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppDiagnostic", "AppDiagnostic\AppDiagnostic.csproj", "{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppDiagnostic.Logging", "AppDiagnostic.Logging\AppDiagnostic.Logging.csproj", "{A7AF8ED2-362E-4DBB-B607-EBA2820719EC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution _MANUAL_CONTROL|Any CPU = _MANUAL_CONTROL|Any CPU @@ -2638,78 +2637,6 @@ Global {77EB589F-C670-4489-AAD6-2A3C02061FD1}.XP32bit|x64.Build.0 = Release|Any CPU {77EB589F-C670-4489-AAD6-2A3C02061FD1}.XP32bit|x86.ActiveCfg = Release|Any CPU {77EB589F-C670-4489-AAD6-2A3C02061FD1}.XP32bit|x86.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Any CPU.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Any CPU.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Mixed Platforms.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x64.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x64.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x86.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x86.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x64.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x64.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x86.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x86.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Any CPU.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Any CPU.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Mixed Platforms.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Mixed Platforms.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x64.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x64.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x86.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x86.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Any CPU.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x64.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x64.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x86.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x86.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Any CPU.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x64.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x64.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x86.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x86.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x64.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x64.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x86.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x86.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Any CPU.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x64.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x64.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x86.ActiveCfg = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x86.Build.0 = Debug|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Any CPU.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x64.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x64.Build.0 = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x86.ActiveCfg = Release|Any CPU - {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x86.Build.0 = Release|Any CPU {8F942729-F454-4C99-BA6C-746962065AE3}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU {8F942729-F454-4C99-BA6C-746962065AE3}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU {8F942729-F454-4C99-BA6C-746962065AE3}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU @@ -5806,6 +5733,150 @@ Global {70398B99-B134-4BBD-968B-7399B70C3CE2}.XP32bit|x64.Build.0 = Debug|Any CPU {70398B99-B134-4BBD-968B-7399B70C3CE2}.XP32bit|x86.ActiveCfg = Debug|Any CPU {70398B99-B134-4BBD-968B-7399B70C3CE2}.XP32bit|x86.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Any CPU.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Any CPU.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|Mixed Platforms.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x64.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x64.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x86.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.COM|x86.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x64.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x64.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x86.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x86.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Any CPU.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Any CPU.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|Mixed Platforms.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x64.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x64.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x86.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug-local IIS-CUST|x86.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Any CPU.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Any CPU.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|Mixed Platforms.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x64.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x64.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x86.ActiveCfg = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.PerformTest|x86.Build.0 = Debug|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Any CPU.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x64.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x64.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x86.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x86.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x64.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x64.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x86.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.ReleaseTest|x86.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Any CPU.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Any CPU.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Mixed Platforms.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|Mixed Platforms.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x64.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x64.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x86.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.VPN_Debug|x86.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Any CPU.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x64.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x64.Build.0 = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x86.ActiveCfg = Release|Any CPU + {FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.XP32bit|x86.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|Any CPU.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|Any CPU.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|Mixed Platforms.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|x64.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|x64.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|x86.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.COM|x86.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|x64.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|x64.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|x86.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug|x86.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|Any CPU.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|Any CPU.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|Mixed Platforms.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|x64.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|x64.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|x86.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Debug-local IIS-CUST|x86.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|Any CPU.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|Any CPU.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|Mixed Platforms.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|x64.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|x64.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|x86.ActiveCfg = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.PerformTest|x86.Build.0 = Debug|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|Any CPU.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|x64.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|x64.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|x86.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.Release|x86.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|x64.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|x64.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|x86.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.ReleaseTest|x86.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|Any CPU.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|Any CPU.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|Mixed Platforms.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|Mixed Platforms.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|x64.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|x64.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|x86.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.VPN_Debug|x86.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|Any CPU.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|x64.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|x64.Build.0 = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|x86.ActiveCfg = Release|Any CPU + {A7AF8ED2-362E-4DBB-B607-EBA2820719EC}.XP32bit|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TBF/Program.cs b/TBF/Program.cs index 223cdd3fc..8c019fa82 100644 --- a/TBF/Program.cs +++ b/TBF/Program.cs @@ -19,32 +19,32 @@ namespace TBF { public class Program { - public const string HomeDir = "C:\\Tbf\\"; /// Contains subdirectories Results, Logs, Images, ... - public const string ConfigDir = "C:\\Tbf\\Cfg\\"; + public const string HomeDir = "C:\\Tbf\\"; /// Contains subdirectories Results, Logs, Images, ... + public const string ConfigDir = "C:\\Tbf\\Cfg\\"; public const string GraphsDir = "C:\\Tbf\\Graphs\\"; public const string ImagesDir = "C:\\Tbf\\Images\\"; - public const string TempImagesDir = "C:\\Tbf\\Images\\Temp\\"; + public const string TempImagesDir = "C:\\Tbf\\Images\\Temp\\"; public static string ExecutableDir; - /// log4net - static ILog log; - const string log4netConfigFName = "log4netConfig.xml"; + /// log4net + static ILog log; + const string log4netConfigFName = "log4netConfig.xml"; /// Program information public static string Version; /// version string - public static DateTime BuildDateTime; /// date and time of program build + public static DateTime BuildDateTime; /// date and time of program build - /// Local settings - public static LocalSettings LocalSettings; - public const string LocalSettingsFileName = "config.xml"; - public const string LocalSettingsBackupName = "config.backup.xml"; + /// Local settings + public static LocalSettings LocalSettings; + public const string LocalSettingsFileName = "config.xml"; + public const string LocalSettingsBackupName = "config.backup.xml"; + + public static System.Globalization.CultureInfo AltCulture; - public static System.Globalization.CultureInfo AltCulture; - static IList listOfProcedures; - - /// + + /// /// Selected procedure data /// - before the main program window is open, objects referenced by this variable /// are loaded from the database. @@ -69,18 +69,18 @@ namespace TBF [STAThread] static void Main() { - AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); + AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); /// Program version string System.Reflection.Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly(); ExecutableDir = Path.GetDirectoryName(thisAssembly.Location); Version ver = thisAssembly.GetName().Version; Version = string.Format("{0}.{1}.{2}", ver.Major, ver.Minor, ver.Build); - BuildDateTime = new System.IO.FileInfo(thisAssembly.Location).LastWriteTime; + BuildDateTime = new System.IO.FileInfo(thisAssembly.Location).LastWriteTime; /// Local program configuration directory including the trailing backslash string locAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + - Path.DirectorySeparatorChar + "TestBenchFramework" + Path.DirectorySeparatorChar; + Path.DirectorySeparatorChar + "TestBenchFramework" + Path.DirectorySeparatorChar; string sampleConfigDir = Application.StartupPath + Path.DirectorySeparatorChar + "SampleConfig" + Path.DirectorySeparatorChar; @@ -108,7 +108,7 @@ namespace TBF if (File.Exists(locAppDataDir + LocalSettingsBackupName)) File.Copy(locAppDataDir + LocalSettingsBackupName, LocalSettingsBackupName); - + if (File.Exists(locAppDataDir + log4netConfigFName)) File.Copy(locAppDataDir + log4netConfigFName, log4netConfigFName); else if (File.Exists(sampleConfigDir + log4netConfigFName)) @@ -138,67 +138,67 @@ namespace TBF Environment.CurrentDirectory = ConfigDir; } - if (!Directory.Exists(ImagesDir)) Directory.CreateDirectory(ImagesDir); - if (!Directory.Exists(TempImagesDir)) Directory.CreateDirectory(TempImagesDir); + if (!Directory.Exists(ImagesDir)) Directory.CreateDirectory(ImagesDir); + if (!Directory.Exists(TempImagesDir)) Directory.CreateDirectory(TempImagesDir); - IEnumerable files = Directory.EnumerateFiles(TempImagesDir); /// TODO: Implement recursive directory delete + IEnumerable files = Directory.EnumerateFiles(TempImagesDir); /// TODO: Implement recursive directory delete foreach (var file in files) File.Delete(file); - } + } catch (Exception) { MessageBox.Show("Error creating a local application data directory and preparing an initial configuration", "Fatal error"); - return; /// Fatal error + return; /// Fatal error } - /// Configure and start logging + /// Configure and start logging log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(ConfigDir + log4netConfigFName)); - log = LogManager.GetLogger(typeof(Program)); - log.Fatal("--------------------------------------------------------------------------------"); - log.Fatal(string.Format("TBF ver.{0}", Version)); + log = LogManager.GetLogger(typeof(Program)); + log.Fatal("--------------------------------------------------------------------------------"); + log.Fatal(string.Format("TBF ver.{0}", Version)); - /// + /// /// Load the local settings - /// - Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsFileName); - if (Program.LocalSettings == null || Program.LocalSettings.TestBenches == null) - { - /// Loading local seetings from regular config file failed. Use the backup - Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsBackupName); - if (Program.LocalSettings == null || Program.LocalSettings.TestBenches == null) - { - log.Fatal("Application terminated."); - MessageBox.Show(string.Format("Could not load file {0}, nor {1}.", Program.LocalSettingsFileName, Program.LocalSettingsBackupName), "Fatal error"); - return; /// Fatal error + /// + Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsFileName); + if (Program.LocalSettings == null || Program.LocalSettings.TestBenches == null) + { + /// Loading local seetings from regular config file failed. Use the backup + Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsBackupName); + if (Program.LocalSettings == null || Program.LocalSettings.TestBenches == null) + { + log.Fatal("Application terminated."); + MessageBox.Show(string.Format("Could not load file {0}, nor {1}.", Program.LocalSettingsFileName, Program.LocalSettingsBackupName), "Fatal error"); + return; /// Fatal error } - else - { - LocalSettings.Save(); /// Save the settings to overwrite the wrong file + else + { + LocalSettings.Save(); /// Save the settings to overwrite the wrong file log.FatalFormat("BatchNr = {0}", LocalSettings.BatchNr); - } - } - else - { - /// Loading local seetings from the regular config file was successful. Update the backup - File.Copy(Program.LocalSettingsFileName, Program.LocalSettingsBackupName, true); - log.FatalFormat("BatchNr = {0}", LocalSettings.BatchNr); - } + } + } + else + { + /// Loading local seetings from the regular config file was successful. Update the backup + File.Copy(Program.LocalSettingsFileName, Program.LocalSettingsBackupName, true); + log.FatalFormat("BatchNr = {0}", LocalSettings.BatchNr); + } - try - { - string culture = LocalSettings.Language.Replace('_', '-'); - System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture); - } - catch (Exception e) - { - string msg = e.Message; - MessageBox.Show("Selected language not supported.\nUsing English.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); - System.Threading.Thread.CurrentThread.CurrentUICulture = - new System.Globalization.CultureInfo("en"); - } + try + { + string culture = LocalSettings.Language.Replace('_', '-'); + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture); + } + catch (Exception e) + { + string msg = e.Message; + MessageBox.Show("Selected language not supported.\nUsing English.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); + System.Threading.Thread.CurrentThread.CurrentUICulture = + new System.Globalization.CultureInfo("en"); + } - //AltCulture = null; - AltCulture = new System.Globalization.CultureInfo("SK"); + //AltCulture = null; + AltCulture = new System.Globalization.CultureInfo("SK"); /// This belongs to Application.Run(new MainWnd()) ... @@ -207,28 +207,28 @@ namespace TBF Application.SetCompatibleTextRenderingDefault(false); - /// Ensure that there is at least one bench in the configuration - while (Program.LocalSettings.BenchesCount == 0) - { - log.Warn("No test benches in the local configuration -> display an appropriate dialog."); + /// Ensure that there is at least one bench in the configuration + while (Program.LocalSettings.BenchesCount == 0) + { + log.Warn("No test benches in the local configuration -> display an appropriate dialog."); - /// Ask what to do, ask for the password, open 'DatabaseSetingsDlg' and continue on OK - if ((new NoBenchOrDatabaseDlg { Message = Strings.NoBenchMsg }.ShowDialog() != DialogResult.OK) || - (new SharedDatabase.Forms.LoginDlg(true).ShowDialog() == DialogResult.Cancel) || + /// Ask what to do, ask for the password, open 'DatabaseSetingsDlg' and continue on OK + if ((new NoBenchOrDatabaseDlg { Message = Strings.NoBenchMsg }.ShowDialog() != DialogResult.OK) || + (new SharedDatabase.Forms.LoginDlg(true).ShowDialog() == DialogResult.Cancel) || (new TBF.UI.Settings.BenchesDlg().ShowDialog() == DialogResult.Cancel)) - { - return; /// Exit program + { + return; /// Exit program } - log.Warn("Loading the local settings again."); - Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsFileName); - if (Program.LocalSettings == null) return; /// Fatal error + log.Warn("Loading the local settings again."); + Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsFileName); + if (Program.LocalSettings == null) return; /// Fatal error } /// User login bool retryLogin = true; /// true = stay in a login loop do - { + { LoadingConfigEnd(); LoginDlgWithBenchSelection loginDlgBench; @@ -240,8 +240,8 @@ namespace TBF { loginDlgBench = new LoginDlgWithBenchSelection(); } - loginDlgBench.Method = LocalSettings.LoginMethod; - DialogResult dr = loginDlgBench.ShowDialog(); + loginDlgBench.Method = LocalSettings.LoginMethod; + DialogResult dr = loginDlgBench.ShowDialog(); if (dr == DialogResult.Cancel) { @@ -253,11 +253,11 @@ namespace TBF { if (LocalSettings.TestBenches[i].BenchName == loginDlgBench.BenchName) { - log.FatalFormat("Test bench name: {0}", loginDlgBench.BenchName); + log.FatalFormat("Test bench name: {0}", loginDlgBench.BenchName); LoadingConfigStart(); - CurrentUser.RemoteUsersDB = LocalSettings.TestBenches[i].UsersDBSettings; - CurrentUser.LocalUsersDB = LocalSettings.TestBenches[i].ProceduresDBSettings; + CurrentUser.RemoteUsersDB = LocalSettings.TestBenches[i].UsersDBSettings; + CurrentUser.LocalUsersDB = LocalSettings.TestBenches[i].ProceduresDBSettings; SharedDatabase.Entities.User loadedUser = null; try @@ -268,32 +268,32 @@ namespace TBF GID[] reqGrpMembership = null; #endif bool authorized = false; - AuthorizedAs authorizedAs = AuthorizedAs.PowerUser; + AuthorizedAs authorizedAs = AuthorizedAs.PowerUser; if (Common.Utils.IsPowerUser(loginDlgBench.Alias, loginDlgBench.Password)) - { - loadedUser = new SharedDatabase.Entities.User(loginDlgBench.Alias, 6, true); + { + loadedUser = new SharedDatabase.Entities.User(loginDlgBench.Alias, 6, true); authorized = loadedUser.Authorize(loginDlgBench.Alias, loginDlgBench.Password, reqGrpMembership, null); if (authorized) { CurrentUser.AuthorizedAs = AuthorizedAs.PowerUser; } - } + } /// /// Authorisation using databases /// if (!authorized) - { - DBSettings[] dbs = new DBSettings[] { CurrentUser.RemoteUsersDB, CurrentUser.LocalUsersDB }; + { + DBSettings[] dbs = new DBSettings[] { CurrentUser.RemoteUsersDB, CurrentUser.LocalUsersDB }; - authorizedAs = AuthorizedAs.RemoteUser; /// Try remote DB first + authorizedAs = AuthorizedAs.RemoteUser; /// Try remote DB first - foreach (var db in dbs) - { - /// Load and authorise user from the UsersDB database - try - { + foreach (var db in dbs) + { + /// Load and authorise user from the UsersDB database + try + { if (loginDlgBench.Password == LoginDlgWithBenchSelection.UseTheTagPassword) { loadedUser = SharedDatabase.Entities.User.LoadUserByTag(loginDlgBench.Alias, db); @@ -320,24 +320,24 @@ namespace TBF break; } } - } - catch - { - authorized = false; - } + } + catch + { + authorized = false; + } - if (authorized) break; + if (authorized) break; - authorizedAs = AuthorizedAs.LocalUser; /// Try local DB afterwards + authorizedAs = AuthorizedAs.LocalUser; /// Try local DB afterwards } - } + } - if (authorized) + if (authorized) { loadedUser.SetLegalizator(loginDlgBench.Legalizator); CurrentUser.AuthorizedAs = authorizedAs; - - LocalSettings.LoginMethod = loginDlgBench.Method; /// Save the login method actually used + + LocalSettings.LoginMethod = loginDlgBench.Method; /// Save the login method actually used if (LocalSettings.TestBenches[i].IsRealBench) { @@ -349,9 +349,9 @@ namespace TBF return; } } - + log.InfoFormat("Password accepted, bench '{0}' parameters loaded.", - LocalSettings.TestBenches[i].BenchName); + LocalSettings.TestBenches[i].BenchName); /// Copy the selected bench settings to CurrentBench. /// Clone() guarantees that current bench settings wont be modified @@ -448,31 +448,31 @@ namespace TBF /// Ask what to do switch ((new NoBenchOrDatabaseDlg { Message = Strings.NoDatabaseMsg, ShowRetry = true }).ShowDialog()) - { - case DialogResult.Abort: + { + case DialogResult.Abort: return; /// Exit program - - case DialogResult.Retry: + + case DialogResult.Retry: break; /// Retry connection to the database, stay inside the loop - + case DialogResult.Yes: new TBF.UI.Settings.UpgradeSelectionDlg().ShowDialog(); break; /// Stay inside the loop - default: - /// Open 'DatabaseSetingsDlg' and retry DB connect on OK + default: + /// Open 'DatabaseSetingsDlg' and retry DB connect on OK if (new SharedDatabase.Forms.LoginDlg(true).ShowDialog() == DialogResult.Cancel || new TBF.UI.Settings.BenchesDlg().ShowDialog() == DialogResult.Cancel) - { - return; /// Exit program + { + return; /// Exit program } - if (Program.LocalSettings == null) + if (Program.LocalSettings == null) return; /// Fatal error -> Exit program else - break; /// Stay inside the loop + break; /// Stay inside the loop } - } - } // if benchname is OK + } + } // if benchname is OK } // for all benches in local settings loop } // not Canceled } //do @@ -485,53 +485,56 @@ namespace TBF { if (listOfProcedures != null && listOfProcedures.Count == 1) { - log.InfoFormat("Pre-selecting the procedure {0}", LocalSettings.LastProcedureName); - SelectedProcedure = listOfProcedures[0]; + log.InfoFormat("Pre-selecting the procedure {0}", LocalSettings.LastProcedureName); + SelectedProcedure = listOfProcedures[0]; } } - try - { + //AppDiagnostic SDK - nlog connector registration + AppDiagnostic.Logging.AppDiagnosticConnector.Register(); + + try + { /// Open the main application window log.Info("Creating the main window"); - MainWnd = new UI.MainWnd(); - log.Info("Opening the main window"); + MainWnd = new UI.MainWnd(); + log.Info("Opening the main window"); LoadingConfigEnd(); Application.Run(MainWnd); - log.Info("The main window was closed"); - } - catch (Exception e) - { - LogException(log, "Exception in Application.Run(MainWnd)", e); - } - finally - { - /// Save local settings - LocalSettings.Save(); - } + log.Info("The main window was closed"); + } + catch (Exception e) + { + LogException(log, "Exception in Application.Run(MainWnd)", e); + } + finally + { + /// Save local settings + LocalSettings.Save(); + } /// Close Fluent NHibernate /// Todo - - log.Info("Exiting application."); + + log.Info("Exiting application."); } - static void MyHandler(object sender, UnhandledExceptionEventArgs args) - { - LogException(log, "Unhandled exception", (Exception)args.ExceptionObject); - } + static void MyHandler(object sender, UnhandledExceptionEventArgs args) + { + LogException(log, "Unhandled exception", (Exception)args.ExceptionObject); + } - static void LogException(ILog log, string description, Exception e) - { - log.FatalFormat("---------------( {0} )---------------", description); - log.FatalFormat("Message : {0}", e.Message); - if (e.InnerException != null) - { - log.FatalFormat("InnerMessage : {0}", e.InnerException.Message); - } - log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace); - log.Fatal("--------------------------------------"); - } + static void LogException(ILog log, string description, Exception e) + { + log.FatalFormat("---------------( {0} )---------------", description); + log.FatalFormat("Message : {0}", e.Message); + if (e.InnerException != null) + { + log.FatalFormat("InnerMessage : {0}", e.InnerException.Message); + } + log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace); + log.Fatal("--------------------------------------"); + } static UI.Shared.ModelessActivityForm form; @@ -562,5 +565,5 @@ namespace TBF form = null; formThread = null; } - } + } } \ No newline at end of file diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index 71b56aa0e..b9c766b6c 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -4595,9 +4595,9 @@ {5954d496-caab-4f7a-bde2-bdc8f47dab19} NfcS5_DLL - - {fa9abad1-7184-4295-ade8-d44f2e3de6b2} - AppDiagnostic + + {a7af8ed2-362e-4dbb-b607-eba2820719ec} + AppDiagnostic.Logging {c8939821-ba5c-4988-a3d0-bf53b74865c7} @@ -4694,4 +4694,9 @@ + + if not exist "$(TargetDir)AppDiagnostic\" mkdir "$(TargetDir)AppDiagnostic\" +xcopy /Y /E /I "$(SolutionDir)AppDiagnostic\bin\$(ConfigurationName)\*" "$(TargetDir)AppDiagnostic\" +if errorlevel 1 exit /b 1 + \ No newline at end of file diff --git a/TBF/UI/MainWnd.cs b/TBF/UI/MainWnd.cs index 8bb041a6f..70933832a 100644 --- a/TBF/UI/MainWnd.cs +++ b/TBF/UI/MainWnd.cs @@ -22,6 +22,8 @@ using SharedComponents; using System.Diagnostics; using TBF.Rig.TestMethods.iPerlCommunication; using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication; +using System.Diagnostics; +using System.IO; namespace TBF.UI { @@ -31,6 +33,7 @@ namespace TBF.UI public partial class MainWnd : Form { static readonly ILog log = LogManager.GetLogger(typeof(MainWnd)); + private static readonly NLog.Logger diagnosticLogger = NLog.LogManager.GetCurrentClassLogger(); /// Used when re-scaling the dialog: 100% = 96dpi, 125% = 120dpi, 150% = 144dpi public static int Dpi; @@ -49,7 +52,7 @@ namespace TBF.UI IList tracingDBOrders; /// Production orders loaded from the production tracing DB IList oracleOrders; /// Production orders loaded from the Oracle DB IList procedureInfos; /// Composed procedure infos - /// + /// public ProcedureInfo SelectedProcedure; public Procedure CurrentProcedure; @@ -58,7 +61,7 @@ namespace TBF.UI /// Shared.ModelessActivityForm closingTbfMessageForm; - TestProgressControls testProgressControls; + TestProgressControls testProgressControls; /// /// Set when procedures are updated while the ProceduresComboBox is disabled (i.e. during a test). @@ -78,36 +81,36 @@ namespace TBF.UI { Invalid = -1, Hydraulics = 0, - Process, + Process, Insert, - Results, + Results, Graphs, Events, Calendar, Camera, - TabPagesCount + TabPagesCount } /// /// Event handlers switching between tab pages /// private void homeTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Hydraulics); } - private void processTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Process); } - private void resultsTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Results); } - private void graphsToolStripMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Graphs); } - private void eventsTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Events); } + private void processTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Process); } + private void resultsTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Results); } + private void graphsToolStripMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Graphs); } + private void eventsTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Events); } private void calendarTSMenuItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Calendar); } #if CAMERA - private System.Windows.Forms.ToolStripMenuItem cameraTSMItem; - private void cameraTSMItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Camera); } + private System.Windows.Forms.ToolStripMenuItem cameraTSMItem; + private void cameraTSMItem_Click(object sender, EventArgs e) { mainTabControl.SelectTab((int)MainTabPageId.Camera); } #endif /// DB entities of components loaded in the MainWnd constructor IList cmpntEntities; - /// + /// /// Constructor /// public MainWnd() @@ -130,24 +133,24 @@ namespace TBF.UI procedureInfos = new List(); SelectedProcedure = null; CurrentProcedure = null; - - /// - /// Customize menu items - /// -#if CAMERA - /// Add 'Camera' menu item - cameraTSMItem = new System.Windows.Forms.ToolStripMenuItem(); - cameraTSMItem.Name = "cameraTSMItem"; - cameraTSMItem.Text = Strings.Camera; - cameraTSMItem.Click += new System.EventHandler(this.cameraTSMItem_Click); - - mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {this.cameraTSMItem}); + /// + /// Customize menu items + /// +#if CAMERA + /// Add 'Camera' menu item + cameraTSMItem = new System.Windows.Forms.ToolStripMenuItem(); + + cameraTSMItem.Name = "cameraTSMItem"; + cameraTSMItem.Text = Strings.Camera; + cameraTSMItem.Click += new System.EventHandler(this.cameraTSMItem_Click); + + mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.cameraTSMItem }); #endif UpdateMenuItemsVisibility(); optoHeadsToolStripMenuItem.Visible = true; - optoHeadsToolStripMenuItem.Enabled = false; + optoHeadsToolStripMenuItem.Enabled = false; IsShutdownDisabled = true; IsShutdownPCAfterClosingTbf = false; @@ -166,11 +169,11 @@ namespace TBF.UI Rig.StateMachine.MachineState = TBF.DB.CurrentBench.IsRealBench ? Rig.MachineState.StartingUp : Rig.MachineState.Disabled; - #if DEBUG +#if DEBUG //define always valid for printer test - BUMI Rig.StateMachine.MachineState = Rig.MachineState.StartingUp; - #endif - +#endif + /// if (Rig.StateMachine.MachineState == Rig.MachineState.StartingUp) { @@ -230,20 +233,20 @@ namespace TBF.UI } } - void Localize() - { + void Localize() + { /// /// Menu /// benchTSMenuItem.Text = Strings.Bench; - benchComponentsTSMenuItem.Text = Strings.Components; - benchPathsTSMenuItem.Text = Strings.Paths; - benchTransitionsToolStripMenuItem.Text = Strings.Transitions; - benchMetrologyTSMenuItem.Text = Strings.Metrology; - benchUncertaintyTSMItem.Text = Strings.Uncertainty; - benchTestProfilesTSMItem.Text = Strings.Test_profiles; - editSchDrawingTSMItem.Text = Strings.Edit_schematic_drawing; - exitToolStripMenuItem.Text = Strings.Exit; + benchComponentsTSMenuItem.Text = Strings.Components; + benchPathsTSMenuItem.Text = Strings.Paths; + benchTransitionsToolStripMenuItem.Text = Strings.Transitions; + benchMetrologyTSMenuItem.Text = Strings.Metrology; + benchUncertaintyTSMItem.Text = Strings.Uncertainty; + benchTestProfilesTSMItem.Text = Strings.Test_profiles; + editSchDrawingTSMItem.Text = Strings.Edit_schematic_drawing; + exitToolStripMenuItem.Text = Strings.Exit; proceduresToolStripMenuItem.Text = Strings.Procedures; homeTSMenuItem.Text = Strings.Home; processToolStripMenuItem.Text = Strings.Process; @@ -252,31 +255,31 @@ namespace TBF.UI eventLogsTSMenuItem.Text = Strings.Event_logs; calendarTSMenuItem.Text = Strings.Calendar; settingsTSMenuItem.Text = Strings.Settings; - usersTSMenuItem.Text = Strings.Users; - languageTSMItem.Text = Strings.Language; - databaseSettingsTSMenuItem.Text = Strings.Database; - backUpTSMItem.Text = Strings.Backup; - backUpConfigTSMItem.Text = Strings.Configuration; - backUpResultsTSMItem.Text = Strings.Results; - passwdTSMItem.Text = Strings.Password; - upgradeTSMenuItem.Text = Strings.Upgrade_DB; + usersTSMenuItem.Text = Strings.Users; + languageTSMItem.Text = Strings.Language; + databaseSettingsTSMenuItem.Text = Strings.Database; + backUpTSMItem.Text = Strings.Backup; + backUpConfigTSMItem.Text = Strings.Configuration; + backUpResultsTSMItem.Text = Strings.Results; + passwdTSMItem.Text = Strings.Password; + upgradeTSMenuItem.Text = Strings.Upgrade_DB; appDiagnosticMenuItem.Text = Strings.Application_Diagnostic; optoHeadsToolStripMenuItem.Text = Strings.Optical_heads; - clearCountersToolStripMenuItem.Text = Strings.Clear_counters; + clearCountersToolStripMenuItem.Text = Strings.Clear_counters; helpTSMenuItem.Text = Strings.Help; - aboutTSMenuItem.Text = Strings.About; - + aboutTSMenuItem.Text = Strings.About; + procedureGroupBox.Text = Strings.Procedure; - activityGroupBox.Text = Strings.Activity; - progressGroupBox.Text = Strings.Progress; - } + activityGroupBox.Text = Strings.Activity; + progressGroupBox.Text = Strings.Progress; + } /// /// Initializes this window and its controls /// private void MainWnd_Load(object sender, EventArgs e) { - Localize(); + Localize(); TBF.LocalSettings ls = Program.LocalSettings; WindowState = (ls.MainWndMaximized ? FormWindowState.Maximized : FormWindowState.Normal); @@ -297,23 +300,23 @@ namespace TBF.UI if (TBF.Rig.StateMachine.MachineState == TBF.Rig.MachineState.StartingUp) { - var form = new Shared.ModelessActivityForm() - { - Message = Strings.Starting_system, - FontFamily = "Arial", - FontSize = 24, - FontStyle = FontStyle.Regular, - BackgroundColor = Color.OliveDrab, /// or Color.YellowGreen - StartActivityHandler = true, - }; - Thread formThread = new Thread(() => form.ShowDialog()); - formThread.Start(); + var form = new Shared.ModelessActivityForm() + { + Message = Strings.Starting_system, + FontFamily = "Arial", + FontSize = 24, + FontStyle = FontStyle.Regular, + BackgroundColor = Color.OliveDrab, /// or Color.YellowGreen + StartActivityHandler = true, + }; + Thread formThread = new Thread(() => form.ShowDialog()); + formThread.Start(); try { string message = Rig.StateMachine.InitializeDevices(); - form.CloseForm(null, new EventArgs()); - formThread.Join(); + form.CloseForm(null, new EventArgs()); + formThread.Join(); #if !DEBUG if (message != null) { @@ -324,43 +327,43 @@ namespace TBF.UI } #endif - Bridge.ButtonsEtcHandler += delegate(object sndr, ButtonsEtcEventArgs args) + Bridge.ButtonsEtcHandler += delegate (object sndr, ButtonsEtcEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(OnButtonsEtc), sndr, args); } else OnButtonsEtc(sndr, args); }; - Bridge.ActivityHandler += delegate(object sndr, UiBridge.ActivityEventArgs args) + Bridge.ActivityHandler += delegate (object sndr, UiBridge.ActivityEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(OnActivity), sndr, args); } else OnActivity(sndr, args); }; - Bridge.StateChangedHandler += delegate(object sndr, UiBridge.StateChangedEventArgs args) + Bridge.StateChangedHandler += delegate (object sndr, UiBridge.StateChangedEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(OnStateChanged), sndr, args); } else OnStateChanged(sndr, args); }; - Bridge.StateMachineTickHandler += delegate(object sndr, UiBridge.StateMachineTickEventArgs args) + Bridge.StateMachineTickHandler += delegate (object sndr, UiBridge.StateMachineTickEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(OnStateMachineTick), sndr, args); } else OnStateMachineTick(sndr, args); }; - Bridge.TestProgressHandler += delegate(object sndr, UiBridge.TestProgressEventArgs args) + Bridge.TestProgressHandler += delegate (object sndr, UiBridge.TestProgressEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(OnTestProgress), sndr, args); } else OnTestProgress(sndr, args); }; - Bridge.ProcedureSelectedHandler += delegate(object sndr, UiBridge.ProcedureSelectedEventArgs args) + Bridge.ProcedureSelectedHandler += delegate (object sndr, UiBridge.ProcedureSelectedEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(OnProcedureSelected), sndr, args); } else OnProcedureSelected(sndr, args); }; - Bridge.SaveSettingsHandler += delegate(object sndr, UiBridge.SaveSettingsEventArgs args) + Bridge.SaveSettingsHandler += delegate (object sndr, UiBridge.SaveSettingsEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(OnSaveSettings), sndr, args); } else OnSaveSettings(sndr, args); @@ -370,10 +373,10 @@ namespace TBF.UI { TBF.Rig.StateMachine.MachineState = TBF.Rig.MachineState.FailedToStart; - form.CloseForm(null, new EventArgs()); - formThread.Join(); + form.CloseForm(null, new EventArgs()); + formThread.Join(); - string errMsg = string.Format(Strings.Failed_to_initialize_device_0_1_2, + string errMsg = string.Format(Strings.Failed_to_initialize_device_0_1_2, Rig.StateMachine.CurrentlyInitializedComponentName, Environment.NewLine, exc.Message); @@ -390,26 +393,26 @@ namespace TBF.UI SelectedProcedure = new ProcedureInfo(ls.LastProcedureSource, ls.LastProcedureNr, ls.LastProcedureName, signature); procedureComboBox.Text = SelectedProcedure.ToString(); - rightHorizSplitContainer.SplitterDistance = Program.LocalSettings.RightPaneHorizSplitterDistance; - topVerticalSplitContainer.SplitterDistance = Program.LocalSettings.TopPaneVerticalSplitterDistance; + rightHorizSplitContainer.SplitterDistance = Program.LocalSettings.RightPaneHorizSplitterDistance; + topVerticalSplitContainer.SplitterDistance = Program.LocalSettings.TopPaneVerticalSplitterDistance; - /// Initialize bench control user interface(s) - BenchControlPanel = new BenchControlPanel(); + /// Initialize bench control user interface(s) + BenchControlPanel = new BenchControlPanel(); BenchControlPanel.BalancesCount = TBF.Rig.StateMachine.Tank3 != null ? 3 : TBF.Rig.StateMachine.Tank2 != null ? 2 : TBF.Rig.StateMachine.Tank1 != null ? 1 : 0; - new System.ComponentModel.ComponentResourceManager(typeof(MainWnd)).ApplyResources(BenchControlPanel, "benchControlPanel"); - BenchControlPanel.Name = "benchControlPanel"; - rightHorizSplitContainer.Panel2.Controls.Add(BenchControlPanel); + new System.ComponentModel.ComponentResourceManager(typeof(MainWnd)).ApplyResources(BenchControlPanel, "benchControlPanel"); + BenchControlPanel.Name = "benchControlPanel"; + rightHorizSplitContainer.Panel2.Controls.Add(BenchControlPanel); - ReloadProcedureComboBoxItems(); + ReloadProcedureComboBoxItems(); /// Select the initial tab page mainTabControl.SelectTab((int)MainTabPageId.Process); /// This is to load the 'Process screen' mainTabControl.SelectTab((int)MainTabPageId.Calendar); /// This is to load the 'Calendar screen' UpdateUser(); - mainTabControl.SelectTab((int)MainTabPageId.Hydraulics); + mainTabControl.SelectTab((int)MainTabPageId.Hydraulics); processTabPageCtrl.Settings2UI(); @@ -422,10 +425,10 @@ namespace TBF.UI string[] edgesLcfg = null; string[] edgesXLcfg = null; /// - var schDrawingCmpnts = (TBF.DB.CurrentBench.IsRealBench && Rig.StateMachine.Components != null) + var schDrawingCmpnts = (TBF.DB.CurrentBench.IsRealBench && Rig.StateMachine.Components != null) ? Rig.StateMachine.Components : TBF.Rig.TbfComponents.LoadComponentsFromDB(cmpntEntities); - + foreach (var component in schDrawingCmpnts) { TBF.Rig.Generic.IComponentCfg cmpCfg = component.Cfg; @@ -488,11 +491,11 @@ namespace TBF.UI topVerticalSplitContainer.SplitterDistance = topVerticalSplitContainer.Width / 2; } - /// - /// Pass any pressed keys to the Bench control panel. - /// Note that MainWnd.KeyPreview must be set to true. - /// - private void MainWnd_KeyPress(object sender, KeyPressEventArgs e) + /// + /// Pass any pressed keys to the Bench control panel. + /// Note that MainWnd.KeyPreview must be set to true. + /// + private void MainWnd_KeyPress(object sender, KeyPressEventArgs e) { #if BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT || GENESIS || CEVAK_200 || TURA_SPECIAL || TURA_IPERL || TURA_IPERL_NEW /// Do nothing = do not process keys @@ -514,24 +517,24 @@ namespace TBF.UI /// void OnActivity(object sender, UiBridge.ActivityEventArgs args) { - switch (args.Cmd) - { - case ActivityEventArgs.Update.Activity: - activityLabel.Text = args.Activity; - if (string.IsNullOrEmpty(messageLabel.Text)) messageLabel.ForeColor = Color.Black; - break; - case ActivityEventArgs.Update.Message: - messageLabel.Text = args.Message; - if (args.ErrorMsg) messageLabel.ForeColor = Color.Red; - else messageLabel.ForeColor = Color.Black; - break; - default: - activityLabel.Text = args.Activity; - messageLabel.Text = args.Message; - if (args.ErrorMsg) messageLabel.ForeColor = Color.Red; - else messageLabel.ForeColor = Color.Black; - break; - } + switch (args.Cmd) + { + case ActivityEventArgs.Update.Activity: + activityLabel.Text = args.Activity; + if (string.IsNullOrEmpty(messageLabel.Text)) messageLabel.ForeColor = Color.Black; + break; + case ActivityEventArgs.Update.Message: + messageLabel.Text = args.Message; + if (args.ErrorMsg) messageLabel.ForeColor = Color.Red; + else messageLabel.ForeColor = Color.Black; + break; + default: + activityLabel.Text = args.Activity; + messageLabel.Text = args.Message; + if (args.ErrorMsg) messageLabel.ForeColor = Color.Red; + else messageLabel.ForeColor = Color.Black; + break; + } } /// @@ -563,7 +566,7 @@ namespace TBF.UI drawingCtrl.MsrmntAvailableFlags = new bool[args.MsrmntAvailableFlags.Length]; } for (int i = 0; i < args.MsrmntAvailableFlags.Length; i++) drawingCtrl.MsrmntAvailableFlags[i] = args.MsrmntAvailableFlags[i]; - + /// Duplicate measured values if (drawingCtrl.MeasuredValues == null || drawingCtrl.MeasuredValues.Length != args.MeasuredValues.Length) { @@ -577,7 +580,7 @@ namespace TBF.UI drawingCtrl.AltStrings = new string[args.AltStrings.Length]; } for (int i = 0; i < args.AltStrings.Length; i++) drawingCtrl.AltStrings[i] = args.AltStrings[i]; - + /// Duplicate setpoints if (drawingCtrl.Setpoints == null || drawingCtrl.Setpoints.Length != args.Setpoints.Length) { @@ -591,7 +594,7 @@ namespace TBF.UI drawingCtrl.CustomBitmaps = new DrawingShape[args.CustomBitmaps.Length]; } for (int i = 0; i < args.CustomBitmaps.Length; i++) drawingCtrl.CustomBitmaps[i] = args.CustomBitmaps[i]; - + drawingCtrl.SupressRedraws = false; } catch (Exception e) @@ -602,10 +605,10 @@ namespace TBF.UI } } - void OnTestProgress(object sender, UiBridge.TestProgressEventArgs args) - { - mainProgressBar.Value = (int)(100.499f * args.OveralProgress); - } + void OnTestProgress(object sender, UiBridge.TestProgressEventArgs args) + { + mainProgressBar.Value = (int)(100.499f * args.OveralProgress); + } void OnProcedureSelected(object sender, UiBridge.ProcedureSelectedEventArgs args) { @@ -671,18 +674,18 @@ namespace TBF.UI public void UpdateUser() { - userInfoStatusLabel.Text = string.Format("{0}: {1}{2}, ", Strings.User, CurrentUser.UserName(), - (CurrentUser.AuthorizedAs == AuthorizedAs.PowerUser) ? "(S)" : - (CurrentUser.AuthorizedAs == AuthorizedAs.LocalUser) ? "(L)" : "(R)"); + userInfoStatusLabel.Text = string.Format("{0}: {1}{2}, ", Strings.User, CurrentUser.UserName(), + (CurrentUser.AuthorizedAs == AuthorizedAs.PowerUser) ? "(S)" : + (CurrentUser.AuthorizedAs == AuthorizedAs.LocalUser) ? "(L)" : "(R)"); UpdateMenuItemsVisibility(); } void UpdateMenuItemsVisibility() { - usersTSMenuItem.Visible = CurrentUser.IsMemberOf(GID.Administrators) || CurrentUser.IsMemberOf(GID.HeadOfLab); - databaseSettingsTSMenuItem.Visible = CurrentUser.IsMemberOf(GID.Administrators) && CurrentUser.IsPowerUser(); - upgradeTSMenuItem.Visible = CurrentUser.IsMemberOf(GID.Administrators) && CurrentUser.IsPowerUser(); + usersTSMenuItem.Visible = CurrentUser.IsMemberOf(GID.Administrators) || CurrentUser.IsMemberOf(GID.HeadOfLab); + databaseSettingsTSMenuItem.Visible = CurrentUser.IsMemberOf(GID.Administrators) && CurrentUser.IsPowerUser(); + upgradeTSMenuItem.Visible = CurrentUser.IsMemberOf(GID.Administrators) && CurrentUser.IsPowerUser(); clearCountersToolStripMenuItem.Visible = CurrentUser.IsMemberOf(GID.Administrators) || CurrentUser.IsMemberOf(GID.HeadOfLab) || CurrentUser.IsMemberOf(GID.TestingSpecialists) || @@ -710,14 +713,14 @@ namespace TBF.UI //Rig.StateMachine.Stop(); } - private void benchComponentsTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Components.ComponentsManagerDlg().ShowDialog(); Cursor = Cursors.Default; } - private void benchPathsTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Paths.PathsDlg().ShowDialog(); Cursor = Cursors.Default; } - private void benchTransitionsTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Transitions.TransitionsDlg().ShowDialog(); Cursor = Cursors.Default; } - private void benchMetrologyTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Metrology.MetrologyDlg().ShowDialog(); Cursor = Cursors.Default; } - private void benchUncertaintyTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Uncertainties.UncertaintiesDlg().ShowDialog(); Cursor = Cursors.Default; } - private void benchTestProfilesTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.TestProfiles.TestProfilesDlg().ShowDialog(); Cursor = Cursors.Default; } - private void editSchDrawingTSMItem_Click(object sender, EventArgs e){ Cursor = Cursors.WaitCursor; new TBF.UI.Bench.EditSchDrawing.EditSchDrawingDlg().ShowDialog();Cursor = Cursors.Default; } - private void proceduresTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Procedures.ProceduresDlg().ShowDialog(); Cursor = Cursors.Default; } + private void benchComponentsTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Components.ComponentsManagerDlg().ShowDialog(); Cursor = Cursors.Default; } + private void benchPathsTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Paths.PathsDlg().ShowDialog(); Cursor = Cursors.Default; } + private void benchTransitionsTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Transitions.TransitionsDlg().ShowDialog(); Cursor = Cursors.Default; } + private void benchMetrologyTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Metrology.MetrologyDlg().ShowDialog(); Cursor = Cursors.Default; } + private void benchUncertaintyTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.Uncertainties.UncertaintiesDlg().ShowDialog(); Cursor = Cursors.Default; } + private void benchTestProfilesTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.TestProfiles.TestProfilesDlg().ShowDialog(); Cursor = Cursors.Default; } + private void editSchDrawingTSMItem_Click(object sender, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Bench.EditSchDrawing.EditSchDrawingDlg().ShowDialog(); Cursor = Cursors.Default; } + private void proceduresTSMItem_Click(object s, EventArgs e) { Cursor = Cursors.WaitCursor; new TBF.UI.Procedures.ProceduresDlg().ShowDialog(); Cursor = Cursors.Default; } private void usersTSMItem_Click(object s, EventArgs e) { @@ -754,15 +757,15 @@ namespace TBF.UI } } } - private void backUpConfigTSMItem_Click(object s, EventArgs e) { BackupConfiguration(); } - private void backUpResultsTSMItem_Click(object s, EventArgs e) { BackupResults(); } - private void passwdTSMItem_Click(object s, EventArgs e) { new SharedDatabase.Forms.PasswordChangeDlg(CurrentUser.UserName()).ShowDialog(); } - private void aboutTSMItem_Click(object s, EventArgs e) { new TBF.UI.Help.AboutDlg().ShowDialog(); } + private void backUpConfigTSMItem_Click(object s, EventArgs e) { BackupConfiguration(); } + private void backUpResultsTSMItem_Click(object s, EventArgs e) { BackupResults(); } + private void passwdTSMItem_Click(object s, EventArgs e) { new SharedDatabase.Forms.PasswordChangeDlg(CurrentUser.UserName()).ShowDialog(); } + private void aboutTSMItem_Click(object s, EventArgs e) { new TBF.UI.Help.AboutDlg().ShowDialog(); } - /// - /// Read the database and re-initialize procedureComboBox items. - /// Try to preserve the original selection. - /// + /// + /// Read the database and re-initialize procedureComboBox items. + /// Try to preserve the original selection. + /// public void ReloadProcedureComboBoxItems() { int separPos = procedureComboBox.Text.IndexOf(ProcSeparator); @@ -771,7 +774,7 @@ namespace TBF.UI } public void ReloadProcedureComboBoxItems(string procedureNameToSelect) - { + { if (!procedureComboBox.Enabled) { /// Test cycle in progress, reload combo box items when the session is finished @@ -915,7 +918,7 @@ namespace TBF.UI if (SelectedProcedure != null) BenchControlPanel.ReloadTests(); } - } + } /// /// To each unresolved procedure finds the first native procedure that matches teh unresolved procedure @@ -977,8 +980,8 @@ namespace TBF.UI return true; } - private void procedureComboBox_SelectedIndexChanged(object sender, EventArgs e) - { + private void procedureComboBox_SelectedIndexChanged(object sender, EventArgs e) + { foreach (var item in procedureComboBox.Items) { var procInfo = item as ProcedureInfo; @@ -1004,7 +1007,7 @@ namespace TBF.UI } } } - } + } private void procedureComboBox_KeyPress(object sender, KeyPressEventArgs e) { @@ -1162,39 +1165,56 @@ namespace TBF.UI private void appDiagnosticMenuItem_Click(object sender, EventArgs e) { - /*diagApi = new DiagApi(liveLogCache); - //diagApi.AddLog("ahoj, toto je prvy log"); - - ILog loger = LogManager.GetLogger("logCache"); - log.Debug("ahoj, ideme");*/ - - LiveLogCache.Instance.AddLog("=== Live diagnostic entry ==="); - DiagApi liveDiagApi = new DiagApi(); - - /*try + try { - // Predpoklad�me, �e ApplicationDiagnostic.exe je v rovnakom adres�ri ako hlavn� aplik�cia - string exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AppDiagnostic.exe"); + string exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AppDiagnostic", "AppDiagnostic.exe"); - if (File.Exists(exePath)) + if (!File.Exists(exePath)) { - ProcessStartInfo startInfo = new ProcessStartInfo - { - FileName = exePath, - UseShellExecute = true // Spust� aplik�ciu ako samostatn� proces - }; - System.Diagnostics.Process.Start(startInfo); + MessageBox.Show($"AppDiagnostic.exe not found:\n{exePath}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; } - else + + System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { - MessageBox.Show("ApplicationDiagnostic.exe not found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + FileName = exePath, + WorkingDirectory = Path.GetDirectoryName(exePath), + UseShellExecute = true + }); + + // Temporary diagnostic test. + SendDiagnosticTestLogs(); } catch (Exception ex) { - MessageBox.Show($"Failed to start ApplicationDiagnostic: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - }*/ + MessageBox.Show($"Failed to start AppDiagnostic or send test logs: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + private void SendDiagnosticTestLogs() + { + NLog.Logger deviceLogger = NLog.LogManager.GetLogger("TBF.TestBench.DeviceSimulation"); + + deviceLogger.Trace("TRACE: Communication cycle started."); + deviceLogger.Debug("DEBUG: Device configuration loaded."); + deviceLogger.Info("INFO: Test bench started."); + deviceLogger.Warn("WARN: Simulated pressure is approaching the limit."); + + for (int position = 1; position <= 10; position++) + { + deviceLogger.Debug($"Reading simulated device at position {position}."); + } + + try + { + throw new InvalidOperationException("Simulated device communication failure."); + } + catch (Exception ex) + { + deviceLogger.Error(ex, "ERROR: Unable to communicate with simulated device."); + } + + deviceLogger.Fatal("FATAL: Simulated emergency stop."); } private void optoHeadsToolStripMenuItem_Click(object sender, EventArgs e) @@ -1246,7 +1266,7 @@ namespace TBF.UI MessageBox.Show(Strings.Remote_database_cannot_be_exported, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information); return; } - + if (MessageBox.Show(Strings.Do_you_want_to_back_up_configuration_qm, string.Empty, MessageBoxButtons.YesNo, diff --git a/TBF/UI/nlog.config b/TBF/UI/nlog.config new file mode 100644 index 000000000..9da732f9e --- /dev/null +++ b/TBF/UI/nlog.config @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TBF/nlog.config b/TBF/nlog.config index b065c5314..9da732f9e 100644 --- a/TBF/nlog.config +++ b/TBF/nlog.config @@ -1,9 +1,13 @@  + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + internalLogLevel="Trace" + internalLogFile="${basedir}/nlog-internal.log" + throwConfigExceptions="true"> + @@ -11,6 +15,14 @@ xsi:type="UiTarget" layout="${time}|${level:uppercase=true:padding=-5}|${message}" /> + + +