H.NotifyIcon
H.NotifyIcon copied to clipboard
Unpackaged WinUI apps crash when using ms-appx URIs
Describe the bug
Unpackaged WinUI applications crash when providing an ms-appx
URI to IconSource
. This is likely because the StorageFile
API used for loading images requires package identity^1.
https://github.com/HavenDV/H.NotifyIcon/blob/1d3326c7e02917e843547df68b81b2f91480a3af/src/libs/H.NotifyIcon.Shared/Utilities/ImageExtensions.cs#L24-L25
Steps to reproduce the bug
- Check out the current
H.NotifyIcon
master
branch (1d3326c7e02917e843547df68b81b2f91480a3af). - Change https://github.com/HavenDV/H.NotifyIcon/blob/1d3326c7e02917e843547df68b81b2f91480a3af/src/apps/H.NotifyIcon.Apps.WinUI.Windowless/TrayIconResources.xaml#L36-L45 to use
IconSource="ms-appx:///Assets/Red.ico"
. - Start debugging
H.NotifyIcon.Apps.WinUI.Windowless
as an unpackaged app.
Expected behavior
The icon specified by IconSource
is displayed in the system tray.
Screenshots
No response
NuGet package version
Current master
of H.NotifyIcon
(1d3326c7e02917e843547df68b81b2f91480a3af).
Platform
WinUI
IDE
Visual Studio 2022
Additional context
No response
Thank you, this is a known issue. Do you know any way around this or do we just have to wait for it to be fixed on the WinUI side?
Thank you, this is a known issue. Do you know any way around this or do we just have to wait for it to be fixed on the WinUI side?
It looks like a uri with scheme "file://" can construct a BitmapImage, but H.NotifyIcon does not create the icon correctly from the BitmapImage constructed this way. Any plans to fix it?
Code I tried: xaml:
<icon:TaskbarIcon
...
IconSource="{x:Bind ViewModel.TaskbarIconSource, Mode=OneWay}"
...>
...
</icon:TaskbarIcon>
cs:
[ObservableProperty]
private ImageSource taskbarIconSource;
var func(args)
{
...
//Constructor of Uri automatically converts path to uri
var img = new BitmapImage(new Uri(Path.Combine(AppContext.BaseDirectory, "Assets/WindowIcon.ico")));
taskbarIconSource = img;
...
}
Also, such an attempt failed:
FileStream fileStream = new(Path.Combine(AppContext.BaseDirectory, "Assets/WindowIcon.ico"), FileMode.Open, FileAccess.Read);
var img = new BitmapImage();
img.SetSource(fileStream.AsRandomAccessStream());
taskbarIconSource = img;
I think the main issue is that the currently implementation of H.NotifyIcon only differs between WPF and none WPF using the pre compiler directive HAS_WPF.
If HAS_WPF is not defined (for example in a WinUI build), and a URI is given, StorageFile.GetFileFromApplicationUriAsync is called and fails because of a missing package identity.
https://github.com/HavenDV/H.NotifyIcon/blob/1994b1d07a5ec722959de54a41199bae81f2ef68/src/libs/H.NotifyIcon.Shared/Utilities/ImageExtensions.cs#L15-L39
Instead of different code for WPF generated via HAS_WPF, I suggest checking for package identity instead. One simple approach would be to simply check if the Uri starts with "ms-appx://" or "ms-appdata://" and if not use the File API instead.