Retrieving file from new resource file format throws System.MissingMethodException: 'Constructor on type 'System.Byte[]' not found.'
Description
When adding a resource file after upgrading Visual Studio to 17.11.0 and adding a file resource, the new Resource Explorer is used.
Then when trying to retrieve the resource using the ResourceFileName.ObjectName syntax, a MissingMethodException is thrown Constructor on type 'System.Byte[]' not found.
Reproduction Steps
- Create a .net8 console project
- Add a Resources (.resx) file
- Double click on the .resx file to open the new Resource Explorer
- Click the + button to create a resource
- Change the type to "File"
- Click "Add existing file..." and select a file
- Close the Resource Explorer.
- The project will now fail to build with an error
MSB3822 Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references.Add the NuGet package "System.Resources.Extensions" Version="8.0.0" to resolve the error. - Reference the resource file in code i.e.
var fileBytes = ResourceFileName.ObjectName - Run the program, an exception will be thrown:
System.MissingMethodException: 'Constructor on type 'System.Byte[]' not found.'
Expected behavior
When accessing the resource file it should be returned as a byte[].
Actual behavior
An exception is thrown: System.MissingMethodException: 'Constructor on type 'System.Byte[]' not found.'
Regression?
This worked before the latest resource file / explorer changes
Known Workarounds
No response
Configuration
No response
Other information
No response
Tagging subscribers to this area: @dotnet/area-system-resources See info in area-owners.md if you want to be subscribed.
Callstack:
Unhandled exception. System.MissingMethodException: Constructor on type 'System.Byte[]' not found.
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
at System.Activator.CreateInstance(Type type, Object[] args)
at System.Resources.Extensions.DeserializingResourceReader.DeserializeObject(Int32 typeIndex)
at System.Resources.Extensions.DeserializingResourceReader._LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode)
at System.Resources.Extensions.DeserializingResourceReader.LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode)
at System.Resources.Extensions.DeserializingResourceReader.LoadObject(Int32 pos, ResourceTypeCode& typeCode)
at System.Resources.Extensions.RuntimeResourceSet.ReadValue(DeserializingResourceReader reader, Int32 dataPos, Boolean isString, ResourceLocator& locator)
at System.Resources.Extensions.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase, Boolean isString)
at System.Resources.Extensions.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase)
at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture, Boolean wrapUnmanagedMemStream)
at conRes.Resources.get_ProgramSource() in C:\scratch\conRes\Resources.Designer.cs:line 68
at Program.<Main>$(String[] args) in C:\scratch\conRes\Program.cs:line 4
So it's being treated as a Activator type resource.
Here's the relevant code in MSBuild: https://github.com/dotnet/msbuild/blob/1a51dd82a24e26b6aac68e29414182fa56fbb573/src/Tasks/ResourceHandling/MSBuildResXReader.cs#L222-L280
MSbuild is registering as activator resource: https://github.com/dotnet/msbuild/blob/1a51dd82a24e26b6aac68e29414182fa56fbb573/src/Tasks/ResourceHandling/MSBuildResXReader.cs#L279C31-L279C49 https://github.com/dotnet/msbuild/blob/1a51dd82a24e26b6aac68e29414182fa56fbb573/src/Tasks/ResourceHandling/FileStreamResource.cs#L47
That's wrong, it should be treating as byte[], but MSBuild is only treating this as a byte array if it has both System.Byte[] and mscorlib
https://github.com/dotnet/msbuild/blob/1a51dd82a24e26b6aac68e29414182fa56fbb573/src/Tasks/ResourceHandling/MSBuildResXReader.cs#L293
Here's what I see in the latest resx:
<data name="ProgramSource" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Program.cs;System.Byte[]</value>
</data>
Repro: conRes.zip
So I can workaround this by adding ,mscorlib to the resx.
<data name="ProgramSource" type="System.Resources.ResXFileRef, System.Windows.Forms">
- <value>Program.cs;System.Byte[]</value>
+ <value>Program.cs;System.Byte[],mscorlib</value>
</data>
Maybe MSBuild could broaden that check to consider this specific case of no core assembly name. @rainersigwald
Did the designer change here? @drewnoakes Here are some previous values written -- all seem to include the assembly name: https://github.com/search?q=org%3Adotnet+ResxFileRef+%2F%3BSystem.Byte%5C%5B%5C%5D%2F+path%3A*.resx&type=code
Hi, thank you for using the new Resource Explorer and for reporting this issue.
The problem is related to creating a resource of type File, where the assembly information isn't being saved in the resource file.
The good news is that the latest Visual Studio version includes a fix for this issue! You can download it from https://visualstudio.microsoft.com/vs/preview/. Let us know if you encounter other issues or have feedback on the new experience.
When can we expect this fix to be in a release?
When can we expect this fix to be in a release?
Would like to know this as well. Having the same issue.
@cmierowsky, @maot01, the fix is available in Visual Studio 17.11.1.
@cmierowsky, @maot01, the fix is available in Visual Studio 17.11.1.
Im still getting : Constructor on type 'System.Byte[]' not found. when trying to access a File saved in Resource
Like such :
var test = Resource.MyFile;
I wonder if I am missing something in here.
I followed the repro steps and I was able to run the program with no exception:
I notice that for me, the file is being saved as a System.String. If I open the Managed Resource Editor, the legacy experience (Open With > Managed Resource Editor(legacy)), it is also saved as a System.String.
If you try to change the resource type in the XML editor (Open With > XML (Text) Editor) from Byte[] to System.String, does exception still occur?
I wonder if I am missing something in here.
I followed the repro steps and I was able to run the program with no exception:
I notice that for me, the file is being saved as a
System.String. If I open the Managed Resource Editor, the legacy experience (Open With > Managed Resource Editor(legacy)), it is also saved as aSystem.String.If you try to change the resource type in the XML editor (Open With > XML (Text) Editor) from Byte[] to System.String, does exception still occur?
This does not work. I have attached an .exe file and that gets stored as byte[]. When trying to force this type to a string it results in "Resource was of type 'System.String' instead of String - call GetObject instead."
I guess in your case its saved as string since its a .cs file you have attached. In my case I need to be able to embed a .exe and be able to retrieve it at a later point.
Tried this change:
Original value:
Thanks for the clarification, @maot01. I can see the error now; I'll investigate this further and keep this thread updated.
A fix for this issue has been internally implemented and is being prepared for release, where we treat text files as System.String and other files, like .cs and .exe, as System.Byte[]. Thanks again for bringing this up! We’ll update you once it becomes available for download.
Has the fix to this issue been released yet? Now it seems with the current version of VS community (17.11.5) I cannot even attach .exe files in the new resource manager. Funny thing, it works perfectly to import them using the legacy solution (and then I can actually read the file). This seems a bit embarrassing at this point... 😅
I also have the same problem with adding fonts. There are also other problems especially with adding images. I have to correct the content of the resource files .resx and .Designer.vb to have a correct operation.
Will we soon have a new version of visual studio (17.11.6) with the essential fixes of the resource explorer?
Still having this problem in 17.12.1 with adding image files to a new resx file. Adding ,mscorlib fixes this as @ericstj suggested
Any updates on this?
