Fix title bar icon missing in single-file published builds
The title bar Image used Source="ms-appx:///Assets/Square44x44Logo.scale-200.png". That resolves fine in a normal build (Assets/ and AmiReel.pri sit next to the exe), but a single-file self-contained publish (IncludeAllContentForSelfExtract=true) bundles Content items into the exe in a way ms-appx:// can no longer resolve at runtime, leaving the title bar icon blank — reproduced with the actual publish-win-x64.ps1 output, confirmed fixed the same way. Load the icon from a plain embedded resource instead (same mechanism already used for ffmpeg.exe/ffprobe.exe): the PNG is embedded via <EmbeddedResource LogicalName="AmiReel.Assets.TitleBarIcon.png">, and MainWindow loads it at startup via GetManifestResourceStream + BitmapImage. SetSourceAsync. This bypasses the ms-appx/MRT resource pipeline entirely, so it behaves identically in dotnet build, dotnet run, and a single-file publish. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="ThirdParty\ffmpeg.exe" Condition="Exists('ThirdParty\ffmpeg.exe')" LogicalName="AmiReel.Tools.ffmpeg.exe" />
|
<EmbeddedResource Include="ThirdParty\ffmpeg.exe" Condition="Exists('ThirdParty\ffmpeg.exe')" LogicalName="AmiReel.Tools.ffmpeg.exe" />
|
||||||
<EmbeddedResource Include="ThirdParty\ffprobe.exe" Condition="Exists('ThirdParty\ffprobe.exe')" LogicalName="AmiReel.Tools.ffprobe.exe" />
|
<EmbeddedResource Include="ThirdParty\ffprobe.exe" Condition="Exists('ThirdParty\ffprobe.exe')" LogicalName="AmiReel.Tools.ffprobe.exe" />
|
||||||
|
<!-- Loaded at runtime via GetManifestResourceStream for the title bar icon (MainWindow.xaml.cs).
|
||||||
|
The Assets\*.png Content items above go through the ms-appx:// / MRT resource pipeline,
|
||||||
|
which a single-file self-contained publish bundles into the exe in a way that ms-appx://
|
||||||
|
can no longer resolve at runtime — this embedded copy sidesteps that entirely. -->
|
||||||
|
<EmbeddedResource Include="Assets\Square44x44Logo.scale-200.png" LogicalName="AmiReel.Assets.TitleBarIcon.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<Grid x:Name="AppTitleBar" Grid.Row="0" Height="44" Background="{ThemeResource PanelBrush}">
|
<Grid x:Name="AppTitleBar" Grid.Row="0" Height="44" Background="{ThemeResource PanelBrush}">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center" Margin="14,0,0,0">
|
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center" Margin="14,0,0,0">
|
||||||
<Image Source="ms-appx:///Assets/Square44x44Logo.scale-200.png"
|
<Image x:Name="TitleBarIcon"
|
||||||
Width="20"
|
Width="20"
|
||||||
Height="20"
|
Height="20"
|
||||||
Stretch="Uniform" />
|
Stretch="Uniform" />
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ using Microsoft.UI;
|
|||||||
using Microsoft.UI.Windowing;
|
using Microsoft.UI.Windowing;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Media.Imaging;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
using Windows.Graphics;
|
using Windows.Graphics;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
using WinRT.Interop;
|
using WinRT.Interop;
|
||||||
@@ -36,6 +39,7 @@ public sealed partial class MainWindow : Window
|
|||||||
AppWindow.SetIcon(executablePath);
|
AppWindow.SetIcon(executablePath);
|
||||||
|
|
||||||
SetDefaultSizeAndPosition();
|
SetDefaultSizeAndPosition();
|
||||||
|
LoadTitleBarIcon();
|
||||||
|
|
||||||
// Navigate the root frame to the main page on startup.
|
// Navigate the root frame to the main page on startup.
|
||||||
RootFrame.Navigate(typeof(MainPage));
|
RootFrame.Navigate(typeof(MainPage));
|
||||||
@@ -43,6 +47,30 @@ public sealed partial class MainWindow : Window
|
|||||||
AppWindow.Closing += AppWindow_Closing;
|
AppWindow.Closing += AppWindow_Closing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the title bar icon from an embedded resource instead of an "ms-appx:///Assets/..."
|
||||||
|
/// URI. A single-file self-contained publish bundles Content/Assets items into the exe in a
|
||||||
|
/// way the ms-appx resource pipeline can no longer resolve at runtime, leaving the title bar
|
||||||
|
/// blank; a plain embedded resource stream works the same in every publish mode.
|
||||||
|
/// </summary>
|
||||||
|
private async void LoadTitleBarIcon()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
|
using Stream? stream = assembly.GetManifestResourceStream("AmiReel.Assets.TitleBarIcon.png");
|
||||||
|
if (stream is null) return;
|
||||||
|
|
||||||
|
BitmapImage bitmap = new();
|
||||||
|
await bitmap.SetSourceAsync(stream.AsRandomAccessStream());
|
||||||
|
TitleBarIcon.Source = bitmap;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Non-critical: the title bar simply shows no icon if this fails.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetDefaultSizeAndPosition()
|
private void SetDefaultSizeAndPosition()
|
||||||
{
|
{
|
||||||
const int DefaultWidth = 1280;
|
const int DefaultWidth = 1280;
|
||||||
|
|||||||
Reference in New Issue
Block a user