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

fix: handle picky Win11 ToastNotificationService #487

Open
wants to merge 1 commit into
base: release/1.3
Choose a base branch
from

Conversation

jglathe
Copy link
Contributor

@jglathe jglathe commented Apr 21, 2023

On a "virgin" Windows 11 machine without VS and notifications off, I got this exception:

Software version: 1.3.278 - a3e65fee6f (64 bit)
.NET runtime version: 4.0.30319.42000+
Time: 2023-04-20 06:51:03 +02:00
OS: Windows 10 2009 x64 build 22621
GDI object count: 58
User object count: 19

Exception: System.InvalidOperationException
Message: Failed initializing notifications

Stack:
   at Microsoft.Toolkit.Uwp.Notifications.ToastNotificationManagerCompat.CreateToastNotifier()
   at Greenshot.Plugin.Win10.ToastNotificationService.ShowMessage(String message, Nullable`1 timeout, Action onClickAction, Action onClosedAction) in C:\Users\glath\Source\Repos\greenshot\src\Greenshot.Plugin.Win10\ToastNotificationService.cs:line 179
   at Greenshot.Plugin.Win10.ToastNotificationService.ShowInfoMessage(String message, Nullable`1 timeout, Action onClickAction, Action onClosedAction) in C:\Users\glath\Source\Repos\greenshot\src\Greenshot.Plugin.Win10\ToastNotificationService.cs:line 200
   at Greenshot.Forms.MainForm.HandleDataTransport(CopyDataTransport dataTransport) in C:\Users\glath\Source\Repos\greenshot\src\Greenshot\Forms\MainForm.cs:line 608
   at Greenshot.Forms.MainForm..ctor(CopyDataTransport dataTransport) in C:\Users\glath\Source\Repos\greenshot\src\Greenshot\Forms\MainForm.cs:line 502
   at Greenshot.Forms.MainForm.Start(String[] arguments) in C:\Users\glath\Source\Repos\greenshot\src\Greenshot\Forms\MainForm.cs:line 325
--- InnerException: ---
Exception: System.IO.IOException
Message: Ein dauerhafter Unterschlüssel kann nicht unter einem temporären übergeordneten Schlüssel erstellt werden.


Stack:
   at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str)
   at Microsoft.Win32.RegistryKey.CreateSubKeyInternal(String subkey, RegistryKeyPermissionCheck permissionCheck, Object registrySecurityObj, RegistryOptions registryOptions)
   at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey)
   at Microsoft.Toolkit.Uwp.Notifications.ToastNotificationManagerCompat.Initialize()
   at Microsoft.Toolkit.Uwp.Notifications.ToastNotificationManagerCompat..cctor()

I probed a little with my bullshitting buddy ChatGPT and found a possible reason and a fix for this.

possible reason:

Yes, `ToastNotificationManagerCompat.CreateToastNotifier()` may try to write to the registry.

Yes, `ToastNotificationManagerCompat.CreateToastNotifier()` may try to write to the registry. The method is used to create a `ToastNotifier` object which can be used to display toast notifications on the Windows 10 desktop. In order to create the `ToastNotifier` object, the method needs to access the Windows registry to determine the current user's settings for notifications.

Specifically, CreateToastNotifier() calls ToastNotificationManagerCompat.Initialize() which initializes the Windows Runtime Toast Notification API and attempts to create a ToastNotifier object. During the initialization process, the method attempts to create a registry key under HKEY_CURRENT_USER\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\Notifications with a subkey named Settings, which contains various settings related to notifications. If there is an issue with creating this registry key or accessing its subkeys, it can cause an IOException or an InvalidOperationException to be thrown.

a lot of BSing later, the solution appears to be to explicitly declare a ToastNotifierCompat variable and call ToastNotificationManagerCompat.CreateToastNotifier - I only wanted to catch the possible exception, but apparently forces this a hard cast to ToastNotifierCompat as the target object, which changes the creation process of the object and doesn't use the registry at all, at least without an exception. 🤷‍♂️😎

This is the PR description ChatGPT generates:

ChtGPT nicely describing the issue

This pull request updates the ToastNotificationService in Greenshot to explicitly create a ToastNotifierCompat instance, which avoids an issue with the Windows registry that could cause notifications to fail.

Previously, the CreateToastNotifier method was used to create a ToastNotifier instance, which could return an object with properties other than ToastNotifierCompat. This approach also relied on the system registry to determine the correct application ID, which could be problematic if the ID was not correctly registered. The new approach avoids these issues by explicitly creating a ToastNotifierCompat instance with the correct application ID. This change has been tested successfully on both Windows 10 and Windows 11.

Yes I have tested on Windows 10 and 11, and Windows 11 arm64.

Exception: System.InvalidOperationException
Message: Failed initializing notifications
--- InnerException: ---
Exception: System.IO.IOException
Message: Ein dauerhafter Unterschlüssel kann nicht unter einem temporären übergeordneten Schlüssel erstellt werden.

Signed-off-by: Jens Glathe <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant