23

Is it possible to add/remove/change an embedded resource in a .NET DLL after it has been compiled? If so, how is this done, and are there any gotchas?

Edit:

I would like to do this manually, but eventually automatically through a script in the post-build event.

Mas
  • 4,546
  • 5
  • 39
  • 56

3 Answers3

22

Its so easy, just 3 lines of code. What you need is to reference mono.cecil.dll (google it!) and:

var targetasmdef = AssemblyFactory.GetAssembly("My.dll");
//May seach for the one you need
targetasmdef.MainModule.Resources.RemoveAt(0);
AssemblyFactory.SaveAssembly(targetasmdef, "My2.dll");
dexit2k
  • 373
  • 3
  • 6
  • 6
    I've written a small program that can replace embedded resources: https://github.com/qerub/ReplaceEmbeddedAssemblyResource – qerub Feb 12 '13 at 13:38
  • ```AssemblyFactory.GetAssembly``` was removed. Use ```AssemblyDefinition.ReadAssembly``` – PeterB Feb 08 '19 at 13:05
21

There's no way to do this in managed code. Once a resource has been embedded it becomes part of the assembly just like the compiled MSIL code is.

However, you could do this manually, like suggested by Lucero, by disassembling the DLL into a text file using ildasm, removing the resource using a text editor, and finally reassembling the DLL using ilasm.

Here's an example using a DLL with a single embedded text file:

1) Decompile the DLL into MSIL:

ildasm MyLibrary.dll /out=MyLibrary.il

2) Open the resulting MyLibrary.il file and remove the .mresource section:

.mresource public MyLibrary.MyResource.txt
{
  // Offset: 0x00000000 Length: 0x0000000F
  // WARNING: managed resource file MyLibrary.MyResource.txt created
}

3) Reassemble the DLL from the modified MyLibrary.il file:

ilasm MyLibrary.il /dll
Community
  • 1
  • 1
Enrico Campidoglio
  • 56,676
  • 12
  • 126
  • 154
  • I've been running into problems with the embedded licenses with 3rd party libraries. When we embed the license in our library, it depends on the specific version. I wanted to be able to create 2 versions of the assembly, one without the license, one with the license. – Mas Jul 01 '11 at 09:46
  • @Enrico - any reason you can think why Lucero's solution isn't possible? – Kieren Johnstone Jul 01 '11 at 09:47
  • @Kieren I thought @Mas meant programmatically. The manual way suggested by @Lucero works. I added a link to his answer and provided an example. – Enrico Campidoglio Jul 01 '11 at 11:06
  • 2
    @Enrico, nothing prevents you from programmatcially doing the same thing `ILDASM` and `ILASM` do... also, your instructions for the manual process are not complete. For disassemblation, you should add `/utf8 /typelist /all`, and for re-assembling `/resource=MyLibrary.res`. – Lucero Jul 01 '11 at 12:18
  • @Lucero How would that be done programmatically? I've tried out the instructions using a sample Console app with an embedded text file and it works. Those instructions are meant to be just an example. Other scenarios would need a different set of arguments. – Enrico Campidoglio Jul 01 '11 at 12:31
  • @Enrico, ILASM and ILDASM are programs as well, which proves that it can be done programmatcially. Anyways, you could for instance try to do this by using reflection and saving and loading the IL bytes you should be able to programmatically rebuild the assembly, or by using Mono.Cecil etc. Regarding the set of arguments, `/utf8` is required to make it independent of the local character set (since the default is ANSI), `/typelist` preserves the type order (which may be relevant), and `/resource` makes sure that the DLL resources (such as application icons etc.) is carried over. – Lucero Jul 01 '11 at 12:40
  • Thanks for the info guys, this was quite helpful. – Mas Jul 01 '11 at 12:47
  • @Lucero Thanks for the clarification. When I said "programmatically" I was indeed meaning "in managed code" :) – Enrico Campidoglio Jul 01 '11 at 13:08
6

Yes, this is possible, by doing a roundtrip with ILDASM and ILASM, replacing the embedded files inbetween.

Gotchas:

  • you need the strong name key file if the assembly was strong-named, or you'll not get the same assembly name in the end
  • if the assembly was signed with a certificate, you need the certificate including the private key to re-sign it if needed
  • obfuscated assemblies may fail to roundtrip due to name issues
Lucero
  • 59,176
  • 9
  • 122
  • 152