-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
PersistedAssemblyBuilder: unable to retrieve resources added with AddManifestResource #110686
Comments
Tagging subscribers to this area: @dotnet/area-system-resources |
Tagging subscribers to this area: @dotnet/area-system-reflection-emit |
I have this working locally after fixing some issues with the sample:
I'll create a PR to fix the alignment and add a test, plus in the docs repo update the sample to something like this: static void SetResource()
{
PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssemblyWithResource"), typeof(object).Assembly);
ab.DefineDynamicModule("MyModule");
MetadataBuilder metadata = ab.GenerateMetadata(out BlobBuilder ilStream, out _);
using MemoryStream memoryStream = new MemoryStream();
ResourceWriter myResourceWriter = new ResourceWriter(memoryStream);
myResourceWriter.AddResource("AddResource 1", "First added resource");
myResourceWriter.AddResource("AddResource 2", "Second added resource");
myResourceWriter.AddResource("AddResource 3", "Third added resource");
myResourceWriter.Close();
byte[] data = memoryStream.ToArray();
BlobBuilder resourceBlob = new BlobBuilder();
resourceBlob.WriteInt32(data.Length);
resourceBlob.WriteBytes(data);
metadata.AddManifestResource(
ManifestResourceAttributes.Public,
metadata.GetOrAddString("MyResource.resources"),
implementation: default,
offset: 0);
ManagedPEBuilder peBuilder = new ManagedPEBuilder(
header: PEHeaderBuilder.CreateLibraryHeader(),
metadataRootBuilder: new MetadataRootBuilder(metadata),
ilStream: ilStream,
managedResources: resourceBlob);
BlobBuilder blob = new BlobBuilder();
peBuilder.Serialize(blob);
using FileStream fileStream = new ("MyAssemblyWithResource.dll", FileMode.Create, FileAccess.Write);
blob.WriteContentTo(fileStream);
fileStream.Close();
var readAssembly = Assembly.LoadFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "MyAssemblyWithResource.dll"));
// Use ResourceReader to read the resources
using Stream readStream = readAssembly.GetManifestResourceStream("MyResource.resources")!;
using ResourceReader reader = new(readStream);
foreach (DictionaryEntry entry in reader)
{
Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}");
}
// Use ResourceManager to read the resources
ResourceManager rm = new ResourceManager("MyResource", readAssembly);
ResourceSet resourceSet = rm.GetResourceSet(CultureInfo.InvariantCulture, createIfNotExists: true, tryParents: false);
foreach (DictionaryEntry entry in resourceSet)
{
Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}");
}
} |
thanks very much! Santa came early :-) Kind regards, Matt |
Description
Hello,
I'm struggling to read out a resource that was added to an Assembly with PersistedAssemblyBuilder. I'm not sure if I'm doing it wrong, the documentation is wrong, or there's actually a bug.
Reproduction Steps
Given the following code (which is just the example code with 4 lines tacked on the end):
Expected behavior
I expect to be able to read the resource back out using ResourceReader.
Actual behavior
BadImageFormatException
Regression?
I tried the HEAD and the 9.0 tag, but nothing other than that.
Known Workarounds
No response
Configuration
.NET 9.0, Windows 10 x64
Other information
The example here shows how you can add a byte array as a resource. Having added that array, I'd now like to read it back out later on.
If, after writing the assembly to disk, I try and load the resource with
I receive the error
at
As far as I can tell (using dnSpy, looking at the assembly in a hex editor) the assembly contains the resource. If I modify the serialisation code to spit out a huge byte array, the size of the assembly grows accordingly, and I'm able to see the bytes in my hex editor.
When I debug the runtime I see the error is thrown here peassembly.cpp:463
specifically,
CHECK(CheckOverflow(VAL32(pDir->VirtualAddress), offset));
in pedecoder.cpp:1243CheckOverflow is passed the VirtualAddress and the offset given with
in the example code, which is over the end of the data. Looking at that, it doesn't seem that I didn't need an offset, but just passing in 0 didn't help much. I've started reading around about the PE Header - it's really interesting and great to come down from the Typescript clouds - but I think I'm out of my depth for the allotted time I have to learn to swim :-)
The text was updated successfully, but these errors were encountered: