Open vsfeedback opened 5 years ago
The WPF flavor currently does this in ModifyBuildAction
called by OnAfterAddFilesEx
but it fails with the simplified project system here.
Why is WPF flavor even involved in this?
@nguerrera @dsplaisted - should this be handled by globs in the WPF SDK in the new world?
The concern with this would be that switching globs by opting in "WPF" would be a fairly disruptive and likely breaking change of the project.
Discussed this at the CPS meeting and adding a new glob to the WPF SDK, but not removing the items from None, seems like the best solution. @davkean we can discuss offline if you still have concerns.
I don't think having globs for different item types (ie Resource and None) cover the same files works well. I think Visual Studio ends up doing weird things to your project file.
Right, and some things in VS may break entirely (T4 templates fail to work if both None and Content for example).
The idea behind using globs was to keep the project file clean, as distinct from changing the item type automatically which would have no option but to specify each file in the project file.
T4 templates should work after this change in CPS I imagine.
I tested this and adding <Resource Include="**\*.xml;... more extensions ...;" />
seems to work fine in general, though CPS is adding an unnecessary <None Remove="..." />
when a file is added, which I will look into.
Current proposal is to implement something akin to this in the SDK:
<ItemGroup Condition="'$(UseWPF)' == 'true' And $(UseWindowsForms) != 'true'">
<None Exclude="**\*.xml;**\*.xsl;**\*.xslt;**\*.txt;**\*.bmp;**\*.ico;**\*.cur;**\*.gif;**\*.jpeg;**\*.jpe;**\*.jpg;**\*.png;**\*.dib;**\*.tiff;**\*.tif;**\*.inf;**\*.compositefont;**\*.otf;**\*.ttf;**\*.ttc;**\*.tte" />
<Resource Include="**\*.xml;**\*.xsl;**\*.xslt;**\*.txt;**\*.bmp;**\*.ico;**\*.cur;**\*.gif;**\*.jpeg;**\*.jpe;**\*.jpg;**\*.png;**\*.dib;**\*.tiff;**\*.tif;**\*.inf;**\*.compositefont;**\*.otf;**\*.ttf;**\*.ttc;**\*.tte" />
</ItemGroup>
The list of file extensions comes from the legacy WPF flavor. If you add a file with one of these extensions (via an item template or "add existing item"), the WPF flavor would use the Resource
item type / Build action.
None
so VS doesn't need to add None Remove
<Resource Include="Resources\**\*.*" />
AndroidResourcePrefix
propertyI'm not convinced that <Resource Include=...
is a good default. <Content ...>
is a common alternative.
In fact <Content
might be preferable - it doesn't add a surprise embedded-resource into the assembly.
/cc @rladuca
My comment above was written while we were discussing this in a meeting, and doesn't really capture what we concluded.
We concluded there's not a good default for a build action / item type to use for image, Xml, and other extensions listed here, because they might be Resource, EmbeddedResource, or Content/None with CopyToOutputFolder, even in a WPF project.
The consensus was that we should fix the experience issues with None items. IE if you set the build action of a file that is in the None glob to Resource, then VS should add an include for the Resource, but shouldn’t also add a <None Remove="foo.png" />
.
Once the “None” issue is fixed, it may be fine to have the “resource-type” items listed explicitly in the project file with the appropriate build action / item type. We may also want to use a convention, such as that all files in the “resources” folder are included as resources, and all files in the "content" folder are included as content which is copied to the output folder. These conventions could either be implicit in the SDK, or explicitly part of the new project templates.
Sometimes people are surprised to hear that actually "Build Action" = "Resource" is not only for WPF projects!
@davkean wrote:
Why is WPF flavor even involved in this?
I think @davkean made an important point there. This issue is not really about WPF projects. The biggest problem is that if you make ANY .csproj that targets .NET 5 SDK (such as a non-WPF Console or ASP.NET 5 project) then "Build Action" = "Resource" fails to build correctly, whereas it did (and still does) build successfully in projects targeting .NETFW 4.8. (I tested this again today with Visual Studio 16.8.3.)
I use "Build Action" = "Resource" in multiple non-WPF .csproj's of these kinds:
In NETFW 4.8 Console .csproj's, when you use "Build Action" = "Resource", Visual Studio bundles all those resources into a .resources file named like "MyNamespace.g.resources" and stores it in an assembly manifest resource.
.resources files are not only readable in WPF apps. Any app, including Console programs, can use System.Resources.ResourceManager (alternatively System.Resources.ResourceReader) to read these resources at runtime.
System.Resources.ResourceManager
and ResourceReader
also exist in .NETFW 5.0 in the DLL System.Runtime.dll
:
C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\5.0.0\ref\net5.0\System.Runtime.dll
Note System.Resources.ResourceManager/ResourceReader
aren't located in WPF's PresentationFramework.dll
, rather they're in System.Runtime.dll
and they work without WPF.
So currently (VS 16.8.3) the situation is, although you can use ResourceManager
and ResourceReader
in NETFW 5 and NETFW 4.8 Console projects without WPF, the "Build Action" = "Resource" was broken for NET Core / 5. Even if you manually edit the XML inside a SDK/5 .csproj to make it correct, and try to build the .csproj, then the .resources file fails to be produced. Currently it only works correctly in NETFW 4.8 projects.
I would greatly appreciate this feature being restored. Currently I'm trying to update several non-WPF .csproj's to NETFW 5 (from NETFW 4.8) but these programs fail at runtime because the necessary resources are missing because Visual Studio 16.8.3 basically ignores files marked "Build Action" = "Resource" in SDK/5 projects.
I suggest renaming "Build Action" = "Embedded Resource" to "Assembly Manifest Resource" or "Manifest Resource", because that's what it actually produces. Currently the name "Embedded Resource" is confusing because both of "Build Action" = "Resource" and "Embedded Resource" produce kinds of resources that are embedded in the output .exe or .dll.
Actually all resources in an app are usually embedded in the app -- "embedded" is the general meaning of any resource in an app. So it'd be great if "Embedded Resource" could be renamed to something clear such as "Assembly Manifest Resource" or "Manifest Resource".
Where the resources show up:
"Build Action" | Where resource shows up |
---|---|
"Embedded Resource" | This actually means "assembly manifest resource". Resources of this kind show up in System.Reflection.Assembly.GetManifestResourceNames and can be read using System.Reflection.Assembly.GetManifestResourceStream. |
"Resource" | In NETFW 4.8 projects (either Console or WPF), Visual Studio bundles all files marked "Build Action" = "Resource" into a file named like "MyNamespace.g.resources" and stores it in an assembly manifest resource. At runtime, the ".resources" can be read using System.Resources.ResourceManager (alternatively System.Resources.ResourceReader). |
"Content" | Keeps the file as a standalone file. In the case of WPF apps, "Content" makes a resource/association that refers to the file, without embedding/copying the file into the ".exe". Good for very large files, and optionally-installed files. |
".resx" Resources File | A ".resx" file with "Build Action" = "Embedded Resource" and "Custom Tool" = "ResXFileCodeGenerator". If the ".resx" file is named for example "Localizations.resx" then it is compiled/built to an assembly manifest resource named like "MyNamespace.Localizations.resources". |
Currently "Build Action" = "Embedded Resource" builds correctly in SDK/5 .csproj's, whereas "Build Action" = "Resource" is broken.
A question may be raised:
Can you workaround the problem by changing all files in a .csproj to use "Embedded Resource" instead of "Resource"? No, because "Embedded Resource" (meaning assembly manifest resource) provides less functionality than ".g.resources"/ResourceManager
/ResourceReader
. For example, manifest resources lack the content type string (such as "image/svg+xml") and culture/localization abilities provided by System.Resources.ResourceManager.
RESX is a separate-but-related issue to the issue of the broken "Build Action" = "Resource".
Make a new .csproj targeting NETFW 5, such as a Console project, and use Visual Studio (16.8.3) to open the Project Properties GUI, then click "Resources" on the left, then click "Click here to create a default resources file", and then VS creates a file named "Resources.resx" in a folder named "Properties" in the same folder as the .csproj.
Alternatively, in VS 16.8.3, you can also use the template named "Resources File" to add a new ".resx" file to a .csproj, including a SDK/NETFW/5 .csproj. Visual Studio has a nice GUI/Designer for .resx files. Inside the .resx file is XML.
Although resx does not require WinForms, unfortunately currently the resx Designer/GUI in VS 16.8.3 produces resx files that do contain references to WinForms. For example:
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="DgmlGraph" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\DgmlGraph.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
It would be great if sometime the Designer/GUI for .resx could be modernized to be independent of WinForms.
Re location in the output Assembly, if the ".resx" file is named for example "Localizations.resx" then it is compiled/built to an assembly manifest resource named like "MyNamespace.Localizations.resources".
System.Resources.ResourceManager/ResourceReader
are in System.Runtime.dll
not in WPF's PresentationFramework.dll
.@verelpode It sounds like your main issue is that setting Build Action to Resource doesn't work in non-WPF SDK-style projects. I would suggest filing a new issue about that in the dotnet/sdk repo. This issue is about what the default build action should be, either when a new file is added via VS, or if a file isn't specified explicitly in the project but is in the project folder.
Thanks.
When you have a .NET Core 3 WPF project in Visual Studio 2019 and you add a .png or a .jpg file, these files have the Build Action "None". That means if you use the image with an Image element in XAML, the Image won't be displayed at runtime, as it is not available at runtime.
The Build Action should be set to "Resource" when adding such an image. This happens, if you have a WPF project with the old .csproj format.
This problem is directly related to this issue on Github: https://github.com/dotnet/wpf/issues/292
Thanks a lot, Thomas
This issue has been moved from https://developercommunity.visualstudio.com/content/problem/440436/wpf-net-core-3-sdk-styled-project-images-png-jpg-e.html VSTS ticketId: 781517 These are the original issue comments:
Thomas Claudius Huber on 30/01/2019, 09:16 PM (4 days ago): Note: This happens with SDK-styled projets. It is not directly related to .NET Core 3. When you create an SDK styled project with WPF that targets .NET Framework 4.7.2, you have the same issue that images added to the project have the Build Action "None" instead of Resource. These are the original issue solutions: (no solutions)