views:

266

answers:

2

Is there any detailed guide on how to use a resource embedded dll within a c# source? All the guides I find on Google don't seem to help much. It's all "make a new class" or "ILMerge" this and ".NETZ" that. But I'm not sure on how to use the ILMerge and .NETZ stuff, and the guides on classes leave out what to do after making the class file, since I find nothing new after doing so. For example, this. After adding the class and function, I have no idea on how to reach out to get the dll from my resources.

So, to be specific, what I'm looking for is a guide on how to use a .dll file that was embedded into Resources to be able to call a class, without and parts left out. Please keep in mind that I am not very experienced with C# coding. Thanks in advance. :D

PS. Try not to use those big words. I tend to get lost easily.

+1  A: 

You can get a Stream to the DLL using Assembly.GetManifestResourceStream, but in order to do anything with it you'll either need to load it into memory and call Assembly.Load, or extract it to the file system (and then quite possibly still call Assembly.Load or Assembly.LoadFile, unless you've actually already got a dependency on it).

After loading the assembly you'd have to use reflection to create instances of classes or call methods etc. All of this is quite fiddly - and in particular I can never remember the situations in which to call the various overloads of Assembly.Load (or similar methods). Jeff Richter's "CLR via C#" book would be a useful resource to have at your desk.

Could you give more information about why you need to do this? I've used manifest resources for various things, but never to include code... is there any reason you can't ship it alongside your executable?

Here's a complete example, albeit without error checking:

// DemoLib.cs - we'll build this into a DLL and embed it
using System;

namespace DemoLib
{   
    public class Demo
    {
        private readonly string name;

        public Demo(string name)
        {
            this.name = name;
        }

        public void SayHello()
        {
            Console.WriteLine("Hello, my name is {0}", name);
        }
    }
}

// DemoExe.cs - we'll build this as the executable
using System;
using System.Reflection;
using System.IO;

public class DemoExe
{
    static void Main()
    {
        byte[] data;
        using (Stream stream = typeof(DemoExe).Assembly
               .GetManifestResourceStream("DemoLib.dll"))
        {
            data = ReadFully(stream);
        }

        // Load the assembly
        Assembly asm = Assembly.Load(data);

        // Find the type within the assembly
        Type type = asm.GetType("DemoLib.Demo");

        // Find and invoke the relevant constructor
        ConstructorInfo ctor = type.GetConstructor(new Type[]{typeof(string)});
        object instance = ctor.Invoke(new object[] { "Jon" });

        // Find and invoke the relevant method
        MethodInfo method = type.GetMethod("SayHello");
        method.Invoke(instance, null);
    }

    static byte[] ReadFully(Stream stream)
    {
        byte[] buffer = new byte[8192];
        using (MemoryStream ms = new MemoryStream())
        {
            int bytesRead;
            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, bytesRead);
            }
            return ms.ToArray();
        }
    }
}

Building the code:

> csc /target:library DemoLib.cs
> csc DemoExe.cs /resource:DemoLib.dll
Jon Skeet
Well, I understood nothing but the "why I wanted this" part. I wanted to include a dll file to call a function, but not want the dll to be copied to the machine. Basically an all-in-one package.
Kevin
@Kevin: If you don't understand any of this, then you may need to do more .NET coding before you're really ready to do it. Even if you can get some code working based on my example, you may find it hard to maintain. Just how badly do you want to avoid copying the DLL?
Jon Skeet
Really badly..?
Kevin
Then I suggest either reading the docs of ILMerge, or buying CLR via C# :)
Jon Skeet
@Jon -I think the reason most of us are looking to do this is, at least in my case, is to build a single *.dll for licensing protection that can be embedded into multiple *.dll Add-ins for various products we develop. I'm re-researching this now because I'm trying to take an Add-in I wrote public, and I do a lot of this same development, so having a single *.dll to embed into various Add-ins is a much better code reuse vs. copying *.cs files into each of our projects.... it also makes it a bit more interesting from a "code hiding" perspective. makes someone have to think more :)
Richard B
+1  A: 

You might need to use ILMerge. Looks like it will solve the problem naturally for you.

http://research.microsoft.com/en-us/people/mbarnett/ILMerge.aspx

Charles Prakash Dasari
Well, the problem is, I have no idea how to use it. Got a guide?
Kevin
There are instructions installed with the tool.
Jon Skeet
Refer the target assembly in your code and then call your function as usual. Later you can merge both these assemblies into one using ilmerge. You can use the tool as follows:ilmerge /t:library /closed /internalized /out:newdll.dll lib1.dll lib2.dllYou can read the further instructions on the command line help or the attached instructions as Jon pointed out.
Charles Prakash Dasari
After a couple googles of 'how to use ilmerge', it seems that ILMerge just merges dlls together so that you're left with 1 dll that you can call all functions from? If so, I'm trying to make it so that I can merge the exe and dll together while being able to also call the functions inside the dll.
Kevin
I believe there is no such restriction with ILMerge. If your end product is an EXE file, then you would use "ilmerge /t:exe ..." instead of the above syntax. Why don't you just try it and check out if it works?
Charles Prakash Dasari