Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieving file from new resource file format throws System.MissingMethodException: 'Constructor on type 'System.Byte[]' not found.' #9526

Open
TimSirmovics opened this issue Aug 19, 2024 · 12 comments
Assignees
Labels
Feature-Resource-Explorer The modern Resource Explorer for editing and managing RESX and RESW files. Regression Regressions from a previous (typically public) build or release. Triage-Approved Reviewed and prioritized

Comments

@TimSirmovics
Copy link

TimSirmovics commented Aug 19, 2024

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

  1. Create a .net8 console project
  2. Add a Resources (.resx) file
  3. Double click on the .resx file to open the new Resource Explorer
  4. Click the + button to create a resource
  5. Change the type to "File"
  6. Click "Add existing file..." and select a file
  7. Close the Resource Explorer.
  8. 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.
  9. Reference the resource file in code i.e. var fileBytes = ResourceFileName.ObjectName
  10. 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

Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-resources
See info in area-owners.md if you want to be subscribed.

@ericstj
Copy link
Member

ericstj commented Aug 20, 2024

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

@drewnoakes drewnoakes transferred this issue from dotnet/runtime Aug 20, 2024
@drewnoakes drewnoakes added the Feature-Resource-Explorer The modern Resource Explorer for editing and managing RESX and RESW files. label Aug 20, 2024
@drewnoakes drewnoakes added Bug Regression Regressions from a previous (typically public) build or release. labels Aug 20, 2024
@melytc
Copy link
Contributor

melytc commented Aug 20, 2024

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.

@melytc melytc closed this as completed Aug 20, 2024
@cmierowsky
Copy link

When can we expect this fix to be in a release?

@maot01
Copy link

maot01 commented Aug 22, 2024

When can we expect this fix to be in a release?

Would like to know this as well. Having the same issue.

@melytc
Copy link
Contributor

melytc commented Aug 22, 2024

@cmierowsky, @maot01, the fix is available in Visual Studio 17.11.1.

@maot01
Copy link

maot01 commented Aug 24, 2024

@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;

image

@melytc
Copy link
Contributor

melytc commented Aug 26, 2024

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:
image

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?

@maot01
Copy link

maot01 commented Aug 27, 2024

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: image

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?

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:
image
Original value:
image

@melytc
Copy link
Contributor

melytc commented Aug 27, 2024

Thanks for the clarification, @maot01. I can see the error now; I'll investigate this further and keep this thread updated.

@melytc melytc reopened this Aug 27, 2024
@melytc
Copy link
Contributor

melytc commented Aug 28, 2024

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.

@haileymck haileymck added Triage-Approved Reviewed and prioritized and removed untriaged labels Aug 29, 2024
@maot01
Copy link

maot01 commented Oct 14, 2024

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... 😅

@drewnoakes drewnoakes removed the Bug label Oct 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature-Resource-Explorer The modern Resource Explorer for editing and managing RESX and RESW files. Regression Regressions from a previous (typically public) build or release. Triage-Approved Reviewed and prioritized
Projects
None yet
Development

No branches or pull requests

7 participants