/ src / modules / launcher / Plugins / Microsoft.Plugin.Program / Storage / PackageRepository.cs
PackageRepository.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using System;
  6  using System.Linq;
  7  
  8  using Microsoft.Plugin.Program.Logger;
  9  using Microsoft.Plugin.Program.Programs;
 10  using Windows.ApplicationModel;
 11  using Wox.Infrastructure.Storage;
 12  using Wox.Plugin;
 13  using Wox.Plugin.Logger;
 14  
 15  namespace Microsoft.Plugin.Program.Storage
 16  {
 17      /// <summary>
 18      /// A repository for storing packaged applications such as UWP apps or appx packaged desktop apps.
 19      /// This repository will also monitor for changes to the PackageCatalog and update the repository accordingly
 20      /// </summary>
 21      internal class PackageRepository : ListRepository<UWPApplication>, IProgramRepository
 22      {
 23          private readonly IPackageCatalog _packageCatalog;
 24          private readonly PluginInitContext _context;
 25  
 26          public PackageRepository(IPackageCatalog packageCatalog, PluginInitContext context)
 27          {
 28              _packageCatalog = packageCatalog ?? throw new ArgumentNullException(nameof(packageCatalog), "PackageRepository expects an interface to be able to subscribe to package events");
 29              _context = context ?? throw new ArgumentNullException(nameof(context));
 30  
 31              _packageCatalog.PackageInstalling += OnPackageInstalling;
 32              _packageCatalog.PackageUninstalling += OnPackageUninstalling;
 33              _packageCatalog.PackageUpdating += OnPackageUpdating;
 34          }
 35  
 36          public void OnPackageInstalling(PackageCatalog p, PackageInstallingEventArgs args)
 37          {
 38              if (args.IsComplete)
 39              {
 40                  AddPackage(args.Package);
 41              }
 42          }
 43  
 44          public void OnPackageUninstalling(PackageCatalog p, PackageUninstallingEventArgs args)
 45          {
 46              if (args.Progress == 0)
 47              {
 48                  RemovePackage(args.Package);
 49              }
 50          }
 51  
 52          public void OnPackageUpdating(PackageCatalog p, PackageUpdatingEventArgs args)
 53          {
 54              if (args.Progress == 0)
 55              {
 56                  RemovePackage(args.SourcePackage);
 57              }
 58  
 59              if (args.IsComplete)
 60              {
 61                  AddPackage(args.TargetPackage);
 62              }
 63          }
 64  
 65          private void AddPackage(Package package)
 66          {
 67              var packageWrapper = PackageWrapper.GetWrapperFromPackage(package);
 68              if (string.IsNullOrEmpty(packageWrapper.InstalledLocation))
 69              {
 70                  return;
 71              }
 72  
 73              try
 74              {
 75                  var uwp = new UWP(packageWrapper);
 76                  uwp.InitializeAppInfo(packageWrapper.InstalledLocation);
 77                  foreach (var app in uwp.Apps)
 78                  {
 79                      app.UpdateLogoPath(_context.API.GetCurrentTheme());
 80                      Add(app);
 81                  }
 82              }
 83  
 84              // InitializeAppInfo will throw if there is no AppxManifest.xml for the package.
 85              // Note there are sometimes multiple packages per product and this doesn't necessarily mean that we haven't found the app.
 86              // e.g. "Could not find file 'C:\\Program Files\\WindowsApps\\Microsoft.WindowsTerminalPreview_2020.616.45.0_neutral_~_8wekyb3d8bbwe\\AppxManifest.xml'."
 87              catch (System.IO.FileNotFoundException e)
 88              {
 89                  ProgramLogger.Exception(e.Message, e, GetType(), package.InstalledLocation.ToString());
 90              }
 91          }
 92  
 93          private void RemovePackage(Package package)
 94          {
 95              // find apps associated with this package.
 96              var packageWrapper = PackageWrapper.GetWrapperFromPackage(package);
 97              var uwp = new UWP(packageWrapper);
 98              var apps = Items.Where(a => a.Package.Equals(uwp)).ToArray();
 99  
100              foreach (var app in apps)
101              {
102                  Remove(app);
103              }
104          }
105  
106          public void IndexPrograms()
107          {
108              var windows10 = new Version(10, 0);
109              var support = Environment.OSVersion.Version.Major >= windows10.Major;
110  
111              var applications = support ? Programs.UWP.All() : Array.Empty<UWPApplication>();
112              Log.Info($"Indexed {applications.Length} packaged applications", GetType());
113              SetList(applications);
114          }
115      }
116  }