# GenerateResource task does not support non-string resources on .NET core #2221

Open
opened this Issue Jun 15, 2017 · 51 comments

Projects
None yet
Member

Open

Open

Closed

Member

### amrmahdi commented May 15, 2018

 When is this planned to be fixed ?
Member Author

### nguerrera commented May 15, 2018

 I'm pretty sure this is now a must-fix for the announced .NET Core 3.0 support for Windows Forms: https://blogs.msdn.microsoft.com/dotnet/2018/05/07/net-core-3-and-support-for-windows-desktop-applications/ :) And we can't just error out and say only strings are supported. We have to actually make non-strings work.
Member

### danmosemsft commented May 15, 2018

 fyi @ericstj
Member Author

### nguerrera commented May 15, 2018

 @tarekgh wrote: you can just embed the file directly to the resources and read it with Assembly.GetManifestResourceStream. no need to miss with the resx at all. Note that this doesn't work very well if your resources are localized. You also need the logic to get the right resource for the current UI culture. ResourceManager is supposed to be the thing that handles that.

Open

Member Author

### nguerrera commented Nov 13, 2018

 I've asked this before, but I'll ask it again here. Why do we need reflection at all to go from one serialized format (resx) to another (resources)? Ignoring format details, it seems theoretically possible to defer all instantiation until runtime and just encode the resx without loss of information into the resource. Is there a limitation of the .resources format itself at play, or is it just the API we've been using to write it?
Contributor

### dasMulli commented Nov 14, 2018

 The design of .resx for non-string resources is questionable already. Currently it states "use this class for serialisation with this input parameter", the parameter being file references and the classes being inside the windows forms namespaces or system.drawing.. A "new" first-class format would be great (with xliff support), but for portability we'd need some sort of compatibility..

Merged

Open

Closed

Closed

Contributor

### rainersigwald commented Dec 13, 2018

 Extremely sloppy notes to myself from things I've figured out recently: ResourceWriter.Precanned resource exists: https://github.com/dotnet/corefx/blob/eb068ffb575e7fc561bac65b236dbbb739e4e0c7/src/System.Resources.Writer/src/System/Resources/ResourceWriter.cs#L205-L218 call via AddResourceData But getting the correct fully-qualified type from the resx xml might be a hassle, see   So the task will probably need a custom resx parser that understands that, or get a ResXResourceReader that does type-name resolution but never loads a type (somehow?)

### jnm2 commented Dec 13, 2018

 does type-name resolution but never loads a type (somehow?) Will dotnet/corefx#33201 possibly help?
Contributor

### rainersigwald commented Dec 17, 2018

 Will dotnet/corefx#33201 possibly help? I don't think so, because the problem is that in the normal current flow, the type is deserialized into a live object in memory, so the assembly that contains the type definition must be really loaded, not reflection-only loaded or metadata loaded.
Contributor

