Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Associate with files and URIs on windows #27001

Merged
merged 32 commits into from
Mar 1, 2024

Conversation

Susko3
Copy link
Member

@Susko3 Susko3 commented Feb 3, 2024

Fixed problems from the previous PR

  • URL associations are implemented
  • added localisable file descriptions
  • added file icons
  • registry keys are properly disposed
  • implementation is testable in a reasonable way
  • SHChangeNotify is now called in a non-blocking way
  • fixed stable registry keys taking priority (this is handled by the windows explorer -- it'll ask the user (once) in which program to open)

Problems with this PR

  • (Fixed) associations are re-created every time on startup (it's not great, but it probably doesn't matter that much)
  • (Fixed) associations clash with getStableInstallPathFromRegistry()
    • if stable uses HKEY_LOCAL_MACHINE, maybe we could use that there instead. since this PR saves to HKEY_CURRENT_USER
  • localised file association descriptions are never written

Testing

Can be done trough the added test scene. Only manual testing is available.

Best way to test in the test scene is to install associations, then try the open/present beatmap/url. You can also uninstall and then check that associations don't work.

For now, uninstalling is only available trough tests and it's not possible to uninstall from the game.

Can be tested by running static methods in WindowsAssociationManager.

I have tested a full deploy+install on a test PC and it's working perfectly!

@Susko3
Copy link
Member Author

Susko3 commented Feb 5, 2024

Hmm, I'm not sure how to make this testable now that ppy/osu-resources#308 is closed and icons are supposed to be in osu.Desktop... Maybe move the current code to osu.Game.Platform.Windows, make it more abstract (actual associations are defined somewhere in osu.Desktop or osu.Game.Tests projects, but WindowsAssociationManager knows how to install them).

This could allow us to make eg. .osz-test associations for testing, which is much cleaner.

@bdach
Copy link
Collaborator

bdach commented Feb 5, 2024

I'm not sure visual tests for this are useful at this stage. If this is gonna hook into squirrel flows the only actual way to test this is via osu-deploy.

I'm kinda uncomfortable with the notion of "visual tests" touching system registry to begin with.

These icons should appear in end-user installation folder.
Can be tested with
```
dotnet publish -f net6.0 -r win-x64 osu.Desktop -o publish -c Debug
publish\osu!
```
osu.Desktop/Windows/Win32Icon.cs Outdated Show resolved Hide resolved
osu.Desktop/Windows/Icons.cs Outdated Show resolved Hide resolved
protected override void LoadComplete()
{
base.LoadComplete();
localisationParameters.ValueChanged += _ => updateDescriptions();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit veiled, but what this ends up implying is that every single change of user language, or even the "show metadata in original language" toggle in settings, is going to cause writes to the windows registry. I am not comfortable with this and do not think that is sane.

I think there are two paths I'd rather take here:

  • not bother with localising descriptions at all
  • localise them, but on a one-shot basis, at point of installation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

localise them, but on a one-shot basis, at point of installation.

This relies too heavily on the automatic language selection being correct. How about updating the localised description once the user selects and confirms their language in the first-run setup wizard?

Copy link
Collaborator

@bdach bdach Feb 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This relies too heavily on the automatic language selection being correct

What do you mean by "too heavily"? I'm not sure I've known that to fail that much. If there's one place where that should work perfectly it's windows.

How about updating the localised description once the user selects and confirms their language in the first-run setup wizard?

Eeeeehhhh I don't know. I'd rather not touch the registry outside of squirrel flows / manual intervention via settings button.

Copy link
Member Author

@Susko3 Susko3 Feb 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ppy/team-client I'm happy with the code and this PR is ready for review. The above conversation and stable in 'open with' remain the only open questions.

osu.Desktop/OsuGameDesktop.cs Outdated Show resolved Hide resolved
@bdach
Copy link
Collaborator

bdach commented Feb 7, 2024

associations clash with getStableInstallPathFromRegistry()

Can you elaborate on what this means?

@Susko3
Copy link
Member Author

Susko3 commented Feb 7, 2024

associations clash with getStableInstallPathFromRegistry()

Can you elaborate on what this means?

getStableInstallPathFromRegistry() queries the current osu:// URI handler and checks if it is stable. Since lazer will overwrite that handler (for thr current user), the stable install path information will be lost.

File associations for lazer and stable are installed side-by-side, so I'll look into using those for detecting the stable install.

@Susko3
Copy link
Member Author

Susko3 commented Feb 7, 2024

I've just checked how this behaves with stable installed. I used a clean slate test PC which hasn't ever had stable or lazer installed.

  • stable registers .osz2, is this a file format lazer can handle? (a quick search yields that it doesn't)
  • stable uses a lowercase osu! beatmap as the file description
  • stable calls every file osu! beatmap
  • there is no 'open with' for protocols, so osu:// is always handled by lazer (HKCU overrides HKLM)
    • uninstalling lazer will restore stable as the protocol handler
  • we can use the osu! entry for getStableInstallPathFromRegistry(), as that is used exclusively by stable

comparison

As it currently stands, lazer file associations override stable's, with only lazer appearing in the open with menu:

only lazer

Luckily, it's a simple fix and can be done either from stable or lazer. The following registry keys need to be added (both HKLM and HKCU works!):

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osk\OpenWithProgIds]
"osu!"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osr\OpenWithProgIds]
"osu!"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osz\OpenWithProgIds]
"osu!"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osz2\OpenWithProgIds]
"osu!"=""

