Files
archived-WinDurango.UI/Utils/Packages.cs
Dexrn ZacAttack 1883d0edea simple mod manager
2025-02-24 00:43:55 -08:00

245 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Xml.Linq;
using Windows.ApplicationModel;
using Windows.Management.Deployment;
using WinDurango.UI.Dialogs;
using WinUI3Localizer;
using static WinDurango.UI.Localization.Locale;
namespace WinDurango.UI.Utils
{
// do not touch or you will combust from all the glue holding this together
// this class sucks so much that we literally had to stop bc we didn't know how to rewrite a function and make it still work with the UI stuff
// update: this was fixed same commit.
#nullable enable
public class ManifestInfo
{
public string? DisplayName { get; set; }
public string? PublisherDisplayName { get; set; }
public string? Logo { get; set; }
public string? Description { get; set; }
}
public abstract class Packages
{
// TODO: Make these methods not use the GUI, instead just throw an exception and catch it in the area where the method is actually invoked.
public static IEnumerable<Package> GetInstalledPackages()
{
var sid = WindowsIdentity.GetCurrent().User?.Value;
var pm = new PackageManager();
return pm.FindPackagesForUser(sid);
}
public static ManifestInfo GetPropertiesFromManifest(string manifestPath)
{
ManifestInfo manifestInfo = new();
if (!File.Exists(manifestPath))
return manifestInfo;
string manifest;
using (var stream = File.OpenRead(manifestPath))
{
var reader = new StreamReader(stream);
manifest = reader.ReadToEnd();
}
XDocument doc = XDocument.Parse(manifest);
XElement? package = doc.Descendants().FirstOrDefault(e => e.Name.LocalName == "Package");
XElement? properties = package?.Descendants().FirstOrDefault(e => e.Name.LocalName == "Properties");
manifestInfo.Logo = properties?.Descendants().FirstOrDefault(e => e.Name.LocalName == "Logo")?.Value;
manifestInfo.DisplayName = properties?.Descendants().FirstOrDefault(e => e.Name.LocalName == "DisplayName")?.Value;
manifestInfo.PublisherDisplayName = properties?.Descendants().FirstOrDefault(e => e.Name.LocalName == "PublisherDisplayName")?.Value;
manifestInfo.Description = properties?.Descendants().FirstOrDefault(e => e.Name.LocalName == "Description")?.Value;
return manifestInfo;
}
public static async Task InstallXPackageAsync(string dir, ProgressController controller, bool addInstalledPackage = true)
{
string mountDir = Path.Combine(dir, "Mount");
if (!Directory.Exists(mountDir))
{
await new NoticeDialog(GetLocalizedText($"Error.mountNotFound", mountDir), "Error").Show();
return;
}
await InstallPackageAsync(new Uri(mountDir + "\\AppxManifest.xml", UriKind.Absolute), controller, addInstalledPackage);
}
public static string GetSplashScreenPath(Package pkg)
{
try
{
string installPath = pkg.InstalledPath;
string manifestPath = Path.Combine(installPath, "AppxManifest.xml");
if (!File.Exists(manifestPath))
return null;
string manifest;
using (var stream = File.OpenRead(manifestPath))
{
var reader = new StreamReader(stream);
manifest = reader.ReadToEnd();
}
XDocument doc = XDocument.Parse(manifest);
XElement package = doc.Descendants().FirstOrDefault(e => e.Name.LocalName == "Package");
if (package == null) return null;
XElement applications = package.Descendants().FirstOrDefault(e => e.Name.LocalName == "Applications");
if (applications == null) return null;
XElement application = applications.Descendants().FirstOrDefault(e => e.Name.LocalName == "Application");
if (application == null) return null;
XElement visualElements = application.Descendants().FirstOrDefault(e => e.Name.LocalName == "VisualElements");
if (visualElements == null) return null;
XElement splashScreen = visualElements.Descendants().FirstOrDefault(e => e.Name.LocalName == "SplashScreen");
if (splashScreen == null) return null;
string imagePath = splashScreen.Attribute("Image")?.Value;
if (imagePath == null) return null;
string splashScreenPath = Path.Combine(installPath, imagePath);
return splashScreenPath;
}
catch
{
return null;
}
}
public static async Task<string> InstallPackageAsync(Uri appxManifestUri, ProgressController controller, bool addInstalledPackage = true)
{
string manifestPath = Uri.UnescapeDataString(appxManifestUri.AbsolutePath);
if (!File.Exists(manifestPath))
{
throw new Exception(GetLocalizedText("Error.NotFound", manifestPath));
}
Logger.WriteInformation($"Installing package \"{manifestPath}\"...");
PackageManager pm = new();
try
{
Logger.WriteInformation($"Reading manifest...");
controller?.UpdateText("Packages.ReadingManifest".GetLocalizedString());
string manifest;
await using (var stream = File.OpenRead(manifestPath))
{
StreamReader reader = new StreamReader(stream);
manifest = await reader.ReadToEndAsync();
}
XDocument doc = XDocument.Parse(manifest);
XElement? package = doc.Descendants().FirstOrDefault(e => e.Name.LocalName == "Package");
XElement? identity = package?.Descendants().FirstOrDefault(e => e.Name.LocalName == "Identity");
string? pkgName = identity?.Attribute("Name")?.Value;
string? pkgPublisher = identity?.Attribute("Publisher")?.Value;
controller?.UpdateProgress(20.0);
controller?.UpdateText(GetLocalizedText("CheckingInstallStatus", pkgName));
string? sid = WindowsIdentity.GetCurrent().User?.Value;
IEnumerable<Package>? installedPackages = await Task.Run(() => pm.FindPackagesForUser(sid, pkgName, pkgPublisher));
if (installedPackages.Any())
{
Logger.WriteError($"{pkgName} is already installed.");
throw new Exception(GetLocalizedText("Error.AlreadyInstalled", pkgName));
}
controller?.UpdateProgress(40.0);
controller?.UpdateText(GetLocalizedText("Packages.InstallingPackage", pkgName));
Logger.WriteInformation($"Registering...");
await pm.RegisterPackageAsync(appxManifestUri, null, DeploymentOptions.DevelopmentMode);
controller?.UpdateProgress(60.0);
controller?.UpdateText("Packages.GettingAppInfo".GetLocalizedString());
Package recentPkg = GetMostRecentlyInstalledPackage();
if (addInstalledPackage)
{
controller?.UpdateText($"Ui.UpdatingAppList".GetLocalizedString());
controller?.UpdateProgress(80.0);
App.InstalledPackages.AddPackage(recentPkg);
controller?.UpdateProgress(90.0);
App.MainWindow.ReloadAppList();
controller?.UpdateProgress(100.0);
}
else
{
controller?.UpdateProgress(100.0);
}
Logger.WriteInformation($"{recentPkg.Id.Name} was installed.");
return recentPkg.Id.FamilyName;
}
catch (Exception e)
{
// we're fucked :(
Logger.WriteError($"{appxManifestUri} failed to install");
Logger.WriteException(e);
throw new Exception(
GetLocalizedText("Packages.Error.PackageInstallFailedEx", appxManifestUri, e.Message), e);
}
}
public static async Task RemovePackage(Package package, ProgressController controller)
{
Logger.WriteError($"Uninstalling {package.DisplayName}...");
PackageManager pm = new();
try
{
var undeployment = await pm.RemovePackageAsync(package.Id.FullName, RemovalOptions.PreserveApplicationData);
controller.UpdateProgress(50.0);
App.InstalledPackages.RemovePackage(package);
controller.UpdateProgress(100.0);
App.MainWindow.ReloadAppList();
}
catch (Exception ex)
{
Logger.WriteError($"{package.DisplayName} failed to uninstall");
Logger.WriteException(ex);
throw new Exception(GetLocalizedText("Packages.Error.PackageUninstallFailedEx", package.DisplayName, ex.Message), ex);
}
}
public static Package GetPackageByFamilyName(string familyName)
{
var packageManager = new PackageManager();
var packages = packageManager.FindPackagesForUser(null, familyName);
return packages == null || !packages.Any() ? null : packages.First();
}
public static Package GetMostRecentlyInstalledPackage()
{
var sid = WindowsIdentity.GetCurrent().User?.Value;
var pm = new PackageManager();
var packages = pm.FindPackagesForUser(sid);
if (!packages.Any())
return null;
var newestPackage = packages.Last();
return newestPackage;
}
}
}