DLL Within

The idea

For a long time I have done a program that uses two party libraries. It turns out that at the exit it was at least 3 files, but I want the only one file! At that time, I’m not particularly bothered by how to do it and it remained there 3 files

Now again I pondered over this problem as much better to give a link / distribute an executive file, which will run all that is necessary, you unpack the archive, to think, where the executable file. That is not necessary here laughing, this is for programmers and other technically grammar known people showing file extensions, and a simple user names are displayed only with vague icons, come see what’s what.

Thus, we do so that could be implemented in a single file, all libraries, as well as his third parties.

Preparation

To demonstrate the technology will need at least 2 projects, let it be already familiar WinForms and ClassLibrary projects. Add a link to the project ClassLibrary in WinForms.

To see that everything is working as it should, add to a form a label and will write there the value of the class defined in the dynamic link library project.

namespace ClassLibrary {
   public class Class1 {
      public string Message = "Hello world! Yeah!";
   }
}

namespace Gui {
   public partial class Form1 : Form {
      public Form1() {
         InitializeComponent();
         label1.Text = new Class1().Message;
      }
  }
}

Compile the application and look at the output files. It should look like in the picture.

Yes, we see that we finally get 2 files. If you now remove ClassLibrary.dll, then nothing will work. We will amend it.

No, do not move a class to another project =)

Create a folder in a project GUI, where we will in some sense “keep” the required libraries. Once the folder is created (in my situation it’s Magic), add an already exist element .

But not in a quite usual way.

Магия

We find the compiled library in the folder for ClassLibrary, and add it as a reference. See the screenshot.

As a result, you should get the image below. On the file icon should be seen that this is a link.

But it’s not all. We now move on to the screen “Properties» (F4), and select in the line Build Action the value Embedded Resource

You can then go to the assembly references and indicate that the assembly ClassLibrary not copied when compiling into the final directory.

Choose ClassLibrary, press F4 and in the Properties window for the property CopyLocal change to False.

We can say that most of the work is done, you just finish a small piece of code, and only in one place. So, open Program.cs, and subscribe to an event AssemblyResolve for the current domain, before going all the core code.

private static void Main() {
   AppDomain.CurrentDomain.AssemblyResolve += LoadAssemblyFromMemory;

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

AssemblyResolve called after the application has not been able tofind a link to the required assembly, which in fact is what we want.

It now remains to implement the method LoadAssemblyFromMemory. In this method, the request for the resource as a stream, translate it into a byte array and create the basis for his library in memory. Which deliver the main domain for registration.

private static Assembly LoadAssemblyFromMemory(object sender, ResolveEventArgs args) {
   var assembly = Assembly.GetExecutingAssembly();

   var name = args.Name.Substring(0, args.Name.IndexOf(","));
   var stream = assembly.GetManifestResourceStream(string.Format("Gui.Magic.{0}.dll", name));

   var bytes = new BinaryReader(stream).ReadBytes((int) stream.Length);

   return Assembly.Load(bytes);
}

That’s all. You can now delete the library of ClassLibrary from the Bin folder , so it turned out as on the one below.

Rebuild the application, we see that now the library does not appear in the original folder, but it works!

To make sure that everything we do well and requires no further configuration change at a line class Class1, and then run the application again. At the interface shows that the line has changed!

The conclusions

Thus, we have all the advantages of separating application to libraries, the normal style of programming and only one file in the output. Setting a new library is performed only once until the end of the project.
The study met the question methods:

  • where libraries from memory to disk and then clung to the automat
  • advised to use ILMerge, but this program can not work with WPF assemblies
  • particularly perverse practices were based on reflection and a pile of constants for the methods. It is clear that you can forget about IntelliSense in this approach

That’s all what I wanted to tell you today.

Source code.

Hard’n’Heavy!

Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>