mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
add log
This commit is contained in:
@@ -142,6 +142,8 @@ internal static class LayoutCommands
|
|||||||
|
|
||||||
public static (int ExitCode, string Output) SetLayout(string[] args, Action<uint> notifyFancyZones, uint wmPrivAppliedLayoutsFileUpdate)
|
public static (int ExitCode, string Output) SetLayout(string[] args, Action<uint> notifyFancyZones, uint wmPrivAppliedLayoutsFileUpdate)
|
||||||
{
|
{
|
||||||
|
Logger.LogInfo($"SetLayout called with args: [{string.Join(", ", args)}]");
|
||||||
|
|
||||||
if (args.Length == 0)
|
if (args.Length == 0)
|
||||||
{
|
{
|
||||||
return (1, "Error: set-layout requires a UUID parameter");
|
return (1, "Error: set-layout requires a UUID parameter");
|
||||||
@@ -251,9 +253,11 @@ internal static class LayoutCommands
|
|||||||
|
|
||||||
// Write back to file
|
// Write back to file
|
||||||
FancyZonesData.WriteAppliedLayouts(appliedLayouts);
|
FancyZonesData.WriteAppliedLayouts(appliedLayouts);
|
||||||
|
Logger.LogInfo($"Applied layouts file updated for {monitorsToUpdate.Count} monitor(s)");
|
||||||
|
|
||||||
// Notify FancyZones to reload
|
// Notify FancyZones to reload
|
||||||
notifyFancyZones(wmPrivAppliedLayoutsFileUpdate);
|
notifyFancyZones(wmPrivAppliedLayoutsFileUpdate);
|
||||||
|
Logger.LogInfo("FancyZones notified of layout change");
|
||||||
|
|
||||||
string layoutName = targetCustomLayout?.Name ?? targetTemplate?.Type ?? uuid;
|
string layoutName = targetCustomLayout?.Name ?? targetTemplate?.Type ?? uuid;
|
||||||
if (applyToAll)
|
if (applyToAll)
|
||||||
|
|||||||
@@ -84,9 +84,12 @@ internal static class FancyZonesData
|
|||||||
result = null;
|
result = null;
|
||||||
error = null;
|
error = null;
|
||||||
|
|
||||||
|
Logger.LogDebug($"Reading file: {filePath}");
|
||||||
|
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
{
|
{
|
||||||
error = $"File not found: {Path.GetFileName(filePath)}";
|
error = $"File not found: {Path.GetFileName(filePath)}";
|
||||||
|
Logger.LogWarning(error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,19 +100,23 @@ internal static class FancyZonesData
|
|||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
error = $"Failed to parse {Path.GetFileName(filePath)}";
|
error = $"Failed to parse {Path.GetFileName(filePath)}";
|
||||||
|
Logger.LogError(error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.LogDebug($"Successfully read {Path.GetFileName(filePath)}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (JsonException ex)
|
catch (JsonException ex)
|
||||||
{
|
{
|
||||||
error = $"JSON parse error in {Path.GetFileName(filePath)}: {ex.Message}";
|
error = $"JSON parse error in {Path.GetFileName(filePath)}: {ex.Message}";
|
||||||
|
Logger.LogError(error, ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
error = $"Failed to read {Path.GetFileName(filePath)}: {ex.Message}";
|
error = $"Failed to read {Path.GetFileName(filePath)}: {ex.Message}";
|
||||||
|
Logger.LogError(error, ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,7 +134,9 @@ internal static class FancyZonesData
|
|||||||
|
|
||||||
private static void WriteJsonFile<T>(string filePath, T data, JsonTypeInfo<T> jsonTypeInfo)
|
private static void WriteJsonFile<T>(string filePath, T data, JsonTypeInfo<T> jsonTypeInfo)
|
||||||
{
|
{
|
||||||
|
Logger.LogDebug($"Writing file: {filePath}");
|
||||||
var json = JsonSerializer.Serialize(data, jsonTypeInfo);
|
var json = JsonSerializer.Serialize(data, jsonTypeInfo);
|
||||||
File.WriteAllText(filePath, json);
|
File.WriteAllText(filePath, json);
|
||||||
|
Logger.LogInfo($"Successfully wrote {Path.GetFileName(filePath)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
126
src/modules/fancyzones/FancyZonesCLI/Logger.cs
Normal file
126
src/modules/fancyzones/FancyZonesCLI/Logger.cs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
// 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;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace FancyZonesCLI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simple logger for FancyZones CLI.
|
||||||
|
/// Logs to %LOCALAPPDATA%\Microsoft\PowerToys\FancyZones\CLI\Logs
|
||||||
|
/// </summary>
|
||||||
|
internal static class Logger
|
||||||
|
{
|
||||||
|
private static readonly object LockObj = new();
|
||||||
|
private static string _logFilePath = string.Empty;
|
||||||
|
private static bool _isInitialized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path to the current log file.
|
||||||
|
/// </summary>
|
||||||
|
public static string LogFilePath => _logFilePath;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the logger.
|
||||||
|
/// </summary>
|
||||||
|
public static void InitializeLogger()
|
||||||
|
{
|
||||||
|
if (_isInitialized)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
|
var logDirectory = Path.Combine(localAppData, "Microsoft", "PowerToys", "FancyZones", "CLI", "Logs");
|
||||||
|
|
||||||
|
if (!Directory.Exists(logDirectory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(logDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
var logFileName = $"FancyZonesCLI_{DateTime.Now:yyyy-MM-dd}.log";
|
||||||
|
_logFilePath = Path.Combine(logDirectory, logFileName);
|
||||||
|
_isInitialized = true;
|
||||||
|
|
||||||
|
LogInfo("FancyZones CLI started");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Silently fail if logging cannot be initialized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an error message.
|
||||||
|
/// </summary>
|
||||||
|
public static void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||||
|
{
|
||||||
|
Log("ERROR", message, memberName, sourceFilePath, sourceLineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an error message with exception details.
|
||||||
|
/// </summary>
|
||||||
|
public static void LogError(string message, Exception ex, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||||
|
{
|
||||||
|
var fullMessage = ex == null
|
||||||
|
? message
|
||||||
|
: $"{message} | Exception: {ex.GetType().Name}: {ex.Message}";
|
||||||
|
Log("ERROR", fullMessage, memberName, sourceFilePath, sourceLineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a warning message.
|
||||||
|
/// </summary>
|
||||||
|
public static void LogWarning(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||||
|
{
|
||||||
|
Log("WARN", message, memberName, sourceFilePath, sourceLineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an informational message.
|
||||||
|
/// </summary>
|
||||||
|
public static void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||||
|
{
|
||||||
|
Log("INFO", message, memberName, sourceFilePath, sourceLineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a debug message (only in DEBUG builds).
|
||||||
|
/// </summary>
|
||||||
|
[System.Diagnostics.Conditional("DEBUG")]
|
||||||
|
public static void LogDebug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
|
||||||
|
{
|
||||||
|
Log("DEBUG", message, memberName, sourceFilePath, sourceLineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Log(string level, string message, string memberName, string sourceFilePath, int sourceLineNumber)
|
||||||
|
{
|
||||||
|
if (!_isInitialized || string.IsNullOrEmpty(_logFilePath))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(sourceFilePath);
|
||||||
|
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
|
||||||
|
var logEntry = $"[{timestamp}] [{level}] [{fileName}:{sourceLineNumber}] [{memberName}] {message}{Environment.NewLine}";
|
||||||
|
|
||||||
|
lock (LockObj)
|
||||||
|
{
|
||||||
|
File.AppendAllText(_logFilePath, logEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Silently fail if logging fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,10 @@ internal sealed class Program
|
|||||||
{
|
{
|
||||||
private static int Main(string[] args)
|
private static int Main(string[] args)
|
||||||
{
|
{
|
||||||
|
// Initialize logger
|
||||||
|
Logger.InitializeLogger();
|
||||||
|
Logger.LogInfo($"CLI invoked with args: [{string.Join(", ", args)}]");
|
||||||
|
|
||||||
// Initialize Windows messages
|
// Initialize Windows messages
|
||||||
NativeMethods.InitializeWindowMessages();
|
NativeMethods.InitializeWindowMessages();
|
||||||
|
|
||||||
@@ -48,6 +52,16 @@ internal sealed class Program
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log result
|
||||||
|
if (result.ExitCode == 0)
|
||||||
|
{
|
||||||
|
Logger.LogInfo($"Command completed successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.LogWarning($"Command failed with exit code {result.ExitCode}: {result.Output}");
|
||||||
|
}
|
||||||
|
|
||||||
// Output result
|
// Output result
|
||||||
if (!string.IsNullOrEmpty(result.Output))
|
if (!string.IsNullOrEmpty(result.Output))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user