diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ICompatibleLogger.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ICompatibleLogger.cs
index 74b323f..16d4edb 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ICompatibleLogger.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ICompatibleLogger.cs
@@ -10,8 +10,8 @@ namespace WelsonJS.Launcher
{
public interface ICompatibleLogger
{
- void Info(string message);
- void Warn(string message);
- void Error(string message);
+ void Info(params object[] args);
+ void Warn(params object[] args);
+ void Error(params object[] args);
}
}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/JsCore.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/JsCore.cs
index 38db84a..53af2b5 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/JsCore.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/JsCore.cs
@@ -4,53 +4,47 @@
// https://github.com/gnh1201/welsonjs
//
using System;
+using System.Globalization;
using System.Runtime.InteropServices;
namespace WelsonJS.Launcher
{
public sealed class JsCore : IDisposable
{
- private IntPtr _runtime = IntPtr.Zero;
- private IntPtr _context = IntPtr.Zero;
+ private JsNative.JsRuntime _rt;
+ private JsNative.JsContext _ctx;
private bool _disposed;
public JsCore()
{
- Check(JsCreateRuntime(0, IntPtr.Zero, out _runtime), nameof(JsCreateRuntime));
- Check(JsCreateContext(_runtime, out _context), nameof(JsCreateContext));
- Check(JsSetCurrentContext(_context), nameof(JsSetCurrentContext));
+ Check(JsNative.JsCreateRuntime(JsNative.JsRuntimeAttributes.None, null, out _rt), "JsCreateRuntime");
+ Check(JsNative.JsCreateContext(_rt, out _ctx), "JsCreateContext");
+ Check(JsNative.JsSetCurrentContext(_ctx), "JsSetCurrentContext");
}
- ///
- /// Evaluates JavaScript and returns the result converted to string (via JsConvertValueToString).
- ///
public string EvaluateToString(string script, string sourceUrl = "repl")
{
if (_disposed) throw new ObjectDisposedException(nameof(JsCore));
- if (script is null) throw new ArgumentNullException(nameof(script));
+ if (script == null) throw new ArgumentNullException(nameof(script));
- Check(JsRunScript(script, IntPtr.Zero, sourceUrl, out var result), nameof(JsRunScript));
+ JsNative.JsValue result;
+ Check(JsNative.JsRunScript(script, UIntPtr.Zero, sourceUrl, out result), "JsRunScript");
- // Convert result -> JsString
- Check(JsConvertValueToString(result, out var jsString), nameof(JsConvertValueToString));
+ JsNative.JsValue jsStr;
+ Check(JsNative.JsConvertValueToString(result, out jsStr), "JsConvertValueToString");
- // Extract pointer/length (UTF-16) and marshal to managed string
- Check(JsStringToPointer(jsString, out var p, out var len), nameof(JsStringToPointer));
- return Marshal.PtrToStringUni(p, checked((int)len));
+ IntPtr p;
+ UIntPtr len;
+ Check(JsNative.JsStringToPointer(jsStr, out p, out len), "JsStringToPointer");
+
+ int chars = checked((int)len);
+ return Marshal.PtrToStringUni(p, chars);
}
- ///
- /// Evaluates JavaScript for side effects; discards the result.
- ///
- public void Execute(string script, string sourceUrl = "repl")
+ private static void Check(JsNative.JsErrorCode code, string op)
{
- _ = EvaluateToString(script, sourceUrl);
- }
-
- private static void Check(JsErrorCode code, string op)
- {
- if (code != JsErrorCode.JsNoError)
- throw new InvalidOperationException($"{op} failed with {code} (0x{(int)code:X}).");
+ if (code != JsNative.JsErrorCode.JsNoError)
+ throw new InvalidOperationException(op + " failed: " + code + " (0x" + ((int)code).ToString("X", CultureInfo.InvariantCulture) + ")");
}
public void Dispose()
@@ -60,112 +54,18 @@ namespace WelsonJS.Launcher
try
{
- // Unset the current context from the SAME physical thread that set it.
- JsSetCurrentContext(IntPtr.Zero);
- }
- catch
- {
- // Swallow to ensure runtime is disposed.
+ // Unset current context
+ JsNative.JsSetCurrentContext(new JsNative.JsContext { Handle = IntPtr.Zero });
}
+ catch { /* ignore */ }
finally
{
- if (_runtime != IntPtr.Zero)
- {
- JsDisposeRuntime(_runtime);
- _runtime = IntPtr.Zero;
- }
- _context = IntPtr.Zero;
+ if (_rt.Handle != IntPtr.Zero)
+ JsNative.JsDisposeRuntime(_rt);
}
-
GC.SuppressFinalize(this);
}
- ~JsCore() => Dispose();
-
- // =========================
- // P/Invoke surface (as given)
- // =========================
-
- // Essential (expanded) JsErrorCode set matching ChakraCore’s headers layout.
- // Values are grouped by category bases (0x10000, 0x20000, ...).
- public enum JsErrorCode
- {
- // Success
- JsNoError = 0,
-
- // Category bases (useful when inspecting ranges)
- JsErrorCategoryUsage = 0x10000,
- JsErrorCategoryEngine = 0x20000,
- JsErrorCategoryScript = 0x30000,
- JsErrorCategoryFatal = 0x40000,
-
- // Usage errors (0x10001+)
- JsErrorInvalidArgument = 0x10001,
- JsErrorNullArgument = 0x10002,
- JsErrorNoCurrentContext = 0x10003,
- JsErrorInExceptionState = 0x10004,
- JsErrorNotImplemented = 0x10005,
- JsErrorWrongThread = 0x10006,
- JsErrorRuntimeInUse = 0x10007,
- JsErrorBadSerializedScript = 0x10008,
- JsErrorInDisabledState = 0x10009,
- JsErrorCannotDisableExecution = 0x1000A,
- JsErrorHeapEnumInProgress = 0x1000B,
- JsErrorArgumentNotObject = 0x1000C,
- JsErrorInProfileCallback = 0x1000D,
- JsErrorInThreadServiceCallback = 0x1000E,
- JsErrorCannotSerializeDebugScript = 0x1000F,
- JsErrorAlreadyDebuggingContext = 0x10010,
- JsErrorAlreadyProfilingContext = 0x10011,
- JsErrorIdleNotEnabled = 0x10012,
-
- // Engine errors (0x20001+)
- JsErrorOutOfMemory = 0x20001,
- JsErrorBadFPUState = 0x20002,
-
- // Script errors (0x30001+)
- JsErrorScriptException = 0x30001,
- JsErrorScriptCompile = 0x30002,
- JsErrorScriptTerminated = 0x30003,
- JsErrorScriptEvalDisabled = 0x30004,
-
- // Fatal (0x40001)
- JsErrorFatal = 0x40001,
-
- // Misc/diagnostic (0x50000+)
- JsErrorWrongRuntime = 0x50000,
- JsErrorDiagAlreadyInDebugMode = 0x50001,
- JsErrorDiagNotInDebugMode = 0x50002,
- JsErrorDiagNotAtBreak = 0x50003,
- JsErrorDiagInvalidHandle = 0x50004,
- JsErrorDiagObjectNotFound = 0x50005,
- JsErrorDiagUnableToPerformAction = 0x50006,
- }
-
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern JsErrorCode JsCreateRuntime(uint attributes, IntPtr callback, out IntPtr runtime);
-
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern JsErrorCode JsCreateContext(IntPtr runtime, out IntPtr context);
-
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern JsErrorCode JsSetCurrentContext(IntPtr context);
-
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
- public static extern JsErrorCode JsRunScript(string script, IntPtr sourceContext, string sourceUrl, out IntPtr result);
-
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern JsErrorCode JsConvertValueToString(IntPtr value, out IntPtr stringValue);
-
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern JsErrorCode JsStringToPointer(IntPtr value, out IntPtr buffer, out UIntPtr length);
-
- // Note: Unsetting is typically done via JsSetCurrentContext(IntPtr.Zero)
- // Kept here only if your build exposes this symbol.
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "JsSetCurrentContext")]
- public static extern JsErrorCode JsUnSetCurrentContext(IntPtr zero);
-
- [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern JsErrorCode JsDisposeRuntime(IntPtr runtime);
+ ~JsCore() { Dispose(); }
}
}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/JsNative.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/JsNative.cs
new file mode 100644
index 0000000..3f44823
--- /dev/null
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/JsNative.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace WelsonJS.Launcher
+{
+ public static class JsNative
+ {
+ // === Enums / handles ===
+ [Flags]
+ public enum JsRuntimeAttributes : uint
+ {
+ None = 0x00000000,
+ DisableBackgroundWork = 0x00000001,
+ AllowScriptInterrupt = 0x00000002,
+ EnableIdleProcessing = 0x00000004,
+ DisableNativeCodeGeneration = 0x00000008,
+ EnableExperimentalFeatures = 0x00000010,
+ }
+
+ // ChakraCore typedefs are opaque pointers; represent as IntPtr
+ public struct JsRuntime { public IntPtr Handle; }
+ public struct JsContext { public IntPtr Handle; }
+ public struct JsValue { public IntPtr Handle; }
+
+ // JsErrorCode (essential subset; expand as needed)
+ public enum JsErrorCode
+ {
+ JsNoError = 0,
+
+ // Usage
+ JsErrorInvalidArgument = 0x10001,
+ JsErrorNullArgument = 0x10002,
+ JsErrorNoCurrentContext = 0x10003,
+ JsErrorInExceptionState = 0x10004,
+ JsErrorNotImplemented = 0x10005,
+ JsErrorWrongThread = 0x10006,
+ JsErrorRuntimeInUse = 0x10007,
+
+ // Script
+ JsErrorScriptException = 0x30001,
+ JsErrorScriptCompile = 0x30002,
+ JsErrorScriptTerminated = 0x30003,
+
+ // Engine
+ JsErrorOutOfMemory = 0x20001,
+
+ // Fatal
+ JsErrorFatal = 0x40001,
+ }
+
+ // Thread service callback: __stdcall
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ public delegate JsErrorCode JsThreadServiceCallback(IntPtr callback, IntPtr callbackState);
+
+ // ======= FIXED SIGNATURES (StdCall + Unicode) =======
+
+ [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.StdCall)]
+ public static extern JsErrorCode JsCreateRuntime(
+ JsRuntimeAttributes attributes,
+ JsThreadServiceCallback threadService, // pass null if unused
+ out JsRuntime runtime);
+
+ [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.StdCall)]
+ public static extern JsErrorCode JsCreateContext(
+ JsRuntime runtime,
+ out JsContext newContext);
+
+ [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.StdCall)]
+ public static extern JsErrorCode JsSetCurrentContext(JsContext context);
+
+ // JsSourceContext is size_t → UIntPtr; strings are wide-char
+ [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
+ public static extern JsErrorCode JsRunScript(
+ string script,
+ UIntPtr sourceContext,
+ string sourceUrl,
+ out JsValue result);
+
+ [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.StdCall)]
+ public static extern JsErrorCode JsConvertValueToString(JsValue value, out JsValue stringValue);
+
+ // Returns pointer to UTF-16 buffer + length (size_t) for a JsString value
+ [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.StdCall)]
+ public static extern JsErrorCode JsStringToPointer(
+ JsValue value,
+ out IntPtr buffer,
+ out UIntPtr length);
+
+ // Unset by passing "invalid" context (JS_INVALID_REFERENCE is typically null)
+ [DllImport("ChakraCore.dll", CallingConvention = CallingConvention.StdCall)]
+ public static extern JsErrorCode JsDisposeRuntime(JsRuntime runtime);
+ }
+}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs
index 6d23016..be77132 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs
@@ -60,13 +60,13 @@ namespace WelsonJS.Launcher
}, TaskScheduler.Default);
// Add resource tools
- _tools.Add(new ResourceTools.Completion(this, _httpClient));
- _tools.Add(new ResourceTools.Settings(this, _httpClient));
- _tools.Add(new ResourceTools.ChromiumDevTools(this, _httpClient));
- _tools.Add(new ResourceTools.DnsQuery(this, _httpClient));
- _tools.Add(new ResourceTools.IpQuery(this, _httpClient));
- _tools.Add(new ResourceTools.TwoFactorAuth(this, _httpClient));
- _tools.Add(new ResourceTools.Whois(this, _httpClient));
+ _tools.Add(new ResourceTools.Completion(this, _httpClient, _logger));
+ _tools.Add(new ResourceTools.Settings(this, _httpClient, _logger));
+ _tools.Add(new ResourceTools.ChromiumDevTools(this, _httpClient, _logger));
+ _tools.Add(new ResourceTools.DnsQuery(this, _httpClient, _logger));
+ _tools.Add(new ResourceTools.IpQuery(this, _httpClient, _logger));
+ _tools.Add(new ResourceTools.TwoFactorAuth(this, _httpClient, _logger));
+ _tools.Add(new ResourceTools.Whois(this, _httpClient, _logger));
// Register the prefix
_listener.Prefixes.Add(prefix);
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/ChromiumDevTools.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/ChromiumDevTools.cs
index 81feeb3..d56c5ec 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/ChromiumDevTools.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/ChromiumDevTools.cs
@@ -19,13 +19,16 @@ namespace WelsonJS.Launcher.ResourceTools
{
private readonly ResourceServer Server;
private readonly HttpClient _httpClient;
+ private readonly ICompatibleLogger _logger;
private readonly WebSocketManager _wsManager = new WebSocketManager();
private const string Prefix = "devtools/";
- public ChromiumDevTools(ResourceServer server, HttpClient httpClient)
+ public ChromiumDevTools(ResourceServer server, HttpClient httpClient, ICompatibleLogger logger)
{
Server = server;
+
_httpClient = httpClient;
+ _logger = logger;
}
public bool CanHandle(string path)
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Completion.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Completion.cs
index 57bb482..34abe58 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Completion.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Completion.cs
@@ -22,13 +22,16 @@ namespace WelsonJS.Launcher.ResourceTools
{
private readonly ResourceServer Server;
private readonly HttpClient _httpClient;
+ private readonly ICompatibleLogger _logger;
private const string Prefix = "completion/";
private readonly ConcurrentBag DiscoveredExecutables = new ConcurrentBag();
- public Completion(ResourceServer server, HttpClient httpClient)
+ public Completion(ResourceServer server, HttpClient httpClient, ICompatibleLogger logger)
{
Server = server;
+
_httpClient = httpClient;
+ _logger = logger;
Task.Run(async () => await SafeDiscoverAsync(DiscoverFromInstalledSoftware));
Task.Run(async () => await SafeDiscoverAsync(DiscoverFromPathVariable));
@@ -160,7 +163,7 @@ namespace WelsonJS.Launcher.ResourceTools
{
if (!Directory.Exists(path))
{
- Trace.TraceInformation("Directory does not exist: {0}", path);
+ _logger.Info("Directory does not exist: {0}", path);
return;
}
@@ -175,7 +178,7 @@ namespace WelsonJS.Launcher.ResourceTools
}
catch (Exception ex)
{
- Trace.TraceInformation("Error enumerating executables in '{0}': {1}", path, ex.Message);
+ _logger.Info("Error enumerating executables in '{0}': {1}", path, ex.Message);
}
}
@@ -195,7 +198,7 @@ namespace WelsonJS.Launcher.ResourceTools
}
catch (Exception ex)
{
- Trace.TraceError($"Discovery failed: {ex.Message}");
+ _logger.Error($"Discovery failed: {ex.Message}");
}
}
}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/DnsQuery.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/DnsQuery.cs
index 3b4c8b1..831294b 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/DnsQuery.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/DnsQuery.cs
@@ -18,16 +18,19 @@ namespace WelsonJS.Launcher.ResourceTools
{
private readonly ResourceServer Server;
private readonly HttpClient _httpClient;
+ private readonly ICompatibleLogger _logger;
private const string Prefix = "dns-query/";
private string DnsServer;
private const int DnsPort = 53;
private const int Timeout = 5000;
private static readonly Random _random = new Random();
- public DnsQuery(ResourceServer server, HttpClient httpClient)
+ public DnsQuery(ResourceServer server, HttpClient httpClient, ICompatibleLogger logger)
{
Server = server;
+
_httpClient = httpClient;
+ _logger = logger;
DnsServer = Program.GetAppConfig("DnsServerAddress");
}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/IpQuery.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/IpQuery.cs
index 3a3aa6b..68d7400 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/IpQuery.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/IpQuery.cs
@@ -14,12 +14,15 @@ namespace WelsonJS.Launcher.ResourceTools
{
private readonly ResourceServer Server;
private readonly HttpClient _httpClient;
+ private readonly ICompatibleLogger _logger;
private const string Prefix = "ip-query/";
- public IpQuery(ResourceServer server, HttpClient httpClient)
+ public IpQuery(ResourceServer server, HttpClient httpClient, ICompatibleLogger logger)
{
Server = server;
+
_httpClient = httpClient;
+ _logger = logger;
}
public bool CanHandle(string path)
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Settings.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Settings.cs
index 2f74940..6d6fd94 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Settings.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Settings.cs
@@ -20,12 +20,15 @@ namespace WelsonJS.Launcher.ResourceTools
{
private readonly ResourceServer Server;
private readonly HttpClient _httpClient;
+ private readonly ICompatibleLogger _logger;
private const string Prefix = "settings";
- public Settings(ResourceServer server, HttpClient httpClient)
+ public Settings(ResourceServer server, HttpClient httpClient, ICompatibleLogger logger)
{
Server = server;
+
_httpClient = httpClient;
+ _logger = logger;
}
public bool CanHandle(string path)
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/TwoFactorAuth.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/TwoFactorAuth.cs
index e7094e2..aa44ba6 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/TwoFactorAuth.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/TwoFactorAuth.cs
@@ -19,14 +19,17 @@ namespace WelsonJS.Launcher.ResourceTools
{
private readonly ResourceServer Server;
private readonly HttpClient _httpClient;
+ private readonly ICompatibleLogger _logger;
private const string Prefix = "tfa/";
private const string Base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
private static readonly int[] ValidKeyCharLengths = new[] { 16, 32 };
- public TwoFactorAuth(ResourceServer server, HttpClient httpClient)
+ public TwoFactorAuth(ResourceServer server, HttpClient httpClient, ICompatibleLogger logger)
{
Server = server;
+
_httpClient = httpClient;
+ _logger = logger;
}
public bool CanHandle(string path)
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Whois.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Whois.cs
index 45ae8b9..fc82e85 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Whois.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceTools/Whois.cs
@@ -15,12 +15,15 @@ namespace WelsonJS.Launcher.ResourceTools
{
private readonly ResourceServer Server;
private readonly HttpClient _httpClient;
+ private readonly ICompatibleLogger _logger;
private const string Prefix = "whois/";
- public Whois(ResourceServer server, HttpClient httpClient)
+ public Whois(ResourceServer server, HttpClient httpClient, ICompatibleLogger logger)
{
Server = server;
+
_httpClient = httpClient;
+ _logger = logger;
}
public bool CanHandle(string path)
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/TraceLogger.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/TraceLogger.cs
index 5f86237..6efbaf6 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/TraceLogger.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/TraceLogger.cs
@@ -6,7 +6,9 @@
// We use the ICompatibleLogger interface to maintain a BCL-first style.
// This allows for later replacement with logging libraries such as ILogger or Log4Net.
//
+using System;
using System.Diagnostics;
+using System.Linq;
namespace WelsonJS.Launcher
{
@@ -21,7 +23,7 @@ namespace WelsonJS.Launcher
_logFileName = (typeof(TraceLogger).Namespace ?? "WelsonJS.Launcher") + ".log";
Trace.Listeners.Add(new TextWriterTraceListener(_logFileName));
}
- catch (System.Exception ex)
+ catch (Exception ex)
{
// Fallback when the process cannot write to the working directory
Trace.Listeners.Add(new ConsoleTraceListener());
@@ -30,8 +32,27 @@ namespace WelsonJS.Launcher
Trace.AutoFlush = true;
}
- public void Info(string message) => Trace.TraceInformation(message);
- public void Warn(string message) => Trace.TraceWarning(message);
- public void Error(string message) => Trace.TraceError(message);
+ public void Info(params object[] args) => Trace.TraceInformation(Format(args));
+ public void Warn(params object[] args) => Trace.TraceWarning(Format(args));
+ public void Error(params object[] args) => Trace.TraceError(Format(args));
+
+ private static string Format(object[] args)
+ {
+ if (args == null || args.Length == 0) return string.Empty;
+
+ if (args.Length == 1)
+ return args[0]?.ToString() ?? string.Empty;
+
+ string format = args[0]?.ToString() ?? string.Empty;
+ try
+ {
+ return string.Format(format, args.Skip(1).ToArray());
+ }
+ catch
+ {
+ // In case of mismatched format placeholders
+ return string.Join(" ", args);
+ }
+ }
}
}
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj b/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj
index c76f31e..a5b2e8e 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj
@@ -89,8 +89,10 @@
+
+