[cmdpal] [AOT] make Clipboard/System/WebSearch/WindowsSettings ext become AOT compatible. (#39080)

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
This commit is contained in:
Yu Leng
2025-04-25 16:22:50 +08:00
committed by GitHub
parent 7dc2a05c45
commit 9a6c64f9c0
11 changed files with 64 additions and 18 deletions

View File

@@ -17,7 +17,7 @@ internal static class NativeMethods
internal INPUTTYPE type; internal INPUTTYPE type;
internal InputUnion data; internal InputUnion data;
internal static int Size => Marshal.SizeOf(typeof(INPUT)); internal static int Size => Marshal.SizeOf<INPUT>();
} }
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]

View File

@@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" /> <Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup> <PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Ext.ClipboardHistory</RootNamespace> <RootNamespace>Microsoft.CmdPal.Ext.ClipboardHistory</RootNamespace>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath> <OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>

View File

@@ -311,14 +311,14 @@ internal sealed class NetworkConnectionProperties
{ {
switch (property) switch (property)
{ {
case string: case string str:
return string.IsNullOrWhiteSpace(property) ? string.Empty : $"\n\n{title}{property}"; return string.IsNullOrWhiteSpace(str) ? string.Empty : $"\n\n{title}{str}";
case List<string> listString: case List<string> listString:
return listString.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", property)}"; return listString.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", listString)}";
case List<IPAddress> listIP: case List<IPAddress> listIP:
return listIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", property)}"; return listIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", listIP)}";
case IPAddressCollection collectionIP: case IPAddressCollection collectionIP:
return collectionIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", property)}"; return collectionIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", collectionIP)}";
case null: case null:
return string.Empty; return string.Empty;
default: default:

View File

@@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" /> <Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup> <PropertyGroup>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Microsoft.CmdPal.Ext.System</RootNamespace> <RootNamespace>Microsoft.CmdPal.Ext.System</RootNamespace>

View File

@@ -13,5 +13,5 @@ public class HistoryItem(string searchString, DateTime timestamp)
public DateTime Timestamp { get; private set; } = timestamp; public DateTime Timestamp { get; private set; } = timestamp;
public string ToJson() => JsonSerializer.Serialize(this); public string ToJson() => JsonSerializer.Serialize(this, WebSearchJsonSerializationContext.Default.HistoryItem);
} }

View File

@@ -80,7 +80,7 @@ public class SettingsManager : JsonSettingsManager
if (File.Exists(_historyPath)) if (File.Exists(_historyPath))
{ {
var existingContent = File.ReadAllText(_historyPath); var existingContent = File.ReadAllText(_historyPath);
historyItems = JsonSerializer.Deserialize<List<HistoryItem>>(existingContent) ?? []; historyItems = JsonSerializer.Deserialize<List<HistoryItem>>(existingContent, WebSearchJsonSerializationContext.Default.ListHistoryItem) ?? [];
} }
else else
{ {
@@ -101,7 +101,7 @@ public class SettingsManager : JsonSettingsManager
} }
// Serialize the updated list back to JSON and save it // Serialize the updated list back to JSON and save it
var historyJson = JsonSerializer.Serialize(historyItems); var historyJson = JsonSerializer.Serialize(historyItems, WebSearchJsonSerializationContext.Default.ListHistoryItem);
File.WriteAllText(_historyPath, historyJson); File.WriteAllText(_historyPath, historyJson);
} }
catch (Exception ex) catch (Exception ex)
@@ -121,7 +121,7 @@ public class SettingsManager : JsonSettingsManager
// Read and deserialize JSON into a list of HistoryItem objects // Read and deserialize JSON into a list of HistoryItem objects
var fileContent = File.ReadAllText(_historyPath); var fileContent = File.ReadAllText(_historyPath);
var historyItems = JsonSerializer.Deserialize<List<HistoryItem>>(fileContent) ?? []; var historyItems = JsonSerializer.Deserialize<List<HistoryItem>>(fileContent, WebSearchJsonSerializationContext.Default.ListHistoryItem) ?? [];
// Convert each HistoryItem to a ListItem // Convert each HistoryItem to a ListItem
var listItems = new List<ListItem>(); var listItems = new List<ListItem>();
@@ -198,7 +198,7 @@ public class SettingsManager : JsonSettingsManager
if (File.Exists(_historyPath)) if (File.Exists(_historyPath))
{ {
var existingContent = File.ReadAllText(_historyPath); var existingContent = File.ReadAllText(_historyPath);
var historyItems = JsonSerializer.Deserialize<List<HistoryItem>>(existingContent) ?? []; var historyItems = JsonSerializer.Deserialize<List<HistoryItem>>(existingContent, WebSearchJsonSerializationContext.Default.ListHistoryItem) ?? [];
// Check if trimming is needed // Check if trimming is needed
if (historyItems.Count > maxHistoryItems) if (historyItems.Count > maxHistoryItems)
@@ -207,7 +207,7 @@ public class SettingsManager : JsonSettingsManager
historyItems = historyItems.Skip(historyItems.Count - maxHistoryItems).ToList(); historyItems = historyItems.Skip(historyItems.Count - maxHistoryItems).ToList();
// Save the trimmed history back to the file // Save the trimmed history back to the file
var trimmedHistoryJson = JsonSerializer.Serialize(historyItems); var trimmedHistoryJson = JsonSerializer.Serialize(historyItems, WebSearchJsonSerializationContext.Default.ListHistoryItem);
File.WriteAllText(_historyPath, trimmedHistoryJson); File.WriteAllText(_historyPath, trimmedHistoryJson);
} }
} }

