diff --git a/WelsonJS.Toolkit/WelsonJS.Service/FileEventMonitor.cs b/WelsonJS.Toolkit/WelsonJS.Service/FileEventMonitor.cs index a4a5cc9..070950b 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/FileEventMonitor.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/FileEventMonitor.cs @@ -3,9 +3,9 @@ // https://github.com/gnh1201/welsonjs using ClamAV.Net.Client; using ClamAV.Net.Client.Results; +using Microsoft.Extensions.Logging; using System; using System.Diagnostics.Eventing.Reader; -using System.Runtime.CompilerServices; using System.ServiceProcess; using System.Threading.Tasks; @@ -15,6 +15,7 @@ namespace WelsonJS.Service { private EventLogWatcher eventLogWatcher; private ServiceMain parent; + private ILogger logger; private enum EventType: int { FileCreate = 11, @@ -80,11 +81,16 @@ namespace WelsonJS.Service catch (Exception ex) { clamAvConenctionString = "tcp://127.0.0.1:3310"; - this.parent.Log($"Failed to read the address because of {ex.Message}. Set default: {clamAvConenctionString}"); + logger.LogInformation($"Failed to read the address because of {ex.Message}. Set default: {clamAvConenctionString}"); } ConnectToClamAv().Start(); } + public void SetLogger(ILogger _logger) + { + logger = _logger; + } + public void Start() { try @@ -103,7 +109,7 @@ namespace WelsonJS.Service } catch (Exception ex) { - parent.Log($"Could not reach to the Sysmon service: {ex.Message}"); + logger.LogInformation($"Could not reach to the Sysmon service: {ex.Message}"); } } @@ -140,8 +146,8 @@ namespace WelsonJS.Service string image = e.EventRecord.Properties[(int)FileCreateEvent.Image]?.Value?.ToString(); string fileName = e.EventRecord.Properties[(int)FileCreateEvent.TargetFilename]?.Value?.ToString(); - parent.Log($"> Detected the file creation: {fileName}"); - parent.Log(parent.DispatchServiceEvent("fileCreated", new string[] { + logger.LogInformation($"> Detected the file creation: {fileName}"); + logger.LogInformation(parent.DispatchServiceEvent("fileCreated", new string[] { ruleName, processId, image, @@ -150,7 +156,7 @@ namespace WelsonJS.Service if (clamAvClient != null) { - parent.Log($"> Starting the ClamAV scan: {fileName}"); + logger.LogInformation($"> Starting the ClamAV scan: {fileName}"); Task.Run(async () => { await ScanWithClamAv(fileName); @@ -170,8 +176,8 @@ namespace WelsonJS.Service string desinationPort = e.EventRecord.Properties[(int)NetworkConnectionEvent.DestinationPort]?.Value?.ToString(); string dstinationAddress = $"{protocol}://{destinationIp}:{desinationPort}"; - parent.Log($"> Detected the network connection: {dstinationAddress}"); - parent.Log(parent.DispatchServiceEvent("networkConnected", new string[] { + logger.LogInformation($"> Detected the network connection: {dstinationAddress}"); + logger.LogInformation(parent.DispatchServiceEvent("networkConnected", new string[] { ruleName, processId, image, @@ -191,8 +197,8 @@ namespace WelsonJS.Service string eventType = e.EventRecord.Properties[(int)RegistryEvent.EventType]?.Value?.ToString(); string targetObject = e.EventRecord.Properties[(int)RegistryEvent.TargetObject]?.Value?.ToString(); - parent.Log($"> Detected the registry modification: {targetObject}"); - parent.Log(parent.DispatchServiceEvent("registryModified", new string[] { + logger.LogInformation($"> Detected the registry modification: {targetObject}"); + logger.LogInformation(parent.DispatchServiceEvent("registryModified", new string[] { ruleName, processId, image, @@ -209,12 +215,12 @@ namespace WelsonJS.Service } catch (Exception ex) { - parent.Log($"Failed to process the event bacause of {ex.Message}."); + logger.LogInformation($"Failed to process the event bacause of {ex.Message}."); } } else { - parent.Log("The event instance was null."); + logger.LogInformation("The event instance was null."); } } @@ -230,11 +236,11 @@ namespace WelsonJS.Service // Get ClamAV engine and virus database version VersionResult result = await clamAvClient.GetVersionAsync().ConfigureAwait(false); - parent.Log($"ClamAV version {result.ProgramVersion}, Virus database version {result.VirusDbVersion}"); + logger.LogInformation($"ClamAV version {result.ProgramVersion}, Virus database version {result.VirusDbVersion}"); } catch (Exception ex) { - parent.Log($"Failed to read the address because of {ex.Message}. {clamAvConenctionString}"); + logger.LogInformation($"Failed to read the address because of {ex.Message}. {clamAvConenctionString}"); clamAvClient = null; } } @@ -243,8 +249,8 @@ namespace WelsonJS.Service { ScanResult res = await clamAvClient.ScanRemotePathAsync(remotePath).ConfigureAwait(false); - parent.Log($"> Scan result: Infected={res.Infected}, VirusName={res.VirusName}"); - parent.Log(parent.DispatchServiceEvent("avScanResult", new string[] { + logger.LogInformation($"> Scan result: Infected={res.Infected}, VirusName={res.VirusName}"); + logger.LogInformation(parent.DispatchServiceEvent("avScanResult", new string[] { res.Infected.ToString(), res.VirusName })); diff --git a/WelsonJS.Toolkit/WelsonJS.Service/HeartbeatClient.cs b/WelsonJS.Toolkit/WelsonJS.Service/HeartbeatClient.cs index 9ca715d..8eb933d 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/HeartbeatClient.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/HeartbeatClient.cs @@ -9,12 +9,14 @@ using System.ServiceProcess; using Grpc.Net.Client; using Grpc.Net.Client.Web; using System.Net.Http; +using Microsoft.Extensions.Logging; namespace WelsonJS.Service { public class HeartbeatClient { private readonly HeartbeatService.HeartbeatServiceClient _client; + private ILogger logger; private readonly GrpcChannel _channel; private int HeartbeatInterval; private ServiceMain _parent; @@ -38,7 +40,7 @@ namespace WelsonJS.Service catch (Exception ex) { serverAddress = "http://localhost:50051"; - _parent.Log($"Failed to read the address because of {ex.Message}. Set default: {serverAddress}"); + logger.LogInformation($"Failed to read the address because of {ex.Message}. Set default: {serverAddress}"); } var httpClientHandler = new HttpClientHandler(); @@ -51,7 +53,12 @@ namespace WelsonJS.Service _client = new HeartbeatService.HeartbeatServiceClient(_channel); clientId = GetSystemUUID().ToLower(); - _parent.Log($"Use the client ID: {clientId}"); + logger.LogInformation($"Use the client ID: {clientId}"); + } + + public void SetLogger(ILogger _logger) + { + logger = _logger; } public async Task StartHeartbeatAsync() @@ -69,14 +76,14 @@ namespace WelsonJS.Service await call.RequestStream.WriteAsync(request); await call.RequestStream.CompleteAsync(); - _parent.Log("Sent heartbeat"); + logger.LogInformation("Sent heartbeat"); await Task.Delay(HeartbeatInterval); // Wait for HeartbeatInterval } catch (Exception ex) { - _parent.Log("Heartbeat request stream failed: " + ex.Message); + logger.LogInformation("Heartbeat request stream failed: " + ex.Message); } // 서버 응답을 수신하는 작업 @@ -85,16 +92,16 @@ namespace WelsonJS.Service while (await call.ResponseStream.MoveNext()) { var response = call.ResponseStream.Current; - _parent.Log("Heartbeat response received: " + response.IsAlive); + logger.LogInformation("Heartbeat response received: " + response.IsAlive); } } catch (RpcException ex) { - _parent.Log($"gRPC error: {ex.Status.Detail}"); + logger.LogInformation($"gRPC error: {ex.Status.Detail}"); } catch (Exception ex) { - _parent.Log($"Unexpected error: {ex.Message}"); + logger.LogInformation($"Unexpected error: {ex.Message}"); } finally { @@ -118,7 +125,7 @@ namespace WelsonJS.Service while (await eventCall.ResponseStream.MoveNext()) { var response = eventCall.ResponseStream.Current; - _parent.Log($"Received event from server: {response.EventType} with args: {string.Join(", ", response.Args)}"); + logger.LogInformation($"Received event from server: {response.EventType} with args: {string.Join(", ", response.Args)}"); } } finally @@ -148,7 +155,7 @@ namespace WelsonJS.Service } catch (Exception ex) { - _parent.Log($"An error occurred while retrieving the system UUID: {ex.Message}"); + logger.LogInformation($"An error occurred while retrieving the system UUID: {ex.Message}"); } return "UNKNOWN"; diff --git a/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLogger.cs b/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLogger.cs new file mode 100644 index 0000000..bd76f16 --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLogger.cs @@ -0,0 +1,63 @@ +using Microsoft.Extensions.Logging; +using System.IO; +using System; + +namespace WelsonJS.Service.Logging +{ + public class FileLogger : ILogger + { + private string loggingDirectory; + private string categoryName; + private static object _lock = new object(); + + public FileLogger(string _loggingDirectory, string _categoryName = "welsonjs") + { + loggingDirectory = _loggingDirectory; + categoryName = _categoryName; + } + + public IDisposable BeginScope(TState state) + { + return null; + } + + public bool IsEnabled(LogLevel logLevel) + { + //return logLevel == LogLevel.Trace; + return true; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + if (formatter != null) + { + lock (_lock) + { + try + { + if (!Directory.Exists(loggingDirectory)) + { + Directory.CreateDirectory(loggingDirectory); + } + + string path = Path.Combine(loggingDirectory, $"{categoryName}_service.{DateTime.Now.ToString("yyyy-MM-dd")}.log"); + string nl = Environment.NewLine; + string err = ""; + + if (exception != null) + { + err = nl + exception.GetType() + ": " + exception.Message + nl + exception.StackTrace + nl; + } + + File.AppendAllText(path, logLevel.ToString() + ": [" + DateTime.Now.ToString() + "] " + formatter(state, exception) + nl + err); + } + catch (Exception ex) + { + Console.WriteLine(LogLevel.Warning.ToString() + ": [" + DateTime.Now.ToString() + "] Failed to write a log file. " + ex.Message); + } + + } + } + } + } +} diff --git a/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLoggerExtensions.cs b/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLoggerExtensions.cs new file mode 100644 index 0000000..7c65791 --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLoggerExtensions.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.Logging; + +namespace WelsonJS.Service.Logging +{ + public static class FileLoggerExtensions + { + public static ILoggerFactory AddDirectory(this ILoggerFactory factory, string loggingDirectory) + { + factory.AddProvider(new FileLoggerProvider(loggingDirectory)); + return factory; + } + } +} diff --git a/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLoggerProvider.cs b/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLoggerProvider.cs new file mode 100644 index 0000000..56cd1ff --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Service/Logging/FileLoggerProvider.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.Logging; + +namespace WelsonJS.Service.Logging +{ + public class FileLoggerProvider : ILoggerProvider + { + private string loggingDirectory; + + public FileLoggerProvider(string _loggingDirectory) + { + loggingDirectory = _loggingDirectory; + } + + public ILogger CreateLogger(string categoryName) + { + return new FileLogger(loggingDirectory, categoryName); + } + + public void Dispose() + { + // Dispose + } + } +} diff --git a/WelsonJS.Toolkit/WelsonJS.Service/ScreenMatch.cs b/WelsonJS.Toolkit/WelsonJS.Service/ScreenMatch.cs index 8108933..051e12d 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/ScreenMatch.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/ScreenMatch.cs @@ -15,6 +15,7 @@ using System.Windows.Forms; using System.Linq; using Tesseract; using WelsonJS.Service; +using Microsoft.Extensions.Logging; public class ScreenMatch { @@ -105,6 +106,7 @@ public class ScreenMatch } private ServiceMain parent; + private ILogger logger; private List templateImages; private string templateDirectoryPath; private string outputDirectoryPath; @@ -130,7 +132,7 @@ public class ScreenMatch private void SetBusy(bool busy) { this.busy = busy; - parent.Log($"State changed: busy={busy}"); + logger.LogInformation($"State changed: busy={busy}"); } public class TemplateInfo @@ -198,7 +200,7 @@ public class ScreenMatch { screen_time_mode = null; screen_time_params = null; - this.parent.Log($"Failed to read from configration file: {ex.Message}"); + logger.LogInformation($"Failed to read from configration file: {ex.Message}"); } if (!String.IsNullOrEmpty(screen_time_params)) @@ -238,14 +240,14 @@ public class ScreenMatch case "backward": { isSearchFromEnd = true; - this.parent.Log("Use the backward search when screen time"); + logger.LogInformation("Use the backward search when screen time"); break; } case "save": { isSaveToFile = true; - this.parent.Log("Will be save an image file when capture the screens"); + logger.LogInformation("Will be save an image file when capture the screens"); break; } @@ -330,6 +332,11 @@ public class ScreenMatch LoadTemplateImages(); } + public void SetLogger(ILogger _logger) + { + logger = _logger; + } + public void SetMode(string mode) { if (!String.IsNullOrEmpty(mode)) @@ -358,7 +365,7 @@ public class ScreenMatch catch (Exception ex) { files = new string[]{}; - parent.Log($"Failed to read the directory structure: {ex.Message}"); + logger.LogInformation($"Failed to read the directory structure: {ex.Message}"); } foreach (var file in files) @@ -370,12 +377,12 @@ public class ScreenMatch if (!String.IsNullOrEmpty(altpath)) { realpath = altpath; - parent.Log($"Use the alternative image: {realpath}"); + logger.LogInformation($"Use the alternative image: {realpath}"); } else { realpath = file; - parent.Log($"Use the default image: {realpath}"); + logger.LogInformation($"Use the default image: {realpath}"); } Bitmap bitmap = new Bitmap(realpath) @@ -452,11 +459,11 @@ public class ScreenMatch Height = image.Height }; - parent.Log($"Trying match the template {templateName} on the screen {i}..."); + logger.LogInformation($"Trying match the template {templateName} on the screen {i}..."); if (!String.IsNullOrEmpty(nextTemplateInfo.FileName) && templateName != nextTemplateInfo.FileName) { - parent.Log($"Ignored the template {templateName}"); + logger.LogInformation($"Ignored the template {templateName}"); break; } @@ -477,7 +484,7 @@ public class ScreenMatch { string out_filepath = Path.Combine(outputDirectoryPath, out_filename); ((Bitmap)out_mainImage.Clone()).Save(out_filepath); - parent.Log($"Screenshot saved: {out_filepath}"); + logger.LogInformation($"Screenshot saved: {out_filepath}"); } // List to store the positions of matched templates in the main image @@ -488,7 +495,7 @@ public class ScreenMatch { Bitmap outdatedImage = null; - parent.Log($"Finding a previous screen of {nextTemplateInfo.FileName}..."); + logger.LogInformation($"Finding a previous screen of {nextTemplateInfo.FileName}..."); try { @@ -499,7 +506,7 @@ public class ScreenMatch { if (((SampleInfo)outdatedImage.Tag).FileName == nextTemplateInfo.FileName) { - parent.Log($"Found the previous screen of {nextTemplateInfo.FileName}"); + logger.LogInformation($"Found the previous screen of {nextTemplateInfo.FileName}"); break; } } @@ -507,7 +514,7 @@ public class ScreenMatch } catch (Exception ex) { - parent.Log($"Error finding a previous screen: {ex.Message}"); + logger.LogInformation($"Error finding a previous screen: {ex.Message}"); } // Find the matching positions of the outdated image in the main image @@ -515,16 +522,16 @@ public class ScreenMatch matchPositions = FindTemplate(out_mainImage, outdatedImage); if (matchPositions.Count > 0) { - parent.Log("Match found with the outdated image"); + logger.LogInformation("Match found with the outdated image"); } else { - parent.Log("No match found with the outdated image"); + logger.LogInformation("No match found with the outdated image"); } } else { - parent.Log("Not found a outdated image"); + logger.LogInformation("Not found a outdated image"); matchPositions = new List(); } } @@ -553,18 +560,18 @@ public class ScreenMatch } catch (Exception ex) { - parent.Log($"Ignore the match. {ex.Message}"); + logger.LogInformation($"Ignore the match. {ex.Message}"); } } } if (results.Count > 0) { - parent.Log("Match found"); + logger.LogInformation("Match found"); } else { - parent.Log($"No match found"); + logger.LogInformation($"No match found"); } templateCurrentIndex = ++templateCurrentIndex % templateImages.Count; @@ -622,24 +629,24 @@ public class ScreenMatch else { outdatedSamples.Enqueue(croppedNodupBitmap); - parent.Log($"Added to the image queue. {templateName}"); + logger.LogInformation($"Added to the image queue. {templateName}"); } } // if use Clipboard if (sampleClipboard.Contains(templateName)) { - parent.Log($"Trying to use the clipboard... {templateName}"); + logger.LogInformation($"Trying to use the clipboard... {templateName}"); Thread th = new Thread(new ThreadStart(() => { try { Clipboard.SetImage((Bitmap)croppedBitmap.Clone()); - parent.Log($"Copied the image to Clipboard"); + logger.LogInformation($"Copied the image to Clipboard"); } catch (Exception ex) { - parent.Log($"Failed to copy to the clipboard: {ex.Message}"); + logger.LogInformation($"Failed to copy to the clipboard: {ex.Message}"); } })); th.SetApartmentState(ApartmentState.STA); @@ -657,14 +664,14 @@ public class ScreenMatch { text = page.GetText(); - parent.Log($"Mean confidence: {page.GetMeanConfidence()}"); - parent.Log($"Text (GetText): {text}"); + logger.LogInformation($"Mean confidence: {page.GetMeanConfidence()}"); + logger.LogInformation($"Text (GetText): {text}"); } } } catch (Exception ex) { - parent.Log($"Failed to OCR: {ex.Message}"); + logger.LogInformation($"Failed to OCR: {ex.Message}"); } } @@ -680,7 +687,7 @@ public class ScreenMatch EnumDisplaySettings(screen.DeviceName, -1, ref dm); var scalingFactor = Math.Round(Decimal.Divide(dm.dmPelsWidth, screen.Bounds.Width), 2); - parent.Log($"Resolved the screen scale: {scalingFactor}"); + logger.LogInformation($"Resolved the screen scale: {scalingFactor}"); int adjustedWidth = (int)(screenSize.Width * scalingFactor); int adjustedHeight = (int)(screenSize.Height * scalingFactor); @@ -743,13 +750,13 @@ public class ScreenMatch } catch (Exception ex) { - parent.Log($"Ignore the match. {ex.Message}"); + logger.LogInformation($"Ignore the match. {ex.Message}"); } }); } } catch (Exception ex) { - parent.Log($"Error {ex.Message}"); + logger.LogInformation($"Error {ex.Message}"); } } return true; diff --git a/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs b/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs index e284138..22a5cd4 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs @@ -34,19 +34,22 @@ using System.Collections.Generic; using WelsonJS.TinyINIController; using System.Collections; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using WelsonJS.Service.Logging; +using Grpc.Core.Logging; namespace WelsonJS.Service { public partial class ServiceMain : ServiceBase { - private readonly string appName = "WelsonJS"; + private readonly static string applicationName = "WelsonJS"; private static List timers; + private Microsoft.Extensions.Logging.ILogger logger; private string workingDirectory; private string scriptName; private string scriptFilePath; private string scriptText; private ScriptControl scriptControl; - private string logFilePath; private string[] args; private bool disabledHeartbeat = false; private bool disabledScreenTime = false; @@ -68,8 +71,10 @@ namespace WelsonJS.Service // set service arguments this.args = args; - // set the log file path - logFilePath = Path.Combine(Path.GetTempPath(), "welsonjs_service.log"); + // set the logger + ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole()); + factory.AddDirectory(Path.GetTempPath()); + logger = factory.CreateLogger(applicationName); // mapping arguments to each variables var arguments = ParseArguments(this.args); @@ -109,13 +114,13 @@ namespace WelsonJS.Service // set working directory if (string.IsNullOrEmpty(workingDirectory)) { - workingDirectory = Path.Combine(Path.GetTempPath(), appName); - Log("Working directory not provided. Using default value: " + workingDirectory); + workingDirectory = Path.Combine(Path.GetTempPath(), applicationName); + logger.LogInformation("Working directory not provided. Using default value: " + workingDirectory); if (!Directory.Exists(workingDirectory)) { Directory.CreateDirectory(workingDirectory); - Log("Directory created: " + workingDirectory); + logger.LogInformation("Directory created: " + workingDirectory); } } Directory.SetCurrentDirectory(workingDirectory); @@ -135,7 +140,7 @@ namespace WelsonJS.Service } else { - Log($"Configuration file not found: {settingsFilePath}"); + logger.LogInformation($"Configuration file not found: {settingsFilePath}"); } // read configrations from settings.ini @@ -174,7 +179,7 @@ namespace WelsonJS.Service } catch (Exception ex) { - Log($"{configName} is ignored: {ex.Message}"); + logger.LogInformation($"{configName} is ignored: {ex.Message}"); } } } @@ -183,7 +188,7 @@ namespace WelsonJS.Service if (string.IsNullOrEmpty(scriptName)) { scriptName = "defaultService"; - Log($"Script name not provided. Using default value: {scriptName}"); + logger.LogInformation($"Script name not provided. Using default value: {scriptName}"); } // set path of the script @@ -193,6 +198,7 @@ namespace WelsonJS.Service if (!disabledHeartbeat) { HeartbeatClient heartbeatClient = new HeartbeatClient(this); + heartbeatClient.SetLogger(logger); Task.Run(heartbeatClient.StartHeartbeatAsync); Task.Run(heartbeatClient.StartEventListenerAsync); } @@ -211,10 +217,10 @@ namespace WelsonJS.Service } else { - Log("Disabled the User Interactive Mode. (e.g., OnScreenTime)"); + logger.LogInformation("Disabled the User Interactive Mode. (e.g., OnScreenTime)"); } - Log(appName + " Service Loaded"); + logger.LogInformation(applicationName + " Service Loaded"); } public IniFile GetSettingsHandler() @@ -241,7 +247,7 @@ namespace WelsonJS.Service // Check exists the entry script file if (File.Exists(scriptFilePath)) { - Log($"Script file found: {scriptFilePath}"); + logger.LogInformation($"Script file found: {scriptFilePath}"); try { @@ -281,35 +287,36 @@ namespace WelsonJS.Service } // initialize - Log(DispatchServiceEvent("start", startArguments)); + logger.LogInformation(DispatchServiceEvent("start", startArguments)); } catch (Exception ex) { - Log($"Failed to start because of {ex.Message}"); + logger.LogInformation($"Failed to start because of {ex.Message}"); } } else { - Log($"Script file not found: {scriptFilePath}"); + logger.LogInformation($"Script file not found: {scriptFilePath}"); } // Trace a Sysmon file events (If Sysinternals Sysmon installed) if (!disabledFileMonitor) { fileEventMonitor = new FileEventMonitor(this, workingDirectory); + fileEventMonitor.SetLogger(logger); fileEventMonitor.Start(); - Log("File Event Monitor Started"); + logger.LogInformation("File Event Monitor Started"); } else { - Log("File Event Monitor is Disabled"); + logger.LogInformation("File Event Monitor is Disabled"); } // Start all the registered timers - timers.ForEach(timer => timer?.Start()); + timers.ForEach(timer => timer?.Start()); - Log(appName + " Service Started"); + logger.LogInformation(applicationName + " Service Started"); } protected override void OnStop() @@ -323,16 +330,16 @@ namespace WelsonJS.Service // dispatch stop callback try { - Log(DispatchServiceEvent("stop")); + logger.LogInformation(DispatchServiceEvent("stop")); scriptControl?.Reset(); } catch (Exception ex) { - Log("Exception when stop: " + ex.Message); + logger.LogInformation("Exception when stop: " + ex.Message); } scriptControl = null; - Log(appName + " Service Stopped"); + logger.LogInformation(applicationName + " Service Stopped"); } private void OnUserInteractiveEnvironment() @@ -341,13 +348,14 @@ namespace WelsonJS.Service if (GetSystemMetrics(SM_REMOTESESSION) > 0) { disabledScreenTime = true; - Log("This application may not work correctly in a remote desktop session"); + logger.LogInformation("This application may not work correctly in a remote desktop session"); } // set screen timer if (!disabledScreenTime) { screenMatcher = new ScreenMatch(this, workingDirectory); + screenMatcher.SetLogger(logger); Timer screenTimer = new Timer { @@ -356,13 +364,13 @@ namespace WelsonJS.Service screenTimer.Elapsed += OnScreenTime; timers.Add(screenTimer); - Log("Screen Time Event Enabled"); + logger.LogInformation("Screen Time Event Enabled"); } else { disabledScreenTime = true; - Log("Screen Time Event Disabled"); + logger.LogInformation("Screen Time Event Disabled"); } } @@ -370,11 +378,11 @@ namespace WelsonJS.Service { try { - Log(DispatchServiceEvent("elapsedTime")); + logger.LogInformation(DispatchServiceEvent("elapsedTime")); } catch (Exception ex) { - Log("Exception when elapsed time: " + ex.Message); + logger.LogInformation("Exception when elapsed time: " + ex.Message); } } @@ -385,7 +393,7 @@ namespace WelsonJS.Service List matchedResults = screenMatcher.CaptureAndMatch(); matchedResults.ForEach(result => { - Log(DispatchServiceEvent("screenTemplateMatched", new string[] + logger.LogInformation(DispatchServiceEvent("screenTemplateMatched", new string[] { result.FileName, result.ScreenNumber.ToString(), @@ -396,7 +404,7 @@ namespace WelsonJS.Service } catch (Exception ex) { - Log($"Waiting a next screen time... {ex.Message}"); + logger.LogInformation($"Waiting a next screen time... {ex.Message}"); } } @@ -416,7 +424,7 @@ namespace WelsonJS.Service } else { - Log("InvokeScriptMethod Ignored: " + methodName); + logger.LogInformation("InvokeScriptMethod Ignored: " + methodName); } return "void"; @@ -467,7 +475,7 @@ namespace WelsonJS.Service } catch (Exception ex) { - Log($"Use all templates because of {ex.Message}"); + logger.LogInformation($"Use all templates because of {ex.Message}"); } return new ScreenMatch.TemplateInfo(templateName, index); @@ -485,27 +493,5 @@ namespace WelsonJS.Service } } - - public void Log(string message) - { - string _message = $"{DateTime.Now}: {message}"; - - if (Environment.UserInteractive) - { - Console.WriteLine(_message); - } - - try - { - using (StreamWriter writer = new StreamWriter(logFilePath, true)) - { - writer.WriteLine(_message); - } - } - catch (Exception ex) - { - Console.WriteLine($"LOGGING FAILED: {ex.Message}"); - } - } } } diff --git a/WelsonJS.Toolkit/WelsonJS.Service/UserVariables.cs b/WelsonJS.Toolkit/WelsonJS.Service/UserVariables.cs index b62eac6..6c9560a 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/UserVariables.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/UserVariables.cs @@ -51,13 +51,13 @@ namespace WelsonJS.Service } else { - parent.Log($"Error parsing line: '{pair}'."); + throw new Exception($"Error parsing line: '{pair}'."); } } } catch (Exception ex) { - parent.Log($"Error loading variable file: {ex.Message}"); + Console.WriteLine($"Error loading variable file: {ex.Message}"); userVariables = new Dictionary(); } } diff --git a/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj b/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj index c6e8265..1f40e47 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj +++ b/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj @@ -125,12 +125,42 @@ ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + ..\packages\Microsoft.Extensions.Configuration.8.0.0\lib\net462\Microsoft.Extensions.Configuration.dll + + + ..\packages\Microsoft.Extensions.Configuration.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.Configuration.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Configuration.Binder.8.0.2\lib\net462\Microsoft.Extensions.Configuration.Binder.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.8.0.1\lib\net462\Microsoft.Extensions.DependencyInjection.dll + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + ..\packages\Microsoft.Extensions.Logging.8.0.1\lib\net462\Microsoft.Extensions.Logging.dll + ..\packages\Microsoft.Extensions.Logging.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll + + ..\packages\Microsoft.Extensions.Logging.Configuration.8.0.1\lib\net462\Microsoft.Extensions.Logging.Configuration.dll + + + ..\packages\Microsoft.Extensions.Logging.Console.8.0.1\lib\net462\Microsoft.Extensions.Logging.Console.dll + + + ..\packages\Microsoft.Extensions.Options.8.0.2\lib\net462\Microsoft.Extensions.Options.dll + + + ..\packages\Microsoft.Extensions.Options.ConfigurationExtensions.8.0.0\lib\net462\Microsoft.Extensions.Options.ConfigurationExtensions.dll + + + ..\packages\Microsoft.Extensions.Primitives.8.0.0\lib\net462\Microsoft.Extensions.Primitives.dll + ..\packages\RestSharp.112.1.0\lib\net48\RestSharp.dll @@ -138,6 +168,7 @@ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + @@ -159,6 +190,7 @@ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll @@ -185,6 +217,9 @@ + + + Component diff --git a/WelsonJS.Toolkit/WelsonJS.Service/app.config b/WelsonJS.Toolkit/WelsonJS.Service/app.config index 566f236..e57591a 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/app.config +++ b/WelsonJS.Toolkit/WelsonJS.Service/app.config @@ -65,7 +65,7 @@ - + @@ -87,6 +87,14 @@ + + + + + + + + diff --git a/WelsonJS.Toolkit/WelsonJS.Service/packages.config b/WelsonJS.Toolkit/WelsonJS.Service/packages.config index f9d088e..d128629 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/packages.config +++ b/WelsonJS.Toolkit/WelsonJS.Service/packages.config @@ -10,8 +10,18 @@ + + + + + + + + + + diff --git a/WelsonJS.Toolkit/WelsonJS.Toolkit/TinyINIController/IniFile.cs b/WelsonJS.Toolkit/WelsonJS.Toolkit/TinyINIController/IniFile.cs index 4e47530..a2afd5f 100644 --- a/WelsonJS.Toolkit/WelsonJS.Toolkit/TinyINIController/IniFile.cs +++ b/WelsonJS.Toolkit/WelsonJS.Toolkit/TinyINIController/IniFile.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Reflection; using System.Runtime.InteropServices; using System.Text;