From 56eec929ca75bee95c33ae8c93bf7ab4d73d9398 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 6 Jan 2025 23:41:44 +0000 Subject: [PATCH] Register application capability with file extensions https://learn.microsoft.com/en-us/windows/win32/shell/default-programs#registering-an-application-for-use-with-default-programs --- .../Windows/WindowsAssociationManager.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 0561c488d8..b2ae39d837 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -17,6 +17,7 @@ namespace osu.Desktop.Windows public static class WindowsAssociationManager { private const string software_classes = @"Software\Classes"; + private const string software_registered_applications = @"Software\RegisteredApplications"; /// /// Sub key for setting the icon. @@ -38,6 +39,8 @@ namespace osu.Desktop.Windows /// private const string program_id_prefix = "osu.File"; + private static readonly ApplicationCapability application_capability = new ApplicationCapability(@"osu", @"Software\ppy\osu\Capabilities", "osu!(lazer)"); + private static readonly FileAssociation[] file_associations = { new FileAssociation(@".osz", WindowsAssociationManagerStrings.OsuBeatmap, Icons.Beatmap), @@ -112,6 +115,8 @@ namespace osu.Desktop.Windows { try { + application_capability.Uninstall(); + foreach (var association in file_associations) association.Uninstall(); @@ -133,15 +138,21 @@ namespace osu.Desktop.Windows /// private static void updateAssociations() { + application_capability.Install(); + foreach (var association in file_associations) association.Install(); foreach (var association in uri_associations) association.Install(); + + application_capability.RegisterFileAssociations(file_associations); } private static void updateDescriptions(LocalisationManager? localisation) { + application_capability.UpdateDescription(getLocalisedString(application_capability.Description)); + foreach (var association in file_associations) association.UpdateDescription(getLocalisedString(association.Description)); @@ -174,6 +185,51 @@ namespace osu.Desktop.Windows #endregion + private record ApplicationCapability(string UniqueName, string CapabilityPath, LocalisableString Description) + { + /// + /// Registers an application capability according to + /// Registering an Application for Use with Default Programs. + /// + public void Install() + { + using (Registry.CurrentUser.CreateSubKey(CapabilityPath)) + { + // create an empty "capability" key, other methods will fill it with information + } + + using (var registeredApplications = Registry.CurrentUser.OpenSubKey(software_registered_applications, true)) + registeredApplications?.SetValue(UniqueName, CapabilityPath); + } + + public void RegisterFileAssociations(FileAssociation[] associations) + { + using var capability = Registry.CurrentUser.OpenSubKey(CapabilityPath, true); + if (capability == null) return; + + using var fileAssociations = capability.CreateSubKey(@"FileAssociations"); + + foreach (var association in associations) + fileAssociations.SetValue(association.Extension, association.ProgramId); + } + + public void UpdateDescription(string description) + { + using (var capability = Registry.CurrentUser.OpenSubKey(CapabilityPath, true)) + { + capability?.SetValue(@"ApplicationDescription", description); + } + } + + public void Uninstall() + { + using (var registeredApplications = Registry.CurrentUser.OpenSubKey(software_registered_applications, true)) + registeredApplications?.DeleteValue(UniqueName, throwOnMissingValue: false); + + Registry.CurrentUser.DeleteSubKeyTree(CapabilityPath, throwOnMissingSubKey: false); + } + } + private record FileAssociation(string Extension, LocalisableString Description, string IconPath) { public string ProgramId => $@"{program_id_prefix}{Extension}";