Lars Holm Jensen's Code Blog

Just another WordPress codeblog on C#, Silverlight and all things .NET

Embed managed dlls easily in a .NET assembly

with 29 comments

Here’s a very quick and dirty way to include managed dlls in your .exe-file. Just right-click your project in Visual Studio, choose Project Properties -> Resources -> Add Resource -> Add Existing File

Add all your dependencies and finally include the code below in your App.xaml.cs or equivalent.. everything else is taken care of.

public App()
{
    AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");

    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);
}

The code is a little bit more complicated than need be. But I wanted to avoid using a named namespace in order to keep the code copy-paste-ready. By the way LINQPad uses a similar method, though Joe Albahari has gone a step further and encrypted his resources.

Written by larsholm

June 15th, 2011 at 8:10 pm

Posted in .NET

Tagged with , , , , , ,

29 Responses to 'Embed managed dlls easily in a .NET assembly'

Subscribe to comments with RSS or TrackBack to 'Embed managed dlls easily in a .NET assembly'.

  1. Hello Larsholm,

    I do not understand how much. Could You spend more details?

    I have a dll C# that use another C++/CLI, how to use it with your code?

    thanks,

    Cobaia

    21 Jul 11 at 4:12 am

  2. Does only work for managed dlls, not for native c dlls unfortunately.

    Frank

    26 Jul 11 at 12:15 pm

  3. You’re right. I didn’t test this with native dlls and it does indeed not work. I will fix my post.

    larsholm

    26 Jul 11 at 9:27 pm

  4. [quote]App.xaml.cs or equivalent[/quote]
    what could be the equivalent?

    Naim ZARD

    28 Jul 11 at 10:25 am

  5. One of your constructors that are called before you use the external library. Or you can use your Main method in a Console or Forms application too, but then you have to modify the code above because the Main method is static.
    GetType().Namespace + “.Properties.Resources” will not work. It would have to be changed to “[YourNamespace].Properties.Resources”

    larsholm

    28 Jul 11 at 5:55 pm

  6. Thank you. I have written a WPF application which requires that I deploy with MySql.Data.dll. I am a bit of a minimalist and prefer the idea of having a single executable out there rather than the exe and associated 3rd party libs.

    This worked very well.

    AshRowe

    21 Aug 11 at 2:21 pm

  7. Correction, it works very well unless you are running a custom theme in Windows 7…. then it tries to resolve the PresentationFramework.Theme assembly, crashed and dies haha. Solution, take the stupid theme off, however this leads me to wonder, is there a way using the above method to resolve only a required dll, rather than every time we think we need to find a dll, call this handler?
    I’ll stop spamming your blog now :|

    AshRowe

    21 Aug 11 at 2:41 pm

  8. I’m so silly, sorry please ignore by above rants. If I’d actually taken two seconds to try and resolve the issue myself, I would have been fine :)

    It’s dirty, but by checking if the strDllName contains “PresentationFramework” and returning null if it does, I get past my issue. Thanks once again for this useful solution mate. Now I promise to stop spamming your blog.

    AshRowe

    22 Aug 11 at 2:09 pm

  9. No problem and thanks for sharing your solution.

    larsholm

    22 Aug 11 at 6:54 pm

  10. Can you please tell me how to use this technique with Windows Forms?

    Frenky

    29 Nov 11 at 2:56 pm

  11. I tried this with a console application and it doesn’t work. All of my references to classes in the dlls will not resolve. The code doesn’t compile.

    Josh

    1 Dec 11 at 10:38 pm

  12. @Josh: At compile time your project needs to have a reference to the dll.

    @Frenky: See my second comment on this page.

    larsholm

    1 Dec 11 at 11:45 pm

  13. “@Josh: At compile time your project needs to have a reference to the dll.”

    What do you mean? How do I reference it from a resource?

    Jason

    21 Jan 12 at 11:38 pm

  14. You dont need to reference the copy in the resources, just add a reference to any copy of the dll as you normally would.

    larsholm

    22 Jan 12 at 2:39 am

  15. Hi,
    Does this work for console app? I tried doing this for my console app, but when I still run the .exe file, it still throws an error, which on debug says ‘Could not load file , or assembly ‘xxxx’ …..’.

    I had added the dll as a reference to my project and also added it to my resources.

    Any suggestions?

    cheerios121

    6 Feb 12 at 7:17 pm

  16. Does anyone have an idea how to embed a Class Library from the same solution? (within the build process)
    Meaning project1 is dependent on Class Library1.
    Thanks.

    Danna

    27 Mar 12 at 6:20 pm

  17. Larsholm, Thanks for putting this up!!

    @cheerios and anyone who gets ‘Could not load file, or assembly..’ message:

    If you reference the class before AssemblyResolve event fires, you will get the error.

    Solution:
    In your main.cs, you should not reference the embedded class.
    eg: using TheEmbeddedClass; etc.
    Separate them into another class and instantiate them in main().

    Vincent

    13 Jul 12 at 10:30 am

  18. By the way, If you don’t like to use “[YourNamespace].Properties.Resources” because it’s a string, you could use typeof( MyClass ).Namespace.

    Vincent

    13 Jul 12 at 10:41 am

  19. Hello,

    When I used the solution above, I am getting the below error.

    Could not load file or assembly ‘ServiceAgent, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’ or one of its dependenciesAn expected resource in the assembly manifest was missing. (Exception from HRESULT: 0×80131532)

    My scenario is I have a DLL_1 which is using several other dlls. I added all these dependent dlls as resources and updated properties to Embedded Resource.

    I have a client application (.Exe), included DLL_1. I added following code in program.cs (.Exe)

    [STAThread]
    static void Main()
    {
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
    }

    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {

    string dllName = args.Name.Contains(“,”) ? args.Name.Substring(0, args.Name.IndexOf(‘,’)) : args.Name.Replace(“.dll”, “”);

    dllName = dllName.Replace(“.”, “_”);

    if (dllName.EndsWith(“_resources”)) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(typeof(Program).Namespace + “.Properties.Resources”, System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);

    }

    Not sure why I am getting the error. I appreciate your help.

    Thanks,
    Rao.

    Rao

    24 Jul 12 at 3:07 pm

  20. My guess would be that either the assembly has an external manifest file which it can not find (which does not trigger AssemblyResolve) or that the assembly is not a .NET assembly.

    larsholm

    25 Jul 12 at 9:00 am

  21. Hi Lars,

    Thanks for publishing this. I can’t get this to work, I’ve created a very simple solution to show what I’m doing.

    I have a DLL that has one function, called ReturnA(). All it does is return the character ‘A’. Its source code is:

    namespace ClassLibrary1
    {
    public class Class1
    {
    public static char ReturnA()
    {
    return ‘A’;
    }
    }
    }

    I then have a simple console application that just tries to call this function. As you posted, I added a reference to the DLL, and I also added it as a resource in resources/ClassLibrary1.dll. I selected “Embedded Resource” as a build action. The code for the console app is:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using ClassLibrary1;
    using System.Reflection;

    namespace ConsoleApplication1
    {
    class Program
    {
    static void Main(string[] command_line_args)
    {
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

    Console.WriteLine(“Testing to write a line before embedded DLL function is called”);
    Caller caller = new Caller();
    caller.WriteToLine();
    }

    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {

    string dllName = args.Name.Contains(‘,’) ? args.Name.Substring(0, args.Name.IndexOf(‘,’)) : args.Name.Replace(“.dll”, “”);
    dllName = dllName.Replace(“.”, “_”);
    if (dllName.EndsWith(“_resources”)) return null;
    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(typeof(Program).Namespace + “.Properties.Resources”, System.Reflection.Assembly.GetExecutingAssembly());
    byte[] bytes = (byte[])rm.GetObject(dllName);
    return System.Reflection.Assembly.Load(bytes);
    }
    }

    public class Caller
    {
    public void WriteToLine()
    {
    char foo = Class1.ReturnA();
    Console.WriteLine(foo);
    Console.ReadLine();
    }
    }
    }

    When I call this application from the command line, it doesn’t work if the ClassLibrary1.dll file isn’t in the same directory. As far as I can tell, I have followed your instructions completely. I even put the call to the DLL function in another class, just to make sure.

    I have the solution available at: http://bit.ly/P9N86L

    Thank you for any help!

    zass

    10 Aug 12 at 7:49 pm

  22. Just wanted to say: Great Work!!! Thank you!

    Nicolás

    8 Feb 13 at 5:42 pm

  23. Great! Thanks, it works well!

    DamDam

    13 Feb 13 at 3:08 pm

  24. I wanted to share this with everyone as it took me a while to figure out and I’m sure it will benefit someone else.

    First off, the code above works perfectly as is without modification. My problem was the way I was implementing it.

    I’m writing a console application and, even using this code, I kept getting a System.IO.FileNotFoundException error:

    Could not load file or assembly ‘MyEmbeddedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’ or one of its dependencies. The system cannot find the file specified.

    Following Vincent’s post above, I had created a “loader” class whose sole purpose was to instantiate another class and terminate. This way, I wasn’t “using” the embedded DLL before I tried to load it into memory.

    The problem was, the code above (as is), creates a class constructor called App. For a console application, at least, the class constructor does not get called upon launching the EXE.

    To address this, you have two options:

    1) You can modify the code above to be a static function in your “loader” class.
    or
    2) You can create a third class named something like EmbeddedAssemblyLoader. In your Main() in the Loader class, you first instantiate the EmbeddedAssemblyLoader class, then you instantiate whatever class you have that needed MyEmbeddedAssembly.

    Option 1:
    namespace MyApp
    {
    class Loader
    {
    static void Main(string[] args)
    {
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

    MyNeedyClass mnc = new MyNeedyClass(args);

    return;
    }
    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
    Debug.WriteLine(“CurrentDomain_AssemblyResolve intercepted request for ” + args.Name);

    string dllName = args.Name.Contains(‘,’) ? args.Name.Substring(0, args.Name.IndexOf(‘,’)) : args.Name.Replace(“.dll”, “”);

    dllName = dllName.Replace(“.”, “_”);

    if (dllName.EndsWith(“_resources”)) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(typeof(MyApp).Namespace + “.Properties.Resources”, System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    Debug.WriteLine(“CurrentDomain_AssemblyResolve is loading ” + dllName);

    return System.Reflection.Assembly.Load(bytes);
    }
    }
    }

    Option 2:
    namespace MyApp
    {
    class Loader
    {
    static void Main(string[] args)
    {
    EmbeddedAssemblyLoader eal = new EmbeddedAssemblyLoader();

    MyNeedyClass mnc = new MyNeedyClass(args);

    return;
    }
    }
    class EmbeddedAssemblyLoader
    {
    public EmbeddedAssemblyLoader()
    {
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    }

    System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
    Debug.WriteLine(“EmbeddedAssemblyLoader intercepted request for ” + args.Name);

    string dllName = args.Name.Contains(‘,’) ? args.Name.Substring(0, args.Name.IndexOf(‘,’)) : args.Name.Replace(“.dll”, “”);

    dllName = dllName.Replace(“.”, “_”);

    if (dllName.EndsWith(“_resources”)) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + “.Properties.Resources”, System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    Debug.WriteLine(“EmbeddedAssemblyLoader is loading ” + dllName);

    return System.Reflection.Assembly.Load(bytes);
    }
    }
    }

    John

    22 Feb 13 at 6:44 am

  25. Awesmome, thanks!

    Martin

    22 Mar 13 at 12:48 pm

  26. Vincent, thank you for tip about “using statements”. I had everything else setup correctly, the 3rd party dll added to resources, and included as reference for compile time, and a separate class to instantiate an instance of the code above. But I still kept getting an error at runtime when 3rdpartylib.dll was not in exe dir. The problem was that I had “using 3rdpartylib” in Program.cs and code references to 3rdpartylib in Main. I created a separate class in its own file, moved the using and references there (removing all direct references to 3rdpartylib from Program.cs, and now it works fine.

    Ian

    1 May 13 at 2:11 am

  27. Hi,

    The same is possible for _unmanaged_ dlls too using special tool for that which may “virtualize” some files, it’s boxedapp. Just in case.

    Mike.

    Mike_R

    25 Jul 13 at 5:09 pm

  28. Great info. I will update the post with a link later.

    larsholm

    25 Jul 13 at 5:33 pm

  29. My dll files get corrupted when i try to use them, tried to zip and unzip to destination but still no use. Any ideas?

    Marian

    19 Nov 13 at 9:52 pm

Leave a Reply

Spam Protection by WP-SpamFree