Msbuild: Generating strongly typed resource files requires non-intuitive addition of properties

Created on 19 Sep 2019  路  7Comments  路  Source: dotnet/msbuild

From https://github.com/microsoft/msbuild/issues/2272#issuecomment-532264659
cc @rainersigwald

Steps to reproduce

git clone https://github.com/PowerShell/PSScriptanalyzer
rm global.json # so that the latest version (3.0) of the SDK is used and not 2.2
cd Engine
dotnet build # should work
rm Strings.Designer.cs
dotnet build # does not work

Expected behavior

Build works

Actual behavior

Build fails due to errors resulting from Strings.Designer.cs not being created.

It seems one needs to apply the following non-intuitive changes to the Engine.csproj:

-  <ItemGroup>
+  <!-- <ItemGroup>
     <Compile Update="Strings.Designer.cs">
       <DesignTime>True</DesignTime>
       <AutoGen>True</AutoGen>
       <DependentUpon>Strings.resx</DependentUpon>
     </Compile>
-  </ItemGroup>
+  </ItemGroup> -->

   <ItemGroup>
     <EmbeddedResource Update="Strings.resx">
       <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>Strings.Designer.cs</LastGenOutput>
+      <StronglyTypedFileName>$(IntermediateOutputPath)\Strings.Designer.cs</StronglyTypedFileName>
+      <StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
+      <StronglyTypedNamespace>Microsoft.Windows.PowerShell.ScriptAnalyzer</StronglyTypedNamespace>
+      <StronglyTypedClassName>Strings</StronglyTypedClassName>
     </EmbeddedResource>
   </ItemGroup>

The StronglyTypedNamespace is due to the following in the csproj: <RootNamespace>Microsoft.Windows.PowerShell.ScriptAnalyzer</RootNamespace>
However, having to supply all the other additional parameters seems unintuitive. I'd like to see a minimal solution for a csproj that also works with VS btw.

Environment data

msbuild /version output:

OS info:

Windows 10 1809
.Net Core 3.0-rc1

GenerateResource

Most helpful comment

I was successful for a while doing this:

  <ItemGroup>
      <EmbeddedResource Update="TracerMessages.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>TracerMessages.Designer.cs</LastGenOutput>
      <StronglyTypedFileName>TracerMessages.Designer.cs</StronglyTypedFileName>
      <StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
      <StronglyTypedNamespace>Autofac.Diagnostics.DotGraph</StronglyTypedNamespace>
      <StronglyTypedClassName>TracerMessages</StronglyTypedClassName>
    </EmbeddedResource>
  </ItemGroup>

Note the LastGenOutput and StronglyTypedFileName match. Unfortunately in a recent .NET Core SDK update (I'm now running 3.1.302 on Mac) this started yielding a CS2002 warning:

CSC : warning CS2002: Source file 'TracerMessages.Designer.cs' specified multiple times [/Users/tillig/dev/autofac/Autofac.Diagnostics.DotGraph/src/Autofac.Diagnostics.DotGraph/Autofac.Diagnostics.DotGraph.csproj]

The only way to work around it was to remove the checked-in Designer.cs file and switch to the $(IntermediatePath) in the StronglyTypedFileName as seen in the initial issue comment.

  <ItemGroup>
    <EmbeddedResource Update="TracerMessages.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>TracerMessages.Designer.cs</LastGenOutput>
      <StronglyTypedFileName>$(IntermediateOutputPath)/TracerMessages.Designer.cs</StronglyTypedFileName>
      <StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
      <StronglyTypedNamespace>Autofac.Diagnostics.DotGraph</StronglyTypedNamespace>
      <StronglyTypedClassName>TracerMessages</StronglyTypedClassName>
    </EmbeddedResource>
  </ItemGroup>

This issue is the only place I've found any of this documented. It'd be nice if this was more straightforward to work with in a non-Visual-Studio (i.e., VS Code / all-command-line) environment.

All 7 comments

Team triage: I'd like to dig in on some of the changes required here. This may turn into an SDK feature to make it easier to get strongly typed resources.

Yes, please, ideally the csproj should just pick it up automatically via convention over configuration if the resx file name matches the csproj name.
Please make sure it works both from commandline and VS

@rainersigwald Any updates? Building using dotnet build works now with the described scenario but both VS and VS-Code get confused and show compiler warnings and errors (VS-Code somehow sees the class name as ambiguous and VS fails to build). Also, at runtime, I get the following exception:

MissingManifestResourceException: Could not find the resource "Strings.resources" among the resources "Engine.Strings.resources" embedded in the assembly "Microsoft.Windows.PowerShell.ScriptAnalyzer", nor among the resources in any satellite assemblies for the specified culture. Perhaps the resources were embedded with an incorrect name.

I created the following branch with my changes: https://github.com/bergmeister/PSScriptAnalyzer/tree/netcore3_resgen

Any updates @rainersigwald ? This would be good to be fixed in 3.1 as it will be LTS

I am trying to move PowerShell Core projects to the generator.
With @rainersigwald sample I was able to compile most of csproj-s but not last with UseWPF enabled.
With True resources do not generated at all if added.

I could be able compile PowerShell Core with some workarounds. See https://github.com/PowerShell/PowerShell/pull/12355

I was successful for a while doing this:

  <ItemGroup>
      <EmbeddedResource Update="TracerMessages.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>TracerMessages.Designer.cs</LastGenOutput>
      <StronglyTypedFileName>TracerMessages.Designer.cs</StronglyTypedFileName>
      <StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
      <StronglyTypedNamespace>Autofac.Diagnostics.DotGraph</StronglyTypedNamespace>
      <StronglyTypedClassName>TracerMessages</StronglyTypedClassName>
    </EmbeddedResource>
  </ItemGroup>

Note the LastGenOutput and StronglyTypedFileName match. Unfortunately in a recent .NET Core SDK update (I'm now running 3.1.302 on Mac) this started yielding a CS2002 warning:

CSC : warning CS2002: Source file 'TracerMessages.Designer.cs' specified multiple times [/Users/tillig/dev/autofac/Autofac.Diagnostics.DotGraph/src/Autofac.Diagnostics.DotGraph/Autofac.Diagnostics.DotGraph.csproj]

The only way to work around it was to remove the checked-in Designer.cs file and switch to the $(IntermediatePath) in the StronglyTypedFileName as seen in the initial issue comment.

  <ItemGroup>
    <EmbeddedResource Update="TracerMessages.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>TracerMessages.Designer.cs</LastGenOutput>
      <StronglyTypedFileName>$(IntermediateOutputPath)/TracerMessages.Designer.cs</StronglyTypedFileName>
      <StronglyTypedLanguage>CSharp</StronglyTypedLanguage>
      <StronglyTypedNamespace>Autofac.Diagnostics.DotGraph</StronglyTypedNamespace>
      <StronglyTypedClassName>TracerMessages</StronglyTypedClassName>
    </EmbeddedResource>
  </ItemGroup>

This issue is the only place I've found any of this documented. It'd be nice if this was more straightforward to work with in a non-Visual-Studio (i.e., VS Code / all-command-line) environment.

Was this page helpful?
0 / 5 - 0 ratings