mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 11:46:30 +02:00
CmdPal: Linq clean-up (All Apps) (#41551)
Beginning the process of removing System.Linq from CmdPal. This PR removes it from the All Apps extension.
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using Windows.Management.Deployment;
|
||||
|
||||
@@ -26,9 +25,19 @@ public class PackageManagerWrapper : IPackageManager
|
||||
{
|
||||
var pkgs = _packageManager.FindPackagesForUser(user.Value);
|
||||
|
||||
return pkgs.Select(PackageWrapper.GetWrapperFromPackage).Where(package => package is not null);
|
||||
ICollection<IPackage> packages = [];
|
||||
|
||||
foreach (var package in pkgs)
|
||||
{
|
||||
if (package is not null)
|
||||
{
|
||||
packages.Add(PackageWrapper.GetWrapperFromPackage(package));
|
||||
}
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
return Enumerable.Empty<IPackage>();
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using ManagedCommon;
|
||||
@@ -72,18 +71,20 @@ public partial class UWP
|
||||
PInvoke.SHCreateStreamOnFileEx(path, STGMREAD, noAttribute, false, null, &stream).ThrowOnFailure();
|
||||
using var streamHandle = new SafeComHandle((IntPtr)stream);
|
||||
|
||||
Apps = AppxPackageHelper.GetAppsFromManifest(stream).Select(appInManifest =>
|
||||
var appsInManifest = AppxPackageHelper.GetAppsFromManifest(stream);
|
||||
|
||||
foreach (var appInManifest in appsInManifest)
|
||||
{
|
||||
using var appHandle = new SafeComHandle(appInManifest);
|
||||
return new UWPApplication((IAppxManifestApplication*)appInManifest, this);
|
||||
}).Where(a =>
|
||||
{
|
||||
var valid =
|
||||
!string.IsNullOrEmpty(a.UserModelId) &&
|
||||
!string.IsNullOrEmpty(a.DisplayName) &&
|
||||
a.AppListEntry != "none";
|
||||
return valid;
|
||||
}).ToList();
|
||||
var uwpApp = new UWPApplication((IAppxManifestApplication*)appInManifest, this);
|
||||
|
||||
if (!string.IsNullOrEmpty(uwpApp.UserModelId) &&
|
||||
!string.IsNullOrEmpty(uwpApp.DisplayName) &&
|
||||
uwpApp.AppListEntry != "none")
|
||||
{
|
||||
Apps.Add(uwpApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -93,19 +94,31 @@ public partial class UWP
|
||||
}
|
||||
}
|
||||
|
||||
// http://www.hanselman.com/blog/GetNamespacesFromAnXMLDocumentWithXPathDocumentAndLINQToXML.aspx
|
||||
private static string[] XmlNamespaces(string path)
|
||||
{
|
||||
var z = XDocument.Load(path);
|
||||
if (z.Root is not null)
|
||||
{
|
||||
var namespaces = z.Root.Attributes().
|
||||
Where(a => a.IsNamespaceDeclaration).
|
||||
GroupBy(
|
||||
a => a.Name.Namespace == XNamespace.None ? string.Empty : a.Name.LocalName,
|
||||
a => XNamespace.Get(a.Value)).Select(
|
||||
g => g.First().ToString()).ToArray();
|
||||
return namespaces;
|
||||
var namespaces = new HashSet<string>();
|
||||
|
||||
var attributes = z.Root.Attributes();
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
if (attribute.IsNamespaceDeclaration)
|
||||
{
|
||||
// Extract namespace
|
||||
var key = attribute.Name.Namespace == XNamespace.None ? string.Empty : attribute.Name.LocalName;
|
||||
XNamespace ns = XNamespace.Get(attribute.Value);
|
||||
var nsString = ns.ToString();
|
||||
|
||||
// Use HashSet to check for duplicates
|
||||
namespaces.Add(nsString);
|
||||
}
|
||||
}
|
||||
|
||||
var uniqueNamespaces = new string[namespaces.Count];
|
||||
namespaces.CopyTo(uniqueNamespaces);
|
||||
return uniqueNamespaces;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -115,10 +128,13 @@ public partial class UWP
|
||||
|
||||
private void InitPackageVersion(string[] namespaces)
|
||||
{
|
||||
foreach (var n in _versionFromNamespace.Keys.Where(namespaces.Contains))
|
||||
foreach (var n in _versionFromNamespace.Keys)
|
||||
{
|
||||
Version = _versionFromNamespace[n];
|
||||
return;
|
||||
if (Array.IndexOf(namespaces, n) >= 0)
|
||||
{
|
||||
Version = _versionFromNamespace[n];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Version = PackageVersion.Unknown;
|
||||
@@ -137,7 +153,18 @@ public partial class UWP
|
||||
|
||||
foreach (var app in u.Apps)
|
||||
{
|
||||
if (AllAppsSettings.Instance.DisabledProgramSources.All(x => x.UniqueIdentifier != app.UniqueIdentifier))
|
||||
var isDisabled = false;
|
||||
|
||||
foreach (var disabled in AllAppsSettings.Instance.DisabledProgramSources)
|
||||
{
|
||||
if (disabled.UniqueIdentifier == app.UniqueIdentifier)
|
||||
{
|
||||
isDisabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDisabled)
|
||||
{
|
||||
appsBag.Add(app);
|
||||
}
|
||||
@@ -154,20 +181,28 @@ public partial class UWP
|
||||
|
||||
private static IEnumerable<IPackage> CurrentUserPackages()
|
||||
{
|
||||
return PackageManagerWrapper.FindPackagesForCurrentUser().Where(p =>
|
||||
var currentUsersPackages = PackageManagerWrapper.FindPackagesForCurrentUser();
|
||||
ICollection<IPackage> packagesToReturn = [];
|
||||
|
||||
foreach (var pkg in currentUsersPackages)
|
||||
{
|
||||
try
|
||||
{
|
||||
var f = p.IsFramework;
|
||||
var path = p.InstalledLocation;
|
||||
return !f && !string.IsNullOrEmpty(path);
|
||||
var f = pkg.IsFramework;
|
||||
var path = pkg.InstalledLocation;
|
||||
|
||||
if (!f && !string.IsNullOrEmpty(path))
|
||||
{
|
||||
packagesToReturn.Add(pkg);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return packagesToReturn;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
@@ -348,20 +347,22 @@ public class UWPApplication : IUWPApplication
|
||||
//
|
||||
// FirstOrDefault would result in us using the 1x scaled icon
|
||||
// always, which is usually too small for our needs.
|
||||
var selectedIconPath = paths.LastOrDefault(File.Exists);
|
||||
if (!string.IsNullOrEmpty(selectedIconPath))
|
||||
for (var i = paths.Count - 1; i >= 0; i--)
|
||||
{
|
||||
LogoPath = selectedIconPath;
|
||||
if (highContrast)
|
||||
if (File.Exists(paths[i]))
|
||||
{
|
||||
LogoType = LogoType.HighContrast;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogoType = LogoType.Colored;
|
||||
}
|
||||
LogoPath = paths[i];
|
||||
if (highContrast)
|
||||
{
|
||||
LogoType = LogoType.HighContrast;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogoType = LogoType.Colored;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +403,23 @@ public class UWPApplication : IUWPApplication
|
||||
}
|
||||
}
|
||||
|
||||
var selectedIconPath = paths.OrderBy(x => Math.Abs(pathFactorPairs.GetValueOrDefault(x) - appIconSize)).FirstOrDefault(File.Exists);
|
||||
// Sort paths by distance to desired app icon size
|
||||
var selectedIconPath = string.Empty;
|
||||
var closestDistance = int.MaxValue;
|
||||
|
||||
foreach (var p in paths)
|
||||
{
|
||||
if (File.Exists(p) && pathFactorPairs.TryGetValue(p, out var factor))
|
||||
{
|
||||
var distance = Math.Abs(factor - appIconSize);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
selectedIconPath = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(selectedIconPath))
|
||||
{
|
||||
LogoPath = selectedIconPath;
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
@@ -616,9 +615,24 @@ public class Win32Program : IProgram
|
||||
}
|
||||
|
||||
private static IEnumerable<string> CustomProgramPaths(IEnumerable<ProgramSource> sources, IList<string> suffixes)
|
||||
=> sources?.Where(programSource => Directory.Exists(programSource.Location) && programSource.Enabled)
|
||||
.SelectMany(programSource => ProgramPaths(programSource.Location, suffixes))
|
||||
.ToList() ?? Enumerable.Empty<string>();
|
||||
{
|
||||
if (sources is not null)
|
||||
{
|
||||
var paths = new List<string>();
|
||||
|
||||
foreach (var programSource in sources)
|
||||
{
|
||||
if (Directory.Exists(programSource.Location) && programSource.Enabled)
|
||||
{
|
||||
paths.AddRange(ProgramPaths(programSource.Location, suffixes));
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// Function to obtain the list of applications, the locations of which have been added to the env variable PATH
|
||||
private static List<string> PathEnvironmentProgramPaths(IList<string> suffixes)
|
||||
@@ -647,9 +661,15 @@ public class Win32Program : IProgram
|
||||
}
|
||||
|
||||
private static List<string> IndexPath(IList<string> suffixes, List<string> indexLocations)
|
||||
=> indexLocations
|
||||
.SelectMany(indexLocation => ProgramPaths(indexLocation, suffixes))
|
||||
.ToList();
|
||||
{
|
||||
var paths = new List<string>();
|
||||
foreach (var indexLocation in indexLocations)
|
||||
{
|
||||
paths.AddRange(ProgramPaths(indexLocation, suffixes));
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
private static List<string> StartMenuProgramPaths(IList<string> suffixes)
|
||||
{
|
||||
@@ -691,17 +711,51 @@ public class Win32Program : IProgram
|
||||
}
|
||||
}
|
||||
|
||||
return paths
|
||||
.Where(path => suffixes.Any(suffix => path.EndsWith(suffix, StringComparison.InvariantCultureIgnoreCase)))
|
||||
.Select(ExpandEnvironmentVariables)
|
||||
.Where(path => path is not null)
|
||||
.ToList();
|
||||
var returnedPaths = new List<string>();
|
||||
foreach (var path in paths)
|
||||
{
|
||||
var matchesSuffix = false;
|
||||
foreach (var suffix in suffixes)
|
||||
{
|
||||
if (path.EndsWith(suffix, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
matchesSuffix = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchesSuffix)
|
||||
{
|
||||
var expandedPath = ExpandEnvironmentVariables(path);
|
||||
if (expandedPath is not null)
|
||||
{
|
||||
returnedPaths.Add(expandedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnedPaths;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetPathsFromRegistry(RegistryKey root)
|
||||
=> root
|
||||
.GetSubKeyNames()
|
||||
.Select(x => GetPathFromRegistrySubkey(root, x));
|
||||
{
|
||||
var result = new List<string>();
|
||||
|
||||
// Get all subkey names
|
||||
var subKeyNames = root.GetSubKeyNames();
|
||||
|
||||
// Process each subkey to extract the path
|
||||
foreach (var subkeyName in subKeyNames)
|
||||
{
|
||||
var path = GetPathFromRegistrySubkey(root, subkeyName);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
result.Add(path);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetPathFromRegistrySubkey(RegistryKey root, string subkey)
|
||||
{
|
||||
@@ -765,7 +819,28 @@ public class Win32Program : IProgram
|
||||
}
|
||||
|
||||
public static List<Win32Program> DeduplicatePrograms(IEnumerable<Win32Program> programs)
|
||||
=> new HashSet<Win32Program>(programs, Win32ProgramEqualityComparer.Default).ToList();
|
||||
{
|
||||
// Create a HashSet with the custom equality comparer to automatically deduplicate programs
|
||||
var uniquePrograms = new HashSet<Win32Program>(Win32ProgramEqualityComparer.Default);
|
||||
|
||||
// Filter out invalid programs and add valid ones to the HashSet
|
||||
foreach (var program in programs)
|
||||
{
|
||||
if (program?.Valid == true)
|
||||
{
|
||||
uniquePrograms.Add(program);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the HashSet to a List for return
|
||||
var result = new List<Win32Program>(uniquePrograms.Count);
|
||||
foreach (var program in uniquePrograms)
|
||||
{
|
||||
result.Add(program);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Win32Program GetProgramFromPath(string path)
|
||||
{
|
||||
@@ -881,8 +956,22 @@ public class Win32Program : IProgram
|
||||
|
||||
foreach (var path in source.GetPaths())
|
||||
{
|
||||
if (disabledProgramsList.All(x => x.UniqueIdentifier != path) &&
|
||||
!ExecutableApplicationExtensions.Contains(Extension(path)))
|
||||
if (ExecutableApplicationExtensions.Contains(Extension(path)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var isDisabled = false;
|
||||
foreach (var disabledProgram in disabledProgramsList)
|
||||
{
|
||||
if (disabledProgram.UniqueIdentifier == path)
|
||||
{
|
||||
isDisabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDisabled)
|
||||
{
|
||||
pathBag.Add(path);
|
||||
}
|
||||
@@ -902,7 +991,17 @@ public class Win32Program : IProgram
|
||||
|
||||
foreach (var path in source.GetPaths())
|
||||
{
|
||||
if (disabledProgramsList.All(x => x.UniqueIdentifier != path))
|
||||
var isDisabled = false;
|
||||
foreach (var disabledProgram in disabledProgramsList)
|
||||
{
|
||||
if (disabledProgram.UniqueIdentifier == path)
|
||||
{
|
||||
isDisabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDisabled)
|
||||
{
|
||||
runCommandPathBag.Add(path);
|
||||
}
|
||||
@@ -931,10 +1030,8 @@ public class Win32Program : IProgram
|
||||
}
|
||||
});
|
||||
|
||||
var programs = programsList.ToList();
|
||||
var runCommandPrograms = runCommandProgramsList.ToList();
|
||||
|
||||
return DeduplicatePrograms(programs.Concat(runCommandPrograms).Where(program => program?.Valid == true));
|
||||
List<Win32Program> allPrograms = [.. programsList, .. runCommandProgramsList];
|
||||
return DeduplicatePrograms(allPrograms);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user