Refresh Explorer association cache after registering file associations#37
Merged
Conversation
`install_file_associations` wrote each per-user class registration but never told Explorer to refresh its cached file-type defaults, so a newly registered association only took effect after the next sign-in or an Explorer restart. For an extension Explorer had already resolved to another app (e.g. `.json` -> Visual Studio) the stale default kept winning on double-click even though the new type showed up in "Open with". Extensions nothing else had claimed (`.md`, `.yaml`, `.toml`) had no cached default, so they resolved fresh to the new handler and masked the gap. Changes: - Add `_notify_assoc_changed()`, which calls `SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, ...)` via `ctypes` to invalidate Explorer's association cache. It uses a local `import ctypes` to match the module's existing pattern for Windows-only APIs (`winreg`), so the module still imports cleanly on the Linux CI runner. - Call it once in `install_file_associations` after the registration loop, so the broadcast fires a single time regardless of how many extensions were registered. No unit test added: the helper is a thin `shell32` call with no return value to assert on; the existing import smoke test already covers it loading.
Contributor
There was a problem hiding this comment.
Pull request overview
Ensures newly registered per-user Windows file associations take effect immediately by explicitly invalidating Explorer’s association cache after registry writes, avoiding the need for sign-out or restarting Explorer.
Changes:
- Add a Windows-only helper
_notify_assoc_changed()that callsSHChangeNotify(SHCNE_ASSOCCHANGED, ...)viactypesto refresh Explorer’s association cache. - Call
_notify_assoc_changed()once at the end ofinstall_file_associations()(after processing all configured associations) and log the refresh action. - Expand the
install_file_associationsdocstring to document the refresh behavior.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
install_file_associationswrote each per-user class registration but never told Explorer to refresh its cached file-type defaults, so a newly registered association only took effect after the next sign-in or an Explorer restart. For an extension Explorer had already resolved to another app (e.g..json-> Visual Studio) the stale default kept winning on double-click even though the new type showed up in "Open with". Extensions nothing else had claimed (.md,.yaml,.toml) had no cached default, so they resolved fresh to the new handler and masked the gap.Changes:
_notify_assoc_changed(), which callsSHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, ...)viactypesto invalidate Explorer's association cache. It uses a localimport ctypesto match the module's existing pattern for Windows-only APIs (winreg), so the module still imports cleanly on the Linux CI runner.install_file_associationsafter the registration loop, so the broadcast fires a single time regardless of how many extensions were registered.No unit test added: the helper is a thin
shell32call with no return value to assert on; the existing import smoke test already covers it loading.make ci(ruff check + format, 18 unittests, schema) passes locally, and the call was confirmed live on Windows 11.