H.NotifyIcon icon indicating copy to clipboard operation
H.NotifyIcon copied to clipboard

Unpackaged WinUI apps crash when using ms-appx URIs

Open dalyIsaac opened this issue 2 years ago • 1 comments

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

  1. Check out the current H.NotifyIcon master branch (1d3326c7e02917e843547df68b81b2f91480a3af).
  2. 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".
  3. 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

dalyIsaac avatar May 08 '22 08:05 dalyIsaac

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?

HavenDV avatar May 09 '22 01:05 HavenDV

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;
    ...
}

ArakawaHenri avatar Oct 06 '22 13:10 ArakawaHenri

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;

ArakawaHenri avatar Oct 08 '22 19:10 ArakawaHenri

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.

ChristianGalla avatar Jan 02 '23 22:01 ChristianGalla