Closed to-st closed 5 years ago
This is an intentional change with .NET Core SDK 3.0. As you point out, the prior versions of MSBuild on .NET Core would produce corrupted output which would crash at runtime. With the new version, it's possible to embed resources when using .NET Core MSBuild, but because they're embedded in a different way, they require a new reference to access them at runtime: System.Resources.Extensions
. This is available as a NuGet package which will be published to NuGet.org when .NET Core 3.0 is released. It's available now from a prerelease feed https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json
.
just to make sure: It is intentional that if you have a project with the new csproj format, binary resources, a PackageReference to System.Resources.Extensions and add net48 as targetframework it won't built using "dotnet build"? I do not complain that netcoreapp2.1 no longer builds broken dll ;)
I assume support for binary resources in net48 is not dropped altogether, so how should I build a project with the new csproj format for net48? Calling the msbuild from the .net framework build tools directly?
It is intentional that if you have a project with the new csproj format, binary resources, a PackageReference to System.Resources.Extensions and add net48 as targetframework it won't built using "dotnet build"?
Correct.
how should I build a project with the new csproj format for net48? Calling the msbuild from the .net framework build tools directly?
Yes: projects built using Visual Studio or MSBuild.exe
(as opposed to dotnet build
or dotnet msbuild
) use the older approach to serialize resources into the output assembly by default. It's not ideal to have the project built two different ways depending on how you launched the build, though, so I would recommend always specifying GenerateResourceUsePreserializedResources=true
in your projects and referencing System.Resources.Extensions
. That unifies on the new codepath.
I did not quite understand. What if I just want my existing project to build successfully both on machines with netcore2.1 and on machines with netcore3.0? However, I do not want to change anything, and am ready to get resources through Assembly.GetManifestResourceStream.
I solved my issue by removing of the extra lines from Resources.resx file.
What if I just want my existing project to build successfully both on machines with netcore2.1 and on machines with netcore3.0?
If your projects built successfully with the .NET Core SDK 2.1, they should work without modification in .NET Core SDK 3.0. If the projects built without errors but produced corrupt outputs in 2.1, they can be built correctly only with 3.0's new behavior.
I did not quite understand. What if I just want my existing project to build successfully both on machines with netcore2.1 and on machines with netcore3.0? However, I do not want to change anything, and am ready to get resources through Assembly.GetManifestResourceStream.
I got mad too and I was about to just rage uninstall dotnet sdk 3.0, but then it was just add
<PackageReference Include="System.Resources.Extensions" Version="4.6.0" />
to references and
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
to a property group
I have a few complaints though: GenerateResourceUsePreserializedResources is a HUGE and ugly name and also I wonder why and who would ever disable this, if it's the only way to get embed resources in SDK 3.0 to build? It looks unnecessary to add that ugly bigass name property to my csproj and the error message could have been: Hey, you just need to install System.Resources.Extensions from NuGet, we'll make the rest work. This over here is one of my biggest rants with .Net lately: Things keep breaking every time you upgrade the SDK. :\
Actually after I applied the fixes suggested NOW the application causes runtime error with Unable to load file or assembly 'System.Resources.Extensions, Version=4.0.0
I'm uninstalling SDK 3.0 because it's causing a lot more problems than it should it Installed automatically with Visual Studio update and just broke a lot of code that used to work fine when building with dotnet cli 2.2.300 and even after trying to apply the changes suggested by the SDK it still caused more problems.
Edit: except it's not possible without removing the entire Web Development from Visual Studio altogether. So because of a broken update on Visual Studio I have to completely remove non-string resources from projects because my dotnet command will just build broken assemblies otherwise.
Edit 2: Fixed by going to C:\Program Files\dotnet\sdk
and hardcore deleting 3.0.100;
Also noticed this fix won't work when targeting net45, since the System.Resources.Extensions package does not support it (minimum is netstandard2.0 which would be net461). I know net45 is old, but this app is an installer intended to run on machines that might not have any new version of .Net running (but will install net48 if needed).
@rainersigwald I just faced this issue, and while the fix with adding the package and setting the flag does work, it looks really weird that two build paths are actually different. Could this difference be mitigated or at least be transparently hidden from developers?
I'm running into this issue when trying to migrate some of our libraries with WinForm assets to using the sdk-style csproj so that it can be integrated into CI/CD using the .NET CLI. Unfortunately, while adding the package and setting the flag allows the project to build I do get the following runtime exception when it tries to load the forms icon from the embedded resource even though the System.Resources.Extensions.dll is in the bin folder.
System.IO.FileLoadException: 'Could not load file or assembly 'System.Resources.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)'
@TylerBrinkley Can you get a fusion log trace of the attempted load, to see why the .NET Runtime is rejecting the reference?
@rainersigwald I'm afraid I've moved on from this and am instead manually pulling in these resources using Assembly.GetManifestResourceStream
. This also allowed me to not be forced to update the target framework to .NET 4.6.1. Thanks for reaching out though.
@rainersigwald I've got a fusion log trace for you:
The operation failed.
Bind result: hr = 0x80131040. No description available.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Git\*******\bin\Debug\net48\*******.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = System.Resources.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
(Fully-specified)
LOG: Appbase = file:///C:/Git/*******/bin/Debug/net48/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = *******.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Git\*******\bin\Debug\net48\*******.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.Resources.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Git/*******/bin/Debug/net48/System.Resources.Extensions.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Git\*******\bin\Debug\net48\System.Resources.Extensions.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: System.Resources.Extensions, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
WRN: Comparing the assembly name resulted in the mismatch: Build Number
ERR: The assembly reference did not match the assembly definition found.
ERR: Run-from-source setup phase failed with hr = 0x80131040.
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
Also, a simple reproduction Solution
If I downgrade System.Resources.Extensions to 4.6.0 it works again.
Thanks @EamonHetherton !
I can confirm @EamonHetherton 's finding (and thank you for finding a work-around!)
When I use the latest System.Resources.Extensions
NuGet package at version 4.7.1
, compile works but runtime fails with:
System.IO.FileLoadException : Could not load file or assembly 'System.Resources.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
This makes sense (as far as fusion loader goes) because System.Resources.Extensions.dll
that gets copied to the build output directory is at version 4.0.1.0
(which isn't matching the 4.0.0.0
version rutime is trying to load):
// (from JetBrains dotPeek)
// Assembly System.Resources.Extensions, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// MVID: 52C506DF-7399-4EF0-B2DC-769C3C88FEE3
// Assembly references:
// mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[assembly: AssemblyFileVersion("4.700.20.21406")]
[assembly: AssemblyInformationalVersion("3.1.4+c4164928b270ee2369808ab347d33423ef765216")]
[assembly: AssemblyVersion("4.0.1.0")]
...
When I downgrade to System.Resources.Extensions
NuGet package at version 4.6.0
, compile works + runtime works. This time the System.Resources.Extensions.dll
that gets copied to the build output directory is at version 4.0.0.0
:
// (from JetBrains dotPeek)
// Assembly System.Resources.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// MVID: 4C478117-5922-4E23-84DD-CC9E7D793526
// Assembly references:
// netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[assembly: AssemblyFileVersion("4.700.19.46214")]
[assembly: AssemblyInformationalVersion("3.0.0+4ac4c0367003fe3973a3648eb0715ddb0e3bbcea")]
[assembly: AssemblyVersion("4.0.0.0")]
...
Is this a known issue? Can we expect a fix @rainersigwald ?
I too have run into this problem updating to .NET Core project style. Only version 4.6.0 of the extension package works at run time.
Thanks, folks! I think this is a bug in System.Resources.Extensions
and I filed https://github.com/dotnet/runtime/issues/39078 to track it. When a fix is available we can pick it up in MSBuild: https://github.com/microsoft/msbuild/issues/5504
Hi everyone. To make it clear from the beginning - the differences and details between dotnet build , msbuild and vsbuild are not my area of expertise.
I'd like to achieve a VS-independent build to easily manage build agents:
There are two more problems to achieve VS-independency:
Thanks, Patryk
@marchewek Can you please file new issues for your problems? Please be as specific as possible.
Questions I have from your comment:
vsbuild
? I'm not familiar with it.MSBuild.exe
works fine with SDK-style projects. What leads you to think otherwise?System.Resources.Extensions can work if you use a binding redirect: In the app.config add:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Resources.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="4.0.0.0" newVersion="4.0.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
You won't have to do that manually after picking up a System.Resources.Extensions
that includes https://github.com/dotnet/runtime/pull/39386.
4. Have you tried using Microsoft.NETFramework.ReferenceAssemblies to handle targeting .NET 4.5?
I am trying to release a version of a library for .Net Framework 4.5 besides .Net Core 3.1 and .Net 5, can you explain this in more detail? Simple usage doesn't work:
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
C:\Users\runneradmin\AppData\Local\Microsoft\dotnet\sdk\5.0.100\Microsoft.Common.CurrentVersion.targets(3075,5): error MSB3823: Non-string resources require the property GenerateResourceUsePreserializedResources to be set to true. [D:\a\HtmlEditorControl\HtmlEditorControl\src\WinForms\Framework Extensions\Framework Extensions.csproj]
C:\Users\runneradmin\AppData\Local\Microsoft\dotnet\sdk\5.0.100\Microsoft.Common.CurrentVersion.targets(3075,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references. [D:\a\HtmlEditorControl\HtmlEditorControl\src\WinForms\Framework Extensions\Framework Extensions.csproj]
- Have you tried using Microsoft.NETFramework.ReferenceAssemblies to handle targeting .NET 4.5?
I am trying to release a version of a library for .Net Framework 4.5 besides .Net Core 3.1 and .Net 5, can you explain this in more detail? Simple usage doesn't work:
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
C:\Users\runneradmin\AppData\Local\Microsoft\dotnet\sdk\5.0.100\Microsoft.Common.CurrentVersion.targets(3075,5): error MSB3823: Non-string resources require the property GenerateResourceUsePreserializedResources to be set to true. [D:\a\HtmlEditorControl\HtmlEditorControl\src\WinForms\Framework Extensions\Framework Extensions.csproj] C:\Users\runneradmin\AppData\Local\Microsoft\dotnet\sdk\5.0.100\Microsoft.Common.CurrentVersion.targets(3075,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references. [D:\a\HtmlEditorControl\HtmlEditorControl\src\WinForms\Framework Extensions\Framework Extensions.csproj]
In your projects PropertyGroup set
<PropertyGroup>
....
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
</PropertyGroup>
If the other is still giving issues one could use GeneratePathProperty=true on the nuget package and then reference the dll directly:
<ItemGroup>
<Reference Name="System.Resources.Extensions" Include="$(Microsoft_NETFramework_ReferenceAssemblies)\lib\NET45\<<NameofDLL>>" />
</ItemGroup>
If the other is still giving issues one could use GeneratePathProperty=true on the nuget package and then reference the dll directly:
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net45" Version="1.0.0" GeneratePathProperty="true">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<Reference Name="System.Resources.Extensions" Include="$(PkgMicrosoft_NETFramework_ReferenceAssemblies_net45)\build\.NETFramework\v4.5\Facades\System.Resources.ResourceManager.dll" />
I am trying this. But the package does not contain anything suitable other than System.Resources.ResourceManager.dll. Anyway, I get the same errors:
2>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(3075,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references.
@HavenDV That was in reply to https://github.com/dotnet/msbuild/issues/4704#issuecomment-660149373 which reported some different issues. If you get this error
2>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(3075,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references.
you need to add
<PackageReference Include="System.Resources.Extensions" Version="5.0.0" />
to your project file.
If the other is still giving issues one could use GeneratePathProperty=true on the nuget package and then reference the dll directly:
<ItemGroup> <Reference Name="System.Resources.Extensions" Include="$(Microsoft_NETFramework_ReferenceAssemblies)\lib\NET45\<<NameofDLL>>" /> </ItemGroup>
@gooterz nit: System.Resources.Extensions
is not in the reference assemblies, only its own package.
@HavenDV That was in reply to #4704 (comment) which reported some different issues. If you get this error
I'm looking for a way to add .Net 4.0 and .Net 4.5 targets to a multi-target project. .Net 4.6.1, .Net Core 3.1 and .Net 5 work fine.
@HavenDV Ah, I see. Since System.Resources.Extensions
only has .NET 4.6.1 and .NET Standard 2.0, it can't be used there. You can build a project that multitargets to older .NET versions with MSBuild.exe
, but not with dotnet build
.
@RusKnyaz
I solved my issue by removing of the extra lines from Resources.resx file.
What extra line did you remove? I'm having the same problem :-/
Do I really need to create the 'resources.resx' for embedded resources to work ? I presumed they would just work by setting them on the .csproj
. Is that the expected behavior ? can someone confirm it for me, please ?
I circumvented the problem by removing the reference to the System.Resources.Extension
NuGet package.
To get the project to build after that, I had to set GenerateResourceUsePreserializedResources
to false
.
This made the project work fine, though I lost the localized ressources in the generated NuGet.
I didn't find a solution for that, but fortunately I had just a few texts localized, so I changed to using a dictionary instead - suboptimal, I know, but after all this time consuming trial & error I was short on time, and I had to get a working solution fast, so yeah... this is where I ended up :-/
This problem still cause with .NET 6 Multi Platform
We have a few projects that muti target .net core and the old fashioned .net framework. Some of these include binary resources (mostly images). With .net core 2.1 / 2.2 they build successfully but accessing an image while running under .net core throws an exception while with the full framework everything continues to works. Now .net core 3.0 added support for binary resources giving us the chance to eliminate a few workarounds. But now TargetFramework=net48 fails to build. As we are still in the transition to .net core and most of our products (still) require the full framework. Therefore this blocks any usage of .net core 3.0 in our codebase.
Steps to reproduce
unzip the attached project and run "dotnet build" or "dotnet build -p:TargetFramework=net48". Note that "dotnet build -p:TargetFramework=netcoreapp3.0" builds successfully.
LibraryWithImage.zip
Expected behavior
Successful build - net48 definitely supports images inside .resx
Actual behavior
Environment data
SDK 3.0.100-preview9-014004 installed using the installer (see https://dotnet.microsoft.com/download/dotnet-core/3.0 )