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

Near-impossible to create a nuget package with WinUI 3 controls and resources #3546

Open
dotMorten opened this issue Mar 29, 2023 · 17 comments
Labels
area-DeveloperTools Issues related to authoring (source and IDL), debugging, HotReload, LiveVisualTree, VS integration area-MRTCore ResourceManager needs-attention 👋

Comments

@dotMorten
Copy link
Contributor

dotMorten commented Mar 29, 2023

Describe the bug

When creating a C# class library and using the Pack target, the generated nuget package is incorrectly packing content files in a way where WAP packaged apps fail to build, and single-app projects fail to find resources.

Steps to reproduce the bug

  1. Unzip the sample project provided and open solution [PackagingBug.zip] (https://github.com/microsoft/WindowsAppSDK/files/11105641/PackagingBug.zip)
  2. Build MyControlLibrary project (simple custom control with an icon and custom font included with project)
  3. Notice in output, a warning is displayed hinting at what is about to go wrong:
1>MyControlLibrary -> E:\sources.tmp\PackagingBug\MyControlLibrary\bin\Debug\net6.0-windows10.0.19041.0\MyControlLibrary.dll
1>C:\Program Files\dotnet\sdk\7.0.102\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets(221,5): warning NU5118: File 'E:\sources.tmp\PackagingBug\MyControlLibrary\Assets\Icon.scale-200.png' is not added because the package already contains file 'content\Assets\Icon.scale-200.png'
1>C:\Program Files\dotnet\sdk\7.0.102\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets(221,5): warning NU5118: File 'E:\sources.tmp\PackagingBug\MyControlLibrary\Assets\Icon.scale-200.png' is not added because the package already contains file 'contentFiles\any\net6.0-windows10.0.19041\Assets\Icon.scale-200.png'
  1. Run ProjectRef_Test (Package) and verify the custom control works when using a project reference to the class library. You should see this:

image

  1. Build NugetRef_TestApp. Notice the build errors:
1>C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(5150,5): error MSB3030: Could not copy the file "E:\sources.tmp\PackagingBug\NuGet_Cache\mycontrollibrary\1.0.0\lib\net6.0-windows10.0.19041\MyControlLibrary\Themes\Generic.xbf" because it was not found.
1>C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(5150,5): error MSB3030: Could not copy the file "E:\sources.tmp\PackagingBug\NuGet_Cache\mycontrollibrary\1.0.0\lib\net6.0-windows10.0.19041\MyControlLibrary\MyCustomControl.Theme.xbf" because it was not found.
1>C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(5150,5): error MSB3030: Could not copy the file "E:\sources.tmp\PackagingBug\NuGet_Cache\mycontrollibrary\1.0.0\lib\net6.0-windows10.0.19041\MyControlLibrary\Assets\Icon.scale-200.png" because it was not found.
1>C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(5150,5): error MSB3030: Could not copy the file "E:\sources.tmp\PackagingBug\NuGet_Cache\mycontrollibrary\1.0.0\lib\net6.0-windows10.0.19041\MyControlLibrary\Assets\calcite-ui-icons-24.ttf" because it was not found.
  1. Instead build and run App_NugetReference_SingleApp which doesn't use a separate packaging project. This project builds, but will crash on launch with a very unhelpful error message:
    image

  2. We can work around the bug in Step 6, by modifying MyControlLibrary.csproj and adding:

    <ItemGroup>
        <Content Update="Assets\*.*" PackagePath="lib\net6.0-windows10.0.19041\$(PackageId)\Assets\%(Filename)%(Extension)" />
    </ItemGroup>

This however, doesn't fix the problem. We are now instead met with the following build error:

2>C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(5150,5): error MSB3030: Could not copy the file "E:\sources.tmp\PackagingBug\NuGet_Cache\mycontrollibrary\1.0.0\lib\net6.0-windows10.0.19041\MyControlLibrary\MyCustomControl.Theme.xbf" because it was not found.
2>C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(5150,5): error MSB3030: Could not copy the file "E:\sources.tmp\PackagingBug\NuGet_Cache\mycontrollibrary\1.0.0\lib\net6.0-windows10.0.19041\MyControlLibrary\Themes\Generic.xbf" because it was not found.

At this point I have not been able to successfully create a nuget package with WinUI controls that has content files and works with both single-project and wap projects.

However even without the workaround in Step 8, if you open the generated nuget package, you'll see both a content and contentFiles folder, and the assets are in there, however are in the wrong folder, and should be pushed further down to include the package name, or the paths like ms-appx:///MyControlLibrary/Assets/... will not be correct since it is missing the package name. Again this can sort of be work around with this:

    <ItemGroup>
        <Content Update="Assets\*.*" PackagePath="contentFiles\any\net6.0-windows10.0.19041\$(PackageId)\Assets\%(Filename)%(Extension)" />
    </ItemGroup>

but again that doesn't really help that much, other than getting the content files deployed in the right location, but single-project app still crashes on launch.

Expected behavior

Generated nuget packages works and deploys files in the right folder.

Screenshots

No response

NuGet package version

Windows App SDK 1.2.5: 1.2.230313.1

Packaging type

Packaged (MSIX)

Windows version

Windows 11 version 22H2 (22621, 2022 Update)

IDE

Visual Studio 2022

Additional context

Note: I'm using a slight "hack" to get the sample apps use a locally built nuget-reference. Sometimes this causes restore errors, which can usually be handled by removing the obj folders in the app projects and rebuilding them, but sometimes it just wants a quick restart of VS to get it to snap out of it.

Additionally I had no luck using <PRIResource /> instead of <Content /> either (that even breaks the project reference version).

@dotMorten
Copy link
Contributor Author

dotMorten commented Apr 3, 2023

Still digging through this without a resolution. I did find that once you got multiple XAML files in your project, they are no longer embedded in the .pri file. Only when you have a single Generic.xaml do you get it embedded.
I found that setting <DisableEmbeddedXbf>false</DisableEmbeddedXbf> will embed all the .xbf files

dotMorten pushed a commit to Esri/arcgis-maps-sdk-dotnet-toolkit that referenced this issue Apr 3, 2023
dotMorten pushed a commit to Esri/arcgis-maps-sdk-dotnet-toolkit that referenced this issue Apr 4, 2023
@bpulliam bpulliam added area-DeveloperTools Issues related to authoring (source and IDL), debugging, HotReload, LiveVisualTree, VS integration needs-attention 👋 labels Apr 5, 2023
@sam-wheat
Copy link

I am also looking for a resolution for this. See this issue also.

dotMorten added a commit to Esri/arcgis-maps-sdk-dotnet-toolkit that referenced this issue Apr 19, 2023
* v200.1

* WPF Popupviewer updates (#491)

* Switch to use PopupElements for popup viewer control

* Address namespace changes

* Update WindowsAppSDK version to match MAUI requirements (#500)

* Update deprecated property

* Add properties to allow compiling for .NET Framework

* Fix typo

* Avoid navigation string resources in toolkit package

* Updates relevant to popupviewer enhancements

(cherry picked from commit 273a7d7)

* Update README.md

Co-authored-by: Morten Nielsen <1378165+dotMorten@users.noreply.github.com>

* Update docs/popup-viewer.md

Co-authored-by: Morten Nielsen <1378165+dotMorten@users.noreply.github.com>

* Fix min-version support in MAUI

* Maui: Ensure fonts are packaged and deployed

* Add support for basic HTML in popups (#504)

* Work around asset deployment issues caused by WinAppSDK

See microsoft/WindowsAppSDK#3546 for details

* Also include assets in lib folder for library layout

Follow-up to work around issue microsoft/WindowsAppSDK#3546

* Set background on toolbar

---------

Co-authored-by: Morten Nielsen <mort5161@esri.com>
Co-authored-by: Matvei Stefarov <mstefarov@esri.com>
Co-authored-by: Preeti Maske <pmaske@esri.com>
@Felix-CodingClimber
Copy link

Same problem here...

@evelynwu-msft
Copy link
Contributor

Nuget packages created with $(Configuration)==Debug aren't going to work without also explicitly setting DisableEmbeddedXbf to false (this was true as well of Nuget packages using UWP XAML).

As for the incorrect source asset paths... those are the result of an MRT target extracting from all referenced .pri files the paths of Path resources to ensure they get copied to the output directory. When the referenced .pri comes from a project then the embedded path matches the actual source layout. But when it comes from a Nuget package there is a mismatch because Nuget places Content into the content and contentFiles directories. But this is fine because when building Nuget will copy those files into the correct destination, so MRT's own copy operation is both unsuccessful and redundant. (Incidentally, I suspect this same issue affects UWP XAML Nuget packages.)

@robertzhou-wpn At a minimum I believe that the MRT Core target AddPriPayloadFilesToCopyToOutputDirectoryItems needs to exclude refereinced .pri files that come from Nuget packages when building the list of .pri files that need to be expanded.

@evelynwu-msft evelynwu-msft added the area-MRTCore ResourceManager label May 3, 2023
@nickrandolph
Copy link

Any movement on getting this issue fixed?

@cody3b
Copy link

cody3b commented Aug 2, 2023

Interested in a solution for this as well.

VincentH-Net added a commit to VincentH-Net/CSharpForMarkup that referenced this issue Oct 23, 2023
@AlanKharebov
Copy link

I have the same problem.
In a similar WPF app, the reference to a UserControl looks like this:
xmlns:wpfControlLibrary="clr-namespace:WpfControlLibrary;assembly=WpfControlLibrary"

However, in WinUI, it is done like this:
xmlns:testLibrary="using:TestLibrary".

Note that there is no "assembly=WpfControlLibrary" in the WinUI version.

I wanted to switch to WinUI, but it still looks very immature compared to WPF.

@AlanKharebov
Copy link

Here my test app in GitHub
https://github.com/AlanKharebov/TestApp

@dotMorten
Copy link
Contributor Author

@AlanKharebov this seems unrelated to this issue. Also I’m not sure why you see a much simplified syntax which UWP also have had for years as signs it is immature but that’s again off topic.

@abdes
Copy link

abdes commented Jan 29, 2024

@dotMorten have you found a workaround for this issue? I doubt we will get a solution before at least a year or two...

@dotMorten
Copy link
Contributor Author

@abdes only via manual fixing nuget package in a post-packaging step. It sucks

@abdes
Copy link

abdes commented Jan 29, 2024

@abdes only via manual fixing nuget package in a post-packaging step. It sucks

Yeah that kinda sucks. I ended up doing my coding in a mono-repo fashion so I can just reference projects. Cannot share anything via NuGet, which really sucks.

By the way, another workaround is to code the UI in C#, not XAML. So I took a look at https://github.com/VincentH-Net/CSharpForMarkup but they don't support Community Toolkit controls, which kinda sucks again cause we have some good stuff in the CTK and re-coding it in C# Markup is too much effort for me.

I just don't get how Microsoft envisioned WinUI without Nuget, and yeah, I get that they want to stay faithful to the fluent UI, but what's wrong with sharing views built on WinUI?

@DRAirey1
Copy link

DRAirey1 commented Feb 11, 2024

First, I can confirm this is a big issue with WinUI.

Second, there is another option. It's not great, but it appears to work: remove all the content resources from your package. My package only used about a dozen images. All of my XAML uses the "ms-appx:" syntax to identify resources, so it's easy enough to change them around to point to a local collection of resources (instead of packaged resources). If you accept that limitation, the large library of custom controls that my applications use seems to have packaged up nicely into a NuGet package. At least, with this option, I can package the common controls and XAML helpers.

@michael-hawker
Copy link

I've been going down a rabbit hole looking for something else, but I didn't think we did anything special here for the Windows Community Toolkit and have seen/tried using it in both types of app projects.

@dotMorten maybe you can help me understand what the gap is here between what the Toolkit does and this issue? Or do the Toolkit components also have this issue and I just haven't realized...? We haven't heard of anyone having issues using them with WinUI 3 like this.

@dotMorten
Copy link
Contributor Author

@michael-hawker it's bit a while since I had to hack around this issue, but if I recall, content files aren't packaged correctly in a WinAppSDK project, compared to how UWP would package it when generating an app layout. It's put in the wrong folders and generating the nuget manifest wrong.

@michael-hawker
Copy link

Hmm, maybe we don't have many content files then in the Toolkit? I would have imagined we have something somewhere within it... it's a large project.

@dotMorten
Copy link
Contributor Author

dotMorten commented Mar 29, 2024

@michael-hawker here's a more recent package I did, where I redirect the content file to a different folder:
https://github.com/dotMorten/CalciteDotNet/blob/main/src/Esri.Calcite.WinUI/Esri.Calcite.WinUI.csproj#L14
And then include a build script to correctly include the file:
https://github.com/dotMorten/CalciteDotNet/blob/main/src/Esri.Calcite.WinUI/build/Esri.Calcite.WinUI.targets#L4-L9

In UWP that was never needed - the files that the library relies on should go in the librarylayout folder and would "just work"

VincentH-Net added a commit to VincentH-Net/CSharpForMarkup that referenced this issue Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-DeveloperTools Issues related to authoring (source and IDL), debugging, HotReload, LiveVisualTree, VS integration area-MRTCore ResourceManager needs-attention 👋
Projects
None yet
Development

No branches or pull requests