lazer and stable

Registry entries installed by stable (reference)

Windows Registry Editor Version 5.00

; files

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osk]
@="osu!"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osr]
@="osu!"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osz]
@="osu!"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.osz2]
@="osu!"

; protocol

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\osu]
@="osu! url handler"
"URL Protocol"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\osu\DefaultIcon]
@="\"C:\\Users\\User\\AppData\\Local\\osu!\\osu!.exe\",1"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\osu\shell\open\command]
@="\"C:\\Users\\User\\AppData\\Local\\osu!\\osu!.exe\" \"%1\""

; file handler (only 1)

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\osu!]
@="osu! beatmap"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\osu!\DefaultIcon]
@="\"C:\\Users\\User\\AppData\\Local\\osu!\\osu!.exe\",1"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\osu!\shell\open\command]
@="\"C:\\Users\\User\\AppData\\Local\\osu!\\osu!.exe\" \"%1\""

`osu` is the `osu://` protocol handler, which gets overriden by lazer.
Instead, use `osu!` which is the stable file handler.
@Joehuu Joehuu changed the title Associate with files and URIs on windows V2 Associate with files and URIs on windows Feb 8, 2024
/// </summary>
public const string SHELL_OPEN_COMMAND = @"Shell\Open\Command";

public static readonly string EXE_PATH = Path.ChangeExtension(typeof(WindowsAssociationManager).Assembly.Location, ".exe").Replace('/', '\\');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with the replace at the end? This already appears to be correct on my machine...

> typeof(Program).Assembly.Location
  "D:\\Open Source\\osu\\osu.Desktop\\bin\\Debug\\net8.0\\osu!.dll"

> Path.ChangeExtension(typeof(Program).Assembly.Location, ".exe")
  "D:\\Open Source\\osu\\osu.Desktop\\bin\\Debug\\net8.0\\osu!.exe"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When running static methods from Rider (for testing), it would have / as a path separator.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dunno that's weird. I'd like to think windows should be able to handle either?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows doesn't handle / and errors out.

Interesting to note is that the icons work fine because Path.GetDirectoryName will normalise path separators to \.

osu.Desktop/Windows/WindowsAssociationManager.cs Outdated Show resolved Hide resolved
osu.Desktop/Windows/WindowsAssociationManager.cs Outdated Show resolved Hide resolved
@peppy peppy added the next release Pull requests which are almost there. We'll aim to get them in the next release, but no guarantees! label Feb 26, 2024
@peppy
Copy link
Member

peppy commented Feb 26, 2024

Hope we can get this in the next release.

@bdach
Copy link
Collaborator

bdach commented Feb 27, 2024

I've tested this and it seems to be behaving pretty well, and getting along with stable pretty amicably even. Did just one small cleanup commit (87509fb), looks good to go otherwise.

We may need some improvements to client itself (e.g. bring the window to front after something has been imported via shell associations or opened via url protocols) but that can come later.

The localisation stuff basically cannot be tested right now but I'd be okay with it just using hardcoded english really.

bdach
bdach previously approved these changes Feb 27, 2024
@bdach bdach requested a review from peppy February 27, 2024 13:41
Copy link
Member

@peppy peppy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works well for me!

@peppy peppy merged commit 91483bd into ppy:master Mar 1, 2024
8 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
next release Pull requests which are almost there. We'll aim to get them in the next release, but no guarantees! platform/windows size/L
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Game does not associate with files on windows
3 participants