mirror of
https://github.com/WinDurango/WinDurango.UI.git
synced 2026-01-31 00:55:24 +01:00
245 lines
10 KiB
C#
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;
|
|
}
|
|
|
|
}
|
|
} |