diff --git a/src/common/ManagedCommon/LanguageHelper.cs b/src/common/ManagedCommon/LanguageHelper.cs index 85cdcd1c335e..89b48e7ccbc2 100644 --- a/src/common/ManagedCommon/LanguageHelper.cs +++ b/src/common/ManagedCommon/LanguageHelper.cs @@ -6,6 +6,7 @@ using System.IO; using System.Text.Json; using System.Text.Json.Serialization; +using ManagedCommon.Serialization; namespace ManagedCommon { @@ -35,7 +36,7 @@ public static string LoadLanguage() inputStream.Close(); reader.Dispose(); - return JsonSerializer.Deserialize(data).LanguageTag; + return JsonSerializer.Deserialize(data, SourceGenerationContext.Default.OutGoingLanguageSettings).LanguageTag; } catch (Exception) { diff --git a/src/common/ManagedCommon/Logger.cs b/src/common/ManagedCommon/Logger.cs index 78b27afefcfc..b67d63c3b573 100644 --- a/src/common/ManagedCommon/Logger.cs +++ b/src/common/ManagedCommon/Logger.cs @@ -15,15 +15,23 @@ namespace ManagedCommon { public static class Logger { - private static readonly Assembly Assembly = Assembly.GetExecutingAssembly(); - private static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion; - private static readonly string Error = "Error"; private static readonly string Warning = "Warning"; private static readonly string Info = "Info"; private static readonly string Debug = "Debug"; private static readonly string TraceFlag = "Trace"; + private static readonly Assembly Assembly = Assembly.GetExecutingAssembly(); + + /* + * Please pay more attention! + * If you want to publish it with Native AOT enabled (or publish as a single file). + * You need to find another way to remove Assembly.Location usage. + */ +#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file + private static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion; +#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file + /// /// Initializes the logger and sets the path for logging. /// @@ -53,18 +61,16 @@ public static void InitializeLogger(string applicationLogPath, bool isLocalLow = Trace.AutoFlush = true; } - [MethodImpl(MethodImplOptions.NoInlining)] - public static void LogError(string message) + public static void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { - Log(message, Error); + Log(message, Error, memberName, sourceFilePath, sourceLineNumber); } - [MethodImpl(MethodImplOptions.NoInlining)] - public static void LogError(string message, Exception ex) + public static void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { if (ex == null) { - Log(message, Error); + Log(message, Error, memberName, sourceFilePath, sourceLineNumber); } else { @@ -83,38 +89,33 @@ public static void LogError(string message, Exception ex) "Stack trace: " + Environment.NewLine + ex.StackTrace; - Log(exMessage, Error); + Log(exMessage, Error, memberName, sourceFilePath, sourceLineNumber); } } - [MethodImpl(MethodImplOptions.NoInlining)] - public static void LogWarning(string message) + public static void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { - Log(message, Warning); + Log(message, Warning, memberName, sourceFilePath, sourceLineNumber); } - [MethodImpl(MethodImplOptions.NoInlining)] - public static void LogInfo(string message) + public static void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { - Log(message, Info); + Log(message, Info, memberName, sourceFilePath, sourceLineNumber); } - [MethodImpl(MethodImplOptions.NoInlining)] - public static void LogDebug(string message) + public static void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { - Log(message, Debug); + Log(message, Debug, memberName, sourceFilePath, sourceLineNumber); } - [MethodImpl(MethodImplOptions.NoInlining)] - public static void LogTrace() + public static void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) { - Log(string.Empty, TraceFlag); + Log(string.Empty, TraceFlag, memberName, sourceFilePath, sourceLineNumber); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static void Log(string message, string type) + private static void Log(string message, string type, string memberName, string sourceFilePath, int sourceLineNumber) { - Trace.WriteLine("[" + DateTime.Now.TimeOfDay + "] [" + type + "] " + GetCallerInfo()); + Trace.WriteLine("[" + DateTime.Now.TimeOfDay + "] [" + type + "] " + GetCallerInfo(memberName, sourceFilePath, sourceLineNumber)); Trace.Indent(); if (message != string.Empty) { @@ -124,49 +125,27 @@ private static void Log(string message, string type) Trace.Unindent(); } - [MethodImpl(MethodImplOptions.NoInlining)] - private static string GetCallerInfo() + private static string GetCallerInfo(string memberName, string sourceFilePath, int sourceLineNumber) { - StackTrace stackTrace = new(); - - var callerMethod = GetCallerMethod(stackTrace); - - return $"{callerMethod?.DeclaringType?.Name}::{callerMethod.Name}"; - } - - private static MethodBase GetCallerMethod(StackTrace stackTrace) - { - const int topFrame = 3; - - var topMethod = stackTrace.GetFrame(topFrame)?.GetMethod(); + string callerFileName = "Unknown"; try { - if (topMethod?.Name == nameof(IAsyncStateMachine.MoveNext) && typeof(IAsyncStateMachine).IsAssignableFrom(topMethod?.DeclaringType)) + string fileName = Path.GetFileName(sourceFilePath); + if (!string.IsNullOrEmpty(fileName)) { - // Async method; return actual method as determined by heuristic: - // "Nearest method on stack to async state-machine's MoveNext() in same namespace but in a different type". - // There are tighter ways of determining the actual method, but this is good enough and probably faster. - for (int deepFrame = topFrame + 1; deepFrame < stackTrace.FrameCount; deepFrame++) - { - var deepMethod = stackTrace.GetFrame(deepFrame)?.GetMethod(); - - if (deepMethod?.DeclaringType != topMethod?.DeclaringType && deepMethod?.DeclaringType?.Namespace == topMethod?.DeclaringType?.Namespace) - { - return deepMethod; - } - } + callerFileName = fileName; } } catch (Exception) { - // Ignore exceptions in Release. The code above won't throw, but if it does, we don't want to crash the app. + callerFileName = "Unknown"; #if DEBUG throw; #endif } - return topMethod; + return $"{callerFileName}::{memberName}::{sourceLineNumber}"; } } } diff --git a/src/common/ManagedCommon/ManagedCommon.csproj b/src/common/ManagedCommon/ManagedCommon.csproj index f3b149616c4c..bd7425307356 100644 --- a/src/common/ManagedCommon/ManagedCommon.csproj +++ b/src/common/ManagedCommon/ManagedCommon.csproj @@ -1,6 +1,7 @@  + PowerToys ManagedCommon diff --git a/src/common/ManagedCommon/NativeMethods.cs b/src/common/ManagedCommon/NativeMethods.cs index 998010f10a29..a8d05b7a4716 100644 --- a/src/common/ManagedCommon/NativeMethods.cs +++ b/src/common/ManagedCommon/NativeMethods.cs @@ -53,7 +53,7 @@ public struct INPUT internal static int Size { - get { return Marshal.SizeOf(typeof(INPUT)); } + get { return Marshal.SizeOf(); } } } diff --git a/src/common/ManagedCommon/RunnerHelper.cs b/src/common/ManagedCommon/RunnerHelper.cs index 67ca0856aec2..16ff45428efe 100644 --- a/src/common/ManagedCommon/RunnerHelper.cs +++ b/src/common/ManagedCommon/RunnerHelper.cs @@ -14,12 +14,11 @@ namespace ManagedCommon { public static class RunnerHelper { - public static void WaitForPowerToysRunner(int powerToysPID, Action act) + public static void WaitForPowerToysRunner(int powerToysPID, Action act, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "") { var stackTrace = new StackTrace(); var assembly = Assembly.GetCallingAssembly().GetName(); - var callingMethod = stackTrace.GetFrame(1).GetMethod().Name; - PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{callingMethod}]WaitForPowerToysRunner waiting for Event powerToysPID={powerToysPID}" }); + PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{memberName}]WaitForPowerToysRunner waiting for Event powerToysPID={powerToysPID}" }); Task.Run(() => { const uint INFINITE = 0xFFFFFFFF; @@ -29,7 +28,7 @@ public static void WaitForPowerToysRunner(int powerToysPID, Action act) IntPtr powerToysProcHandle = NativeMethods.OpenProcess(SYNCHRONIZE, false, powerToysPID); if (NativeMethods.WaitForSingleObject(powerToysProcHandle, INFINITE) == WAIT_OBJECT_0) { - PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{callingMethod}]WaitForPowerToysRunner Event Notified powerToysPID={powerToysPID}" }); + PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{memberName}]WaitForPowerToysRunner Event Notified powerToysPID={powerToysPID}" }); act.Invoke(); } }); diff --git a/src/common/ManagedCommon/SerializationContext/SourceGenerationContext.cs b/src/common/ManagedCommon/SerializationContext/SourceGenerationContext.cs new file mode 100644 index 000000000000..24a46f68d9a4 --- /dev/null +++ b/src/common/ManagedCommon/SerializationContext/SourceGenerationContext.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; +using static ManagedCommon.LanguageHelper; + +namespace ManagedCommon.Serialization; + +[JsonSerializable(typeof(OutGoingLanguageSettings))] +internal sealed partial class SourceGenerationContext : JsonSerializerContext +{ +} diff --git a/src/common/ManagedCommon/ThemeListener.cs b/src/common/ManagedCommon/ThemeListener.cs index 4e7475458155..945ab37debab 100644 --- a/src/common/ManagedCommon/ThemeListener.cs +++ b/src/common/ManagedCommon/ThemeListener.cs @@ -14,7 +14,7 @@ namespace ManagedCommon /// Sender ThemeListener public delegate void ThemeChangedEvent(ThemeListener sender); - public class ThemeListener : IDisposable + public partial class ThemeListener : IDisposable { /// /// Gets the App Theme.