mirror of
https://github.com/ppy/osu.git
synced 2025-01-18 11:02:57 +08:00
Merge pull request #31450 from peppy/association-manager-cleanup
This commit is contained in:
commit
2e10f83b5c
@ -56,14 +56,13 @@ namespace osu.Desktop.Windows
|
|||||||
/// Installs file and URI associations.
|
/// Installs file and URI associations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Call <see cref="UpdateDescriptions"/> in a timely fashion to keep descriptions up-to-date and localised.
|
/// Call <see cref="LocaliseDescriptions"/> in a timely fashion to keep descriptions up-to-date and localised.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static void InstallAssociations()
|
public static void InstallAssociations()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
updateAssociations();
|
updateAssociations();
|
||||||
updateDescriptions(null); // write default descriptions in case `UpdateDescriptions()` is not called.
|
|
||||||
NotifyShellUpdate();
|
NotifyShellUpdate();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -76,17 +75,13 @@ namespace osu.Desktop.Windows
|
|||||||
/// Updates associations with latest definitions.
|
/// Updates associations with latest definitions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Call <see cref="UpdateDescriptions"/> in a timely fashion to keep descriptions up-to-date and localised.
|
/// Call <see cref="LocaliseDescriptions"/> in a timely fashion to keep descriptions up-to-date and localised.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static void UpdateAssociations()
|
public static void UpdateAssociations()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
updateAssociations();
|
updateAssociations();
|
||||||
|
|
||||||
// TODO: Remove once UpdateDescriptions() is called as specified in the xmldoc.
|
|
||||||
updateDescriptions(null); // always write default descriptions, in case of updating from an older version in which file associations were not implemented/installed
|
|
||||||
|
|
||||||
NotifyShellUpdate();
|
NotifyShellUpdate();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -95,11 +90,17 @@ namespace osu.Desktop.Windows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateDescriptions(LocalisationManager localisationManager)
|
// TODO: call this sometime.
|
||||||
|
public static void LocaliseDescriptions(LocalisationManager localisationManager)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
updateDescriptions(localisationManager);
|
foreach (var association in file_associations)
|
||||||
|
association.LocaliseDescription(localisationManager);
|
||||||
|
|
||||||
|
foreach (var association in uri_associations)
|
||||||
|
association.LocaliseDescription(localisationManager);
|
||||||
|
|
||||||
NotifyShellUpdate();
|
NotifyShellUpdate();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -140,17 +141,6 @@ namespace osu.Desktop.Windows
|
|||||||
association.Install();
|
association.Install();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateDescriptions(LocalisationManager? localisation)
|
|
||||||
{
|
|
||||||
foreach (var association in file_associations)
|
|
||||||
association.UpdateDescription(getLocalisedString(association.Description));
|
|
||||||
|
|
||||||
foreach (var association in uri_associations)
|
|
||||||
association.UpdateDescription(getLocalisedString(association.Description));
|
|
||||||
|
|
||||||
string getLocalisedString(LocalisableString s) => localisation?.GetLocalisedString(s) ?? s.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Native interop
|
#region Native interop
|
||||||
|
|
||||||
[DllImport("Shell32.dll")]
|
[DllImport("Shell32.dll")]
|
||||||
@ -174,9 +164,20 @@ namespace osu.Desktop.Windows
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private record FileAssociation(string Extension, LocalisableString Description, string IconPath)
|
private class FileAssociation
|
||||||
{
|
{
|
||||||
private string programId => $@"{program_id_prefix}{Extension}";
|
private string programId => $@"{program_id_prefix}{extension}";
|
||||||
|
|
||||||
|
private string extension { get; }
|
||||||
|
private LocalisableString description { get; }
|
||||||
|
private string iconPath { get; }
|
||||||
|
|
||||||
|
public FileAssociation(string extension, LocalisableString description, string iconPath)
|
||||||
|
{
|
||||||
|
this.extension = extension;
|
||||||
|
this.description = description;
|
||||||
|
this.iconPath = iconPath;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Installs a file extension association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key
|
/// Installs a file extension association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key
|
||||||
@ -189,14 +190,16 @@ namespace osu.Desktop.Windows
|
|||||||
// register a program id for the given extension
|
// register a program id for the given extension
|
||||||
using (var programKey = classes.CreateSubKey(programId))
|
using (var programKey = classes.CreateSubKey(programId))
|
||||||
{
|
{
|
||||||
|
programKey.SetValue(null, description.ToString());
|
||||||
|
|
||||||
using (var defaultIconKey = programKey.CreateSubKey(default_icon))
|
using (var defaultIconKey = programKey.CreateSubKey(default_icon))
|
||||||
defaultIconKey.SetValue(null, IconPath);
|
defaultIconKey.SetValue(null, iconPath);
|
||||||
|
|
||||||
using (var openCommandKey = programKey.CreateSubKey(SHELL_OPEN_COMMAND))
|
using (var openCommandKey = programKey.CreateSubKey(SHELL_OPEN_COMMAND))
|
||||||
openCommandKey.SetValue(null, $@"""{exe_path}"" ""%1""");
|
openCommandKey.SetValue(null, $@"""{exe_path}"" ""%1""");
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var extensionKey = classes.CreateSubKey(Extension))
|
using (var extensionKey = classes.CreateSubKey(extension))
|
||||||
{
|
{
|
||||||
// set ourselves as the default program
|
// set ourselves as the default program
|
||||||
extensionKey.SetValue(null, programId);
|
extensionKey.SetValue(null, programId);
|
||||||
@ -208,13 +211,13 @@ namespace osu.Desktop.Windows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateDescription(string description)
|
public void LocaliseDescription(LocalisationManager localisationManager)
|
||||||
{
|
{
|
||||||
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
||||||
if (classes == null) return;
|
if (classes == null) return;
|
||||||
|
|
||||||
using (var programKey = classes.OpenSubKey(programId, true))
|
using (var programKey = classes.OpenSubKey(programId, true))
|
||||||
programKey?.SetValue(null, description);
|
programKey?.SetValue(null, localisationManager.GetLocalisedString(description));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -225,7 +228,7 @@ namespace osu.Desktop.Windows
|
|||||||
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
||||||
if (classes == null) return;
|
if (classes == null) return;
|
||||||
|
|
||||||
using (var extensionKey = classes.OpenSubKey(Extension, true))
|
using (var extensionKey = classes.OpenSubKey(extension, true))
|
||||||
{
|
{
|
||||||
// clear our default association so that Explorer doesn't show the raw programId to users
|
// clear our default association so that Explorer doesn't show the raw programId to users
|
||||||
// the null/(Default) entry is used for both ProdID association and as a fallback friendly name, for legacy reasons
|
// the null/(Default) entry is used for both ProdID association and as a fallback friendly name, for legacy reasons
|
||||||
@ -240,13 +243,24 @@ namespace osu.Desktop.Windows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private record UriAssociation(string Protocol, LocalisableString Description, string IconPath)
|
private class UriAssociation
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "The <c>URL Protocol</c> string value indicates that this key declares a custom pluggable protocol handler."
|
/// "The <c>URL Protocol</c> string value indicates that this key declares a custom pluggable protocol handler."
|
||||||
/// See https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85).
|
/// See https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string URL_PROTOCOL = @"URL Protocol";
|
private const string url_protocol = @"URL Protocol";
|
||||||
|
|
||||||
|
private string protocol { get; }
|
||||||
|
private LocalisableString description { get; }
|
||||||
|
private string iconPath { get; }
|
||||||
|
|
||||||
|
public UriAssociation(string protocol, LocalisableString description, string iconPath)
|
||||||
|
{
|
||||||
|
this.protocol = protocol;
|
||||||
|
this.description = description;
|
||||||
|
this.iconPath = iconPath;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers an URI protocol handler in accordance with https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85).
|
/// Registers an URI protocol handler in accordance with https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85).
|
||||||
@ -256,31 +270,32 @@ namespace osu.Desktop.Windows
|
|||||||
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
||||||
if (classes == null) return;
|
if (classes == null) return;
|
||||||
|
|
||||||
using (var protocolKey = classes.CreateSubKey(Protocol))
|
using (var protocolKey = classes.CreateSubKey(protocol))
|
||||||
{
|
{
|
||||||
protocolKey.SetValue(URL_PROTOCOL, string.Empty);
|
protocolKey.SetValue(null, $@"URL:{description}");
|
||||||
|
protocolKey.SetValue(url_protocol, string.Empty);
|
||||||
|
|
||||||
using (var defaultIconKey = protocolKey.CreateSubKey(default_icon))
|
using (var defaultIconKey = protocolKey.CreateSubKey(default_icon))
|
||||||
defaultIconKey.SetValue(null, IconPath);
|
defaultIconKey.SetValue(null, iconPath);
|
||||||
|
|
||||||
using (var openCommandKey = protocolKey.CreateSubKey(SHELL_OPEN_COMMAND))
|
using (var openCommandKey = protocolKey.CreateSubKey(SHELL_OPEN_COMMAND))
|
||||||
openCommandKey.SetValue(null, $@"""{exe_path}"" ""%1""");
|
openCommandKey.SetValue(null, $@"""{exe_path}"" ""%1""");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateDescription(string description)
|
public void LocaliseDescription(LocalisationManager localisationManager)
|
||||||
{
|
{
|
||||||
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
||||||
if (classes == null) return;
|
if (classes == null) return;
|
||||||
|
|
||||||
using (var protocolKey = classes.OpenSubKey(Protocol, true))
|
using (var protocolKey = classes.OpenSubKey(protocol, true))
|
||||||
protocolKey?.SetValue(null, $@"URL:{description}");
|
protocolKey?.SetValue(null, $@"URL:{localisationManager.GetLocalisedString(description)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Uninstall()
|
public void Uninstall()
|
||||||
{
|
{
|
||||||
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true);
|
||||||
classes?.DeleteSubKeyTree(Protocol, throwOnMissingSubKey: false);
|
classes?.DeleteSubKeyTree(protocol, throwOnMissingSubKey: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user