View File

@@ -0,0 +1,20 @@
// 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.Collections.Generic;
using System.Text.Json.Serialization;
using Microsoft.CmdPal.Ext.WebSearch.Helpers;
namespace Microsoft.CmdPal.Ext.WebSearch;
[JsonSerializable(typeof(float))]
[JsonSerializable(typeof(int))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(bool))]
[JsonSerializable(typeof(HistoryItem))]
[JsonSerializable(typeof(List<HistoryItem>))]
[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)]
internal sealed partial class WebSearchJsonSerializationContext : JsonSerializerContext
{
}

View File

@@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" /> <Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup> <PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Ext.WebSearch</RootNamespace> <RootNamespace>Microsoft.CmdPal.Ext.WebSearch</RootNamespace>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>

View File

@@ -4,10 +4,8 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers; namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
@@ -21,6 +19,8 @@ internal static class JsonSettingsListHelper
/// </summary> /// </summary>
private const string _settingsFile = "WindowsSettings.json"; private const string _settingsFile = "WindowsSettings.json";
private const string _extTypeNamespace = "Microsoft.CmdPal.Ext.WindowsSettings";
private static readonly JsonSerializerOptions _serializerOptions = new() private static readonly JsonSerializerOptions _serializerOptions = new()
{ {
}; };
@@ -32,7 +32,6 @@ internal static class JsonSettingsListHelper
internal static Classes.WindowsSettings ReadAllPossibleSettings() internal static Classes.WindowsSettings ReadAllPossibleSettings()
{ {
var assembly = Assembly.GetExecutingAssembly(); var assembly = Assembly.GetExecutingAssembly();
var type = assembly.GetTypes().FirstOrDefault(x => x.Name == nameof(WindowsSettingsCommandsProvider));
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. #pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
Classes.WindowsSettings? settings = null; Classes.WindowsSettings? settings = null;
@@ -40,7 +39,7 @@ internal static class JsonSettingsListHelper
try try
{ {
var resourceName = $"{type?.Namespace}.{_settingsFile}"; var resourceName = $"{_extTypeNamespace}.{_settingsFile}";
using var stream = assembly.GetManifestResourceStream(resourceName); using var stream = assembly.GetManifestResourceStream(resourceName);
if (stream is null) if (stream is null)
{ {
@@ -48,12 +47,13 @@ internal static class JsonSettingsListHelper
} }
var options = _serializerOptions; var options = _serializerOptions;
options.Converters.Add(new JsonStringEnumConverter());
// Why we need it? I don't see any enum usage in WindowsSettings
// options.Converters.Add(new JsonStringEnumConverter());
using var reader = new StreamReader(stream); using var reader = new StreamReader(stream);
var text = reader.ReadToEnd(); var text = reader.ReadToEnd();
settings = JsonSerializer.Deserialize<Classes.WindowsSettings>(text, options); settings = JsonSerializer.Deserialize(text, WindowsSettingsJsonSerializationContext.Default.WindowsSettings);
} }
#pragma warning disable CS0168 #pragma warning disable CS0168
catch (Exception exception) catch (Exception exception)

View File

@@ -0,0 +1,22 @@
// 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.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Microsoft.CmdPal.Ext.WindowsSettings;
[JsonSerializable(typeof(float))]
[JsonSerializable(typeof(int))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(bool))]
[JsonSerializable(typeof(Classes.WindowsSettings))]
[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)]
internal sealed partial class WindowsSettingsJsonSerializationContext : JsonSerializerContext
{
}

View File

@@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" /> <Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup> <PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Ext.WindowsSettings</RootNamespace> <RootNamespace>Microsoft.CmdPal.Ext.WindowsSettings</RootNamespace>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath> <OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>