### rainersigwald commented Dec 17, 2018 • edited

 I did a sloppy prototype to learn about the feasibility of using AddResourceData: rainersigwald@9ee5773. It's super close, but doesn't quite work. Unhandled Exception: System.Runtime.Serialization.SerializationException: The input stream is not a valid binary format. The starting contents (in bytes) are: FF-D8-FF-E0-00-10-4A-46-49-46-00-01-01-01-00-60-00 ... at System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(BinaryParser input) at System.Runtime.Serialization.Formatters.Binary.BinaryParser.ReadSerializationHeaderRecord() at System.Runtime.Serialization.Formatters.Binary.BinaryParser.Run() at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(BinaryParser serParser, Boolean fCheck) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, Boolean check) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream) at System.Resources.ResourceReader.DeserializeObject(Int32 typeIndex) at System.Resources.ResourceReader.LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode) at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase, Boolean isString) at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture, Boolean wrapUnmanagedMemStream) at netcore.Form1.InitializeComponent() in S:\work\netcore_resources\netcore\Form1.Designer.cs:line 38 at netcore.Form1..ctor() in S:\work\netcore_resources\netcore\Form1.cs:line 17 at netcore.Program.Main() in S:\work\netcore_resources\netcore\Program.cs:line 19  Diffing the .resources file, left=full-framework MSBuild, right=hardcoded AddResourceData Mode: Differences Left file: S:\work\netcore_resources\examples\full\netcore.Form1.resources Right file: S:\work\netcore_resources\netcore\obj\Debug\netcoreapp3.0\netcore.Form1.resources 0000013C 00 49 00 6D 00 61 00 67 00 65 00 00 00 00 00 40 00 01 00 00 00 FF FF FF .I.m.a.g.e.....@.....ÿÿÿ <> 0000013C 00 49 00 6D 00 61 00 67 00 65 00 00 00 00 00 40 .I.m.a.g.e.....@ 00000154 FF 01 00 00 00 00 00 00 00 0C 02 00 00 00 51 53 79 73 74 65 6D 2E 44 72 ÿ.............QSystem.Dr 0000016C 61 77 69 6E 67 2C 20 56 65 72 73 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 awing, Version=4.0.0.0, 00000184 43 75 6C 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B Culture=neutral, PublicK 0000019C 65 79 54 6F 6B 65 6E 3D 62 30 33 66 35 66 37 66 31 31 64 35 30 61 33 61 eyToken=b03f5f7f11d50a3a 000001B4 05 01 00 00 00 15 53 79 73 74 65 6D 2E 44 72 61 77 69 6E 67 2E 42 69 74 ......System.Drawing.Bit 000001CC 6D 61 70 01 00 00 00 04 44 61 74 61 07 02 02 00 00 00 09 03 00 00 00 0F map.....Data............ 000001E4 03 00 00 00 05 4B 00 00 02 FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 .....K...ÿØÿà..JFIF..... 0000014C FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 ÿØÿà..JFIF..... ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 000001FC 60  = 0000015B 60  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 00004CE2 40 05 14 51 40 05 14 51 40 05 14 51 40 1F FF D9 0B @..Q@..Q@..Q@.ÿÙ. <> 00004C41 40 05 14 51 40 05 14 51 40 05 14 51 40 1F FF D9 @..Q@..Q@..Q@.ÿÙ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  Looks like a missing type header, which I bet is a result of binary serializing the object. I think the resx contains only the payload data, since it also has type information elsewhere in the XML. It's probably possible to reconstruct the payload header from the resx information directly (looks like a few length-delimited fields), but that might be more coupling with implementation details of BinaryFormatter than we care for. We could of course do what we do on full framework: use ResXResourceReader to deserialize the type and ResourceWriter to serialize it again. Edit: But note that right now ResourceWriter on core doesn't support BinaryFormatter--that was lit up for reading in dotnet/coreclr#20907 but not writing (dotnet/corefx#26745 (comment)).
Member Author

### nguerrera commented Dec 17, 2018

 I think we should avoid the deserialize, reseralize route because it's basically incompatible with cross-compilation. The lengths involved in handling different classic runtime versions for generate resource today demonstrate this. If we're really just a few header bytes away, let's ask corefx for an api that adds this envelope. I think that would address the coupling concern.
Member

### danmosemsft commented Dec 17, 2018

 @nguerrera I haven't (re)read the entire thread - but is the only reason we're not following .NET Framework verbatim, that dotnet/corefx#26745 is not done? @ericstj
Member Author

### nguerrera commented Dec 17, 2018 • edited

 @danmosemsft I don't think so. Using the exact same code as full framework msbuild (is that what you mean by following .NET Framework verbatim?), actively deserializes objects in the build only to reserialize them. I really think we should not do that. At some point, I suspect that even the full framework msbuild should avoid this. With the current approach, we cannot ever have data in a .resx that could only be used at runtime on .NET Core. Another issue with using the exact same code is that it would introduce a dependency from MSBuild -> Windows Forms, which we shouldn't have anywhere IMHO, and can't have x-plat. We would have to move the RexXResourceReader down and make it portable.
Member

### danmosemsft commented Dec 17, 2018

 @nguerrera that makes sense. I am on the lookout for BCL work necessary for this. It sounds like we haven't identified any remaining BCL requirements here, right now.
Member Author

### nguerrera commented Dec 17, 2018

 @rainersigwald was going to set something up to discuss the next steps. I don't think we can say that we don't need bcl changes for this. We just don't know exactly what we'll need yet. Even if avoiding deserialization works out, we may need API to write the blobs with appropriate header, etc. And if we don't avoid it, then we do need at least the above work item for ResourceWriter and maybe moving ResxResourceReader out of winforms.
Member

### danmosemsft commented Dec 17, 2018

 OK, let me know.

Open

Open

Closed

Closed

Open

Open

### Blind-Striker added a commit to Blind-Striker/gender-prediction-turkish that referenced this issue Jan 24, 2019

 * Back to regular embedded resource because of Microsoft/msbuild#2221 
* CI/CD pipeline with cake
* Unit Tests
 99969d5 
 fix embedded resources Microsoft/msbuild#2221 (comment) 
 804e63a