diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 482d219ddbe..785ae7f40f0 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -197,6 +197,7 @@ CMock CMONITORS cmpgt cne +CNF coclass codeofconduct codereview diff --git a/Directory.Packages.props b/Directory.Packages.props index b26458ba2de..00c6b8f96af 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -34,7 +34,6 @@ - @@ -77,7 +76,6 @@ - diff --git a/NOTICE.md b/NOTICE.md index a3c40e7a65b..c62bee93f61 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1323,7 +1323,6 @@ EXHIBIT A -Mozilla Public License. - Microsoft.Extensions.Hosting.WindowsServices 8.0.0 - Microsoft.Extensions.Logging 8.0.0 - Microsoft.Extensions.Logging.Abstractions 8.0.0 -- Microsoft.Extensions.ObjectPool 8.0.0 - Microsoft.NET.Test.Sdk 17.8.0 - Microsoft.Toolkit.Uwp.Notifications 7.1.2 - Microsoft.Web.WebView2 1.0.2365.46 @@ -1358,7 +1357,6 @@ EXHIBIT A -Mozilla Public License. - System.IO.Abstractions 17.2.3 - System.IO.Abstractions.TestingHelpers 17.2.3 - System.Management 8.0.0 -- System.Management.Automation 7.4.0 - System.Reactive 6.0.0-preview.9 - System.Runtime.Caching 8.0.0 - System.Security.Cryptography.ProtectedData 8.0.0 diff --git a/PowerToys.sln b/PowerToys.sln index 6fd164f0887..ce05c576ff6 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -538,8 +538,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CropAndLock", "src\modules\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CropAndLockModuleInterface", "src\modules\CropAndLock\CropAndLockModuleInterface\CropAndLockModuleInterface.vcxproj", "{3157FA75-86CF-4EE2-8F62-C43F776493C6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CmdNotFound", "src\modules\cmdNotFound\CmdNotFound\CmdNotFound.csproj", "{A37865FE-2881-449F-8ADB-B8CD373D6D79}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cmdNotFound", "cmdNotFound", "{4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-FancyZonesEditor", "src\modules\fancyzones\UnitTests-FancyZonesEditor\UnitTests-FancyZonesEditor.csproj", "{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}" @@ -2357,18 +2355,6 @@ Global {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x64.Build.0 = Release|x64 {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x86.ActiveCfg = Release|x64 {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x86.Build.0 = Release|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|ARM64.Build.0 = Debug|ARM64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x64.ActiveCfg = Debug|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x64.Build.0 = Debug|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x86.ActiveCfg = Debug|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Debug|x86.Build.0 = Debug|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|ARM64.ActiveCfg = Release|ARM64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|ARM64.Build.0 = Release|ARM64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x64.ActiveCfg = Release|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x64.Build.0 = Release|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x86.ActiveCfg = Release|x64 - {A37865FE-2881-449F-8ADB-B8CD373D6D79}.Release|x86.Build.0 = Release|x64 {FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|ARM64.Build.0 = Debug|ARM64 {FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|x64.ActiveCfg = Debug|x64 @@ -2791,7 +2777,6 @@ Global {3B227528-4BA6-4CAF-B44A-A10C78A64849} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {F5E1146E-B7B3-4E11-85FD-270A500BD78C} = {3B227528-4BA6-4CAF-B44A-A10C78A64849} {3157FA75-86CF-4EE2-8F62-C43F776493C6} = {3B227528-4BA6-4CAF-B44A-A10C78A64849} - {A37865FE-2881-449F-8ADB-B8CD373D6D79} = {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B} {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {FC8EB78F-F061-4BD9-A3F6-507BEA965E2B} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} diff --git a/installer/PowerToysSetup/CmdNotFound.wxs b/installer/PowerToysSetup/CmdNotFound.wxs deleted file mode 100644 index 3ac8445d887..00000000000 --- a/installer/PowerToysSetup/CmdNotFound.wxs +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/installer/PowerToysSetup/Common.wxi b/installer/PowerToysSetup/Common.wxi index 6e68ce19861..4a1c93fc8ea 100644 --- a/installer/PowerToysSetup/Common.wxi +++ b/installer/PowerToysSetup/Common.wxi @@ -18,7 +18,6 @@ - diff --git a/installer/PowerToysSetup/PowerToysInstaller.wixproj b/installer/PowerToysSetup/PowerToysInstaller.wixproj index 8fb186ebb64..926ba624dce 100644 --- a/installer/PowerToysSetup/PowerToysInstaller.wixproj +++ b/installer/PowerToysSetup/PowerToysInstaller.wixproj @@ -104,7 +104,6 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil - diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index e1e2fa8949e..1fe1c838d9b 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -72,7 +72,6 @@ - @@ -135,6 +134,7 @@ + @@ -164,6 +164,9 @@ Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") + + WIX_UPGRADE_DETECTED + Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") @@ -209,6 +212,10 @@ Property="UninstallCommandNotFound" Value="[INSTALLFOLDER]" /> + + @@ -269,6 +276,14 @@ BinaryKey="PTCustomActions" DllEntry="UninstallCommandNotFoundModuleCA" /> + + + diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp index 8384d9ba7c8..7a79ab238d2 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.cpp +++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp @@ -457,6 +457,30 @@ UINT __stdcall UninstallCommandNotFoundModuleCA(MSIHANDLE hInstall) return WcaFinalize(er); } +UINT __stdcall UpgradeCommandNotFoundModuleCA(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + std::wstring installationFolder; + std::string command; + + hr = WcaInitialize(hInstall, "UpgradeCommandNotFoundModule"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = getInstallFolder(hInstall, installationFolder); + ExitOnFailure(hr, "Failed to get installFolder."); + + command = "pwsh.exe"; + command += " "; + command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(installationFolder) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\UpgradeModule.ps1" + "\""; + + system(command.c_str()); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + UINT __stdcall UninstallServicesCA(MSIHANDLE hInstall) { HRESULT hr = S_OK; diff --git a/installer/PowerToysSetupCustomActions/CustomAction.def b/installer/PowerToysSetupCustomActions/CustomAction.def index 6a503da797c..7a4929935c3 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.def +++ b/installer/PowerToysSetupCustomActions/CustomAction.def @@ -23,4 +23,5 @@ EXPORTS UnRegisterContextMenuPackagesCA UninstallEmbeddedMSIXCA UninstallServicesCA - UninstallCommandNotFoundModuleCA \ No newline at end of file + UninstallCommandNotFoundModuleCA + UpgradeCommandNotFoundModuleCA \ No newline at end of file diff --git a/src/modules/cmdNotFound/CmdNotFound/CmdNotFound.csproj b/src/modules/cmdNotFound/CmdNotFound/CmdNotFound.csproj deleted file mode 100644 index 65e6a0436e4..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/CmdNotFound.csproj +++ /dev/null @@ -1,69 +0,0 @@ - - - - - net8.0-windows10.0.22621.0 - 10.0.19041.0 - 10.0.19041.0 - win-x64;win-arm64 - enable - Microsoft Corporation - PowerToys - enable - PowerToys CommandNotFound - PowerToys.CmdNotFound - false - true - ..\..\..\..\$(Platform)\$(Configuration) - false - false - true - true - - - - - win-x64 - - - win-arm64 - - - - DEBUG;TRACE - full - prompt - 4 - false - - - - TRACE;RELEASE - true - pdbonly - prompt - 4 - - - - - contentFiles - all - runtime; compile; build; native; analyzers; buildtransitive - - - contentFiles - all - - - PreserveNewest - PreserveNewest - - - - - - - - - diff --git a/src/modules/cmdNotFound/CmdNotFound/Init.cs b/src/modules/cmdNotFound/CmdNotFound/Init.cs deleted file mode 100644 index 4d4ecb6d60c..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/Init.cs +++ /dev/null @@ -1,57 +0,0 @@ -// 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.Management.Automation; -using System.Management.Automation.Subsystem; -using System.Management.Automation.Subsystem.Feedback; -using System.Management.Automation.Subsystem.Prediction; - -namespace WinGetCommandNotFound -{ - public sealed class Init : IModuleAssemblyInitializer, IModuleAssemblyCleanup - { - internal const string Id = "e5351aa4-dfde-4d4d-bf0f-1a2f5a37d8d6"; - - public void OnImport() - { - if (!Platform.IsWindows || !IsWinGetInstalled()) - { - return; - } - - SubsystemManager.RegisterSubsystem(SubsystemKind.FeedbackProvider, WinGetCommandNotFoundFeedbackPredictor.Singleton); - SubsystemManager.RegisterSubsystem(SubsystemKind.CommandPredictor, WinGetCommandNotFoundFeedbackPredictor.Singleton); - } - - public void OnRemove(PSModuleInfo psModuleInfo) - { - if (!IsWinGetInstalled()) - { - return; - } - - SubsystemManager.UnregisterSubsystem(new Guid(Id)); - SubsystemManager.UnregisterSubsystem(new Guid(Id)); - } - - private bool IsWinGetInstalled() - { - // Ensure WinGet is installed - using (var pwsh = PowerShell.Create(RunspaceMode.CurrentRunspace)) - { - var results = pwsh.AddCommand("Get-Command") - .AddParameter("Name", "winget") - .AddParameter("CommandType", "Application") - .Invoke(); - - if (results.Count is 0) - { - return false; - } - } - - return true; - } - } -} diff --git a/src/modules/cmdNotFound/CmdNotFound/PooledPowerShellObjectPolicy.cs b/src/modules/cmdNotFound/CmdNotFound/PooledPowerShellObjectPolicy.cs deleted file mode 100644 index 75d2ba8922c..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/PooledPowerShellObjectPolicy.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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.Management.Automation; -using System.Management.Automation.Runspaces; -using Microsoft.Extensions.ObjectPool; - -namespace WinGetCommandNotFound -{ - public sealed class PooledPowerShellObjectPolicy : IPooledObjectPolicy - { - private static readonly string[] WingetClientModuleName = new[] { "Microsoft.WinGet.Client" }; - - public PowerShell Create() - { - var iss = InitialSessionState.CreateDefault2(); - iss.ImportPSModule(WingetClientModuleName); - return PowerShell.Create(iss); - } - - public bool Return(PowerShell obj) - { - if (obj != null) - { - obj.Commands.Clear(); - obj.Streams.ClearStreams(); - return true; - } - - return false; - } - } -} diff --git a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundFeedbackProvidedEvent.cs b/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundFeedbackProvidedEvent.cs deleted file mode 100644 index 83563bbe351..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundFeedbackProvidedEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.Diagnostics.Tracing; -using Microsoft.PowerToys.Telemetry; -using Microsoft.PowerToys.Telemetry.Events; - -namespace WinGetCommandNotFound.Telemetry -{ - [EventData] - public class CmdNotFoundFeedbackProvidedEvent : EventBase, IEvent - { - public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; - } -} diff --git a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundFeedbackProvidedFailureEvent.cs b/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundFeedbackProvidedFailureEvent.cs deleted file mode 100644 index efa58bf4f14..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundFeedbackProvidedFailureEvent.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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.Diagnostics.Tracing; -using Microsoft.PowerToys.Telemetry; -using Microsoft.PowerToys.Telemetry.Events; - -namespace WinGetCommandNotFound.Telemetry -{ - [EventData] - public class CmdNotFoundFeedbackProvidedFailureEvent : EventBase, IEvent - { - public string Message { get; set; } = string.Empty; - - public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; - } -} diff --git a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundInstanceCreatedEvent.cs b/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundInstanceCreatedEvent.cs deleted file mode 100644 index 0889f35f185..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundInstanceCreatedEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.Diagnostics.Tracing; -using Microsoft.PowerToys.Telemetry; -using Microsoft.PowerToys.Telemetry.Events; - -namespace WinGetCommandNotFound.Telemetry -{ - [EventData] - public class CmdNotFoundInstanceCreatedEvent : EventBase, IEvent - { - public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; - } -} diff --git a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundSuggestionProvidedEvent.cs b/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundSuggestionProvidedEvent.cs deleted file mode 100644 index 2f55dbbb390..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/Telemetry/CmdNotFoundSuggestionProvidedEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.Diagnostics.Tracing; -using Microsoft.PowerToys.Telemetry; -using Microsoft.PowerToys.Telemetry.Events; - -namespace WinGetCommandNotFound.Telemetry -{ - [EventData] - public class CmdNotFoundSuggestionProvidedEvent : EventBase, IEvent - { - public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage; - } -} diff --git a/src/modules/cmdNotFound/CmdNotFound/WinGetCommandNotFound.psd1 b/src/modules/cmdNotFound/CmdNotFound/WinGetCommandNotFound.psd1 deleted file mode 100644 index c7a1118eac1..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/WinGetCommandNotFound.psd1 +++ /dev/null @@ -1,11 +0,0 @@ -@{ - ModuleVersion = '0.1.0' - GUID = '28c9afa2-92e5-413e-8e53-44b2d7a83ac6' - Author = 'Carlos Zamora' - CompanyName = "Microsoft Corporation" - Copyright = "Copyright (c) Microsoft Corporation." - Description = 'Enable suggestions on how to install missing commands via winget' - PowerShellVersion = '7.4' - NestedModules = @('PowerToys.CmdNotFound.dll') - RequiredModules = @(@{ModuleName = 'Microsoft.WinGet.Client'; ModuleVersion = "0.2.1"; }) -} diff --git a/src/modules/cmdNotFound/CmdNotFound/WinGetCommandNotFoundFeedbackPredictor.cs b/src/modules/cmdNotFound/CmdNotFound/WinGetCommandNotFoundFeedbackPredictor.cs deleted file mode 100644 index 8a307167e96..00000000000 --- a/src/modules/cmdNotFound/CmdNotFound/WinGetCommandNotFoundFeedbackPredictor.cs +++ /dev/null @@ -1,221 +0,0 @@ -// 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; -using System.Collections.ObjectModel; -using System.Globalization; -using System.Management.Automation; -using System.Management.Automation.Subsystem.Feedback; -using System.Management.Automation.Subsystem.Prediction; -using ManagedCommon; -using Microsoft.Extensions.ObjectPool; -using Microsoft.PowerToys.Telemetry; - -namespace WinGetCommandNotFound -{ - public sealed class WinGetCommandNotFoundFeedbackPredictor : IFeedbackProvider, ICommandPredictor - { - private readonly Guid _guid; - - private readonly ObjectPool _pool; - - private const int _maxSuggestions = 20; - - private List? _candidates; - - private bool _warmedUp; - - public static WinGetCommandNotFoundFeedbackPredictor Singleton { get; } = new WinGetCommandNotFoundFeedbackPredictor(Init.Id); - - private WinGetCommandNotFoundFeedbackPredictor(string guid) - { - Logger.InitializeLogger("\\CmdNotFound\\Logs"); - - _guid = new Guid(guid); - - var provider = new DefaultObjectPoolProvider(); - _pool = provider.Create(new PooledPowerShellObjectPolicy()); - _pool.Return(_pool.Get()); - Task.Run(() => WarmUp()); - - // Telemetry that a shell is creating an instance of CommandNotFound. - PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundInstanceCreatedEvent()); - } - - public Guid Id => _guid; - - public string Name => "Windows Package Manager - WinGet"; - - public string Description => "Finds missing commands that can be installed via WinGet."; - - public Dictionary? FunctionsToDefine => null; - - private void WarmUp() - { - var ps = _pool.Get(); - try - { - ps.AddCommand("Find-WinGetPackage") - .AddParameter("Count", 1) - .Invoke(); - } - finally - { - _pool.Return(ps); - _warmedUp = true; - } - } - - /// - /// Gets feedback based on the given commandline and error record. - /// - public FeedbackItem? GetFeedback(FeedbackContext context, CancellationToken token) - { - var target = (string)context.LastError!.TargetObject; - if (target is not null) - { - try - { - bool tooManySuggestions = false; - string packageMatchFilterField = "command"; - var pkgList = FindPackages(target, ref tooManySuggestions, ref packageMatchFilterField); - if (pkgList.Count == 0) - { - return null; - } - - // Build list of suggestions - _candidates = new List(); - foreach (var pkg in pkgList) - { - _candidates.Add(string.Format(CultureInfo.InvariantCulture, "winget install --id {0}", pkg.Members["Id"].Value.ToString())); - } - - // Build footer message - var footerMessage = tooManySuggestions ? - string.Format(CultureInfo.InvariantCulture, "Additional results can be found using \"winget search --{0} {1}\"", packageMatchFilterField, target) : - null; - - PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundFeedbackProvidedEvent()); - - return new FeedbackItem( - "Try installing this package using winget:", - _candidates, - footerMessage, - FeedbackDisplayLayout.Portrait); - } - catch (Exception ex) - { - Logger.LogError("GetFeedback failed to execute", ex); - PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundFeedbackProvidedFailureEvent { Message = ex.Message }); - return new FeedbackItem($"Failed to execute PowerToys Command Not Found.{Environment.NewLine}This is a known issue if PowerShell 7 is installed from the Store or MSIX. If that isn't your case, please report an issue.", new List(), FeedbackDisplayLayout.Portrait); - } - } - - return null; - } - - private Collection FindPackages(string query, ref bool tooManySuggestions, ref string packageMatchFilterField) - { - if (!_warmedUp) - { - return new Collection(); - } - - var ps = _pool.Get(); - try - { - var common = new Hashtable() - { - ["Source"] = "winget", - }; - - // 1) Search by command - var pkgList = ps.AddCommand("Find-WinGetPackage") - .AddParameter("Command", query) - .AddParameter("MatchOption", "StartsWithCaseInsensitive") - .AddParameters(common) - .Invoke(); - if (pkgList.Count > 0) - { - tooManySuggestions = pkgList.Count > _maxSuggestions; - packageMatchFilterField = "command"; - return pkgList; - } - - // 2) No matches found, - // search by name - ps.Commands.Clear(); - pkgList = ps.AddCommand("Find-WinGetPackage") - .AddParameter("Name", query) - .AddParameter("MatchOption", "ContainsCaseInsensitive") - .AddParameters(common) - .Invoke(); - if (pkgList.Count > 0) - { - tooManySuggestions = pkgList.Count > _maxSuggestions; - packageMatchFilterField = "name"; - return pkgList; - } - - // 3) No matches found, - // search by moniker - ps.Commands.Clear(); - pkgList = ps.AddCommand("Find-WinGetPackage") - .AddParameter("Moniker", query) - .AddParameter("MatchOption", "ContainsCaseInsensitive") - .AddParameters(common) - .Invoke(); - tooManySuggestions = pkgList.Count > _maxSuggestions; - packageMatchFilterField = "moniker"; - return pkgList; - } - finally - { - _pool.Return(ps); - } - } - - public bool CanAcceptFeedback(PredictionClient client, PredictorFeedbackKind feedback) - { - return feedback switch - { - PredictorFeedbackKind.CommandLineAccepted => true, - _ => false, - }; - } - - public SuggestionPackage GetSuggestion(PredictionClient client, PredictionContext context, CancellationToken cancellationToken) - { - if (_candidates is not null) - { - string input = context.InputAst.Extent.Text; - List? result = null; - - foreach (string c in _candidates) - { - if (c.StartsWith(input, StringComparison.OrdinalIgnoreCase)) - { - result ??= new List(_candidates.Count); - result.Add(new PredictiveSuggestion(c)); - } - } - - if (result is not null) - { - PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundSuggestionProvidedEvent()); - return new SuggestionPackage(result); - } - } - - return default; - } - - public void OnCommandLineAccepted(PredictionClient client, IReadOnlyList history) - { - // Reset the candidate state. - _candidates = null; - } - } -} diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/CheckCmdNotFoundRequirements.ps1 b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/CheckCmdNotFoundRequirements.ps1 index 260d75c5334..b8f9ceed995 100644 --- a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/CheckCmdNotFoundRequirements.ps1 +++ b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/CheckCmdNotFoundRequirements.ps1 @@ -10,10 +10,25 @@ else # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. } -if (Get-Module -ListAvailable -Name Microsoft.WinGet.Client) +if ($mods = Get-Module -ListAvailable -Name Microsoft.WinGet.Client) { Write-Host "WinGet Client module detected." # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. + + $needsUpdate = $true; + foreach ($mod in $mods) + { + if ($mod.Version -ge "1.8.1133") + { + $needsUpdate = $false; + break; + } + } + if ($needsUpdate) + { + Write-Host "WinGet Client module needs to be updated." + # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. + } } else { Write-Host "WinGet Client module not detected. Installation instructions can be found on https://www.powershellgallery.com/packages/Microsoft.WinGet.Client `r`n" @@ -30,6 +45,11 @@ if (!(Test-Path $PROFILE)) $profileContent = Get-Content -Path $PROFILE -Raw if ((-not [string]::IsNullOrEmpty($profileContent)) -and ($profileContent.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756"))) +{ + Write-Host "Outdated version of Command Not Found module found in the profile file." + # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. +} +elseif ((-not [string]::IsNullOrEmpty($profileContent)) -and ($profileContent.Contains("f45873b3-b655-43a6-b217-97c00aa0db58"))) { Write-Host "Command Not Found module is registered in the profile file." # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/DisableModule.ps1 b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/DisableModule.ps1 index 501c4c4141e..6cfd9767fc2 100644 --- a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/DisableModule.ps1 +++ b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/DisableModule.ps1 @@ -5,14 +5,14 @@ $linesToDeleteFound = $False $atLeastOneInstanceFound = $False $profileContent | ForEach-Object { - if ($_.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756") -and !$linesToDeleteFound) + if (($_.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756") -or $_.Contains("f45873b3-b655-43a6-b217-97c00aa0db58")) -and !$linesToDeleteFound) { $linesToDeleteFound = $True $atLeastOneInstanceFound = $True return } - if ($_.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756") -and $linesToDeleteFound) + if (($_.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756") -or $_.Contains("f45873b3-b655-43a6-b217-97c00aa0db58")) -and $linesToDeleteFound) { $linesToDeleteFound = $False return diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 index 3b4842dba14..a2943e4d4ea 100644 --- a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 +++ b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 @@ -9,13 +9,36 @@ Enable-ExperimentalFeature PSFeedbackProvider Write-Host "Enabling experimental feature: PSCommandNotFoundSuggestion" Enable-ExperimentalFeature PSCommandNotFoundSuggestion -if (Get-Module -ListAvailable -Name Microsoft.WinGet.Client) { +$wingetModules = Get-Module -ListAvailable -Name Microsoft.WinGet.Client +if ($wingetModules) { + + $moduleUpToDate = $false; + foreach ($mod in $wingetModules) { + if ($mod.Version -ge "1.8.1133") { + $moduleUpToDate = $true; + break; + } + } + + if ($moduleUpToDate) { Write-Host "WinGet Client module detected" + } else { + Write-Host "WinGet module needs to be updated. Run `"Update-Module -Name Microsoft.WinGet.Client`" to update `r`n" + } } else { Write-Host "WinGet module was not found. Installation instructions can be found on https://www.powershellgallery.com/packages/Microsoft.WinGet.Client `r`n" } +$CNFModule = Get-Module -ListAvailable -Name Microsoft.WinGet.CommandNotFound +if ($CNFModule) { + Write-Host "Microsoft.WinGet.CommandNotFound module detected" +} else { + Write-Host "Microsoft.WinGet.CommandNotFound was not found. Installing...`r`n" + Install-Module -Name Microsoft.WinGet.CommandNotFound -Force + Write-Host "Microsoft.WinGet.CommandNotFound module installed`r`n" +} + if (!(Test-Path $PROFILE)) { Write-Host "Profile file $PROFILE not found". @@ -26,15 +49,28 @@ if (!(Test-Path $PROFILE)) $profileContent = Get-Content -Path $PROFILE -Raw if ((-not [string]::IsNullOrEmpty($profileContent)) -and ($profileContent.Contains("34de4b3d-13a8-4540-b76d-b9e8d3851756"))) +{ + if ($profileContent.Contains("Import-Module `"$scriptPath\WinGetCommandNotFound.psd1`"")) + { + $profileContent = $profileContent.Replace("Import-Module `"$scriptPath\WinGetCommandNotFound.psd1`"", + "Import-Module -Name Microsoft.WinGet.CommandNotFound") + $profileContent = $profileContent.Replace("34de4b3d-13a8-4540-b76d-b9e8d3851756", + "f45873b3-b655-43a6-b217-97c00aa0db58") + Set-Content -Path $PROFILE -Value $profileContent + Write-Host "Module was successfully upgraded in the profile file." + # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. + } +} +elseif ((-not [string]::IsNullOrEmpty($profileContent)) -and ($profileContent.Contains("f45873b3-b655-43a6-b217-97c00aa0db58"))) { Write-Host "Module is already registered in the profile file." # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. } else { - Add-Content -Path $PROFILE -Value "`r`n#34de4b3d-13a8-4540-b76d-b9e8d3851756 PowerToys CommandNotFound module" - Add-Content -Path $PROFILE -Value "`r`nImport-Module `"$scriptPath\WinGetCommandNotFound.psd1`"" - Add-Content -Path $PROFILE -Value "#34de4b3d-13a8-4540-b76d-b9e8d3851756" + Add-Content -Path $PROFILE -Value "`r`n#f45873b3-b655-43a6-b217-97c00aa0db58 PowerToys CommandNotFound module" + Add-Content -Path $PROFILE -Value "`r`nImport-Module -Name Microsoft.WinGet.CommandNotFound" + Add-Content -Path $PROFILE -Value "#f45873b3-b655-43a6-b217-97c00aa0db58" Write-Host "Module was successfully registered in the profile file." # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. } diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/InstallWinGetClientModule.ps1 b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/InstallWinGetClientModule.ps1 index ed48ac84e40..1f54c620849 100644 --- a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/InstallWinGetClientModule.ps1 +++ b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/InstallWinGetClientModule.ps1 @@ -1,7 +1,46 @@ -if (Get-Module -ListAvailable -Name Microsoft.WinGet.Client) +$wingetModules = Get-Module -ListAvailable -Name Microsoft.WinGet.Client +if ($wingetModules) { - Write-Host "WinGet Client module detected." - # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. + $needsUpdate = $true; + foreach ($mod in $wingetModules) + { + if ($mod.Version -ge "1.8.1133") + { + $needsUpdate = $false; + break; + } + } + + if ($needsUpdate) + { + Update-Module -Name Microsoft.WinGet.Client -Force + $wingetModules = Get-Module -ListAvailable -Name Microsoft.WinGet.Client + $updated = $false; + foreach ($mod in $wingetModules) + { + if ($mod.Version -ge "1.8.1133") + { + $updated = $true; + break; + } + } + + if ($updated) + { + Write-Host "WinGet Client module updated." + # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. + } + else + { + Write-Host "WinGet Client module detected." + # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. + } + } + else + { + Write-Host "WinGet Client module detected." + # This message will be compared against in Command Not Found Settings page code behind. Take care when changing it. + } } else { Install-Module -Name Microsoft.WinGet.Client diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/UpgradeModule.ps1 b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/UpgradeModule.ps1 new file mode 100644 index 00000000000..5bb66b55cb4 --- /dev/null +++ b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/UpgradeModule.ps1 @@ -0,0 +1,29 @@ +if (!(Test-Path $PROFILE)) +{ + return; +} + +$profileContent = Get-Content -Path $PROFILE -Raw +$legacyGuid = "34de4b3d-13a8-4540-b76d-b9e8d3851756" +if ((-not [string]::IsNullOrEmpty($profileContent)) -and ($profileContent.Contains($legacyGuid))) +{ + # Upgrade Microsoft.WinGet.Client module + $wingetModule = Get-Module -ListAvailable -Name Microsoft.WinGet.Client + if ($wingetModule -and $wingetModule.Version -lt "1.8.1133") { + Update-Module -Name Microsoft.WinGet.Client + } + + # Install Microsoft.WinGet.CommandNotFound module + if (-Not (Get-Module -ListAvailable -Name Microsoft.WinGet.CommandNotFound)) { + Install-Module -Name Microsoft.WinGet.CommandNotFound -Force + } + + # Replace old module with new one (and new GUID comment) + $regex = "Import-Module .*WinGetCommandNotFound.psd1`"" + if ($profileContent -match $regex) + { + $profileContent = $profileContent -replace $regex, "Import-Module -Name Microsoft.WinGet.CommandNotFound" + $profileContent = $profileContent -replace $legacyGuid, "f45873b3-b655-43a6-b217-97c00aa0db58" + Set-Content -Path $PROFILE -Value $profileContent + } +} \ No newline at end of file diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml index 049cfbb0ffc..649d3062261 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml @@ -17,10 +17,7 @@ TrueValue="Collapsed" /> - + + IsOpen="True"> @@ -74,16 +71,10 @@ - - + @@ -113,7 +104,7 @@ - + diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index 846af5dc0df..4ca8fc087e7 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -4046,9 +4046,6 @@ Activate by holding the key for the character you want to add an accent to, then Show the release notes after an update - - Command Not Found is not supported on the ARM64 architecture currently. We are actively working on a solution. - Do not activate when Game Mode is on "Game mode" is the Windows feature to prevent notification when playing a game. diff --git a/src/settings-ui/Settings.UI/ViewModels/CmdNotFoundViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/CmdNotFoundViewModel.cs index a861e1e7ad0..c5b8684eddf 100644 --- a/src/settings-ui/Settings.UI/ViewModels/CmdNotFoundViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/CmdNotFoundViewModel.cs @@ -129,11 +129,6 @@ public bool IsEnabledGpoConfigured get => _enabledStateIsGPOConfigured; } - public bool IsArm64Arch - { - get => RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.Arm64; - } - public string RunPowerShellOrPreviewScript(string powershellExecutable, string powershellArguments, bool hidePowerShellWindow = false) { if (isPowerShellPreviewDetected) @@ -228,7 +223,7 @@ public void CheckCommandNotFoundRequirements() { IsWinGetClientModuleDetected = true; } - else if (result.Contains("WinGet Client module not detected.")) + else if (result.Contains("WinGet Client module not detected.") || result.Contains("WinGet Client module needs to be updated.")) { IsWinGetClientModuleDetected = false; } @@ -237,7 +232,7 @@ public void CheckCommandNotFoundRequirements() { IsCommandNotFoundModuleInstalled = true; } - else if (result.Contains("Command Not Found module is not registered in the profile file.")) + else if (result.Contains("Command Not Found module is not registered in the profile file.") || result.Contains("Outdated version of Command Not Found module found in the profile file.")) { IsCommandNotFoundModuleInstalled = false; } @@ -266,7 +261,7 @@ public void InstallWinGetClientModule() var ps1File = AssemblyDirectory + "\\Assets\\Settings\\Scripts\\InstallWinGetClientModule.ps1"; var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\""; var result = RunPowerShellOrPreviewScript("pwsh.exe", arguments); - if (result.Contains("WinGet Client module detected.")) + if (result.Contains("WinGet Client module detected.") || result.Contains("WinGet Client module updated.")) { IsWinGetClientModuleDetected = true; } @@ -284,7 +279,9 @@ public void InstallModule() var arguments = $"-NoProfile -ExecutionPolicy Unrestricted -File \"{ps1File}\" -scriptPath \"{AssemblyDirectory}\\..\""; var result = RunPowerShellOrPreviewScript("pwsh.exe", arguments); - if (result.Contains("Module is already registered in the profile file.") || result.Contains("Module was successfully registered in the profile file.")) + if (result.Contains("Module is already registered in the profile file.") + || result.Contains("Module was successfully registered in the profile file.") + || result.Contains("Module was successfully upgraded in the profile file.")) { IsCommandNotFoundModuleInstalled = true; PowerToysTelemetry.Log.WriteEvent(new CmdNotFoundInstallEvent());