Embedding C++ library/exe inside .NET assembly

Often times in .NET you have to use your existing C++ library to get work done. Traditional way of doing is using Platform invoke API to access un-managed code and distribute both unmanaged library and managed code to end user. For simple applications shipping separate .NET executable and corresponding library can be cumbersome. You will lose simplicity of deployment.

Following example shows the techniques of single file deployment using binary data as resource.

.NET allows embedding any data (binary/text) as resource inside the assembly, using this technique you can create single file assembly which houses any number of binary data.

As an example, let say I have C++ library (TestLibrary.dll) which I need to use from my .NET application (MyApplication).

1. Create new .NET application MyApplication.

2. Add existing item “TestLibrary.dll” to the MyApplication. Select the properties windows by selecting “TestLibrary.DLL” in the solution explorer. Set “Embedded Resource” option for the “Build Action” property. This option enables to embed Test.dll as part of the MyApplication assembly.

3. From MyApplication main application extra DLL resource to a temporary file.

4. Load the temporary DLL to process using Win32 native Load Library function.

5. Use DLL functions from the .NET application using PInvoke.

Advantages.

1. Deployment is easier with single file executable.

2. If needed you can embed unmanaged executable inside .NET assembly and invoke from .NET using Process Start API.

3. You can invoke different executable based on the target OS. For example: By embedding both 32bit/64bit unmanaged executable , you pick executable to launch based on the target OS,

Disadvantages:

1. .NET Application size increases based on the number of resources.

2. If you want to change embedded resource you need to rebuild the host application.

Note: Similar technique can be used to embed other .NET assembly. See Jeffrey Richter Presentation

Following sample shows the how to extract unmanaged DLL from  the resource and invoke function present in unmanaged DLL.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace MyApplication
{
    static public class NativeMethods
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);


        [DllImport("TestLibrary.dll", 
        CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetString();
    }

    public static class CommonUtils
    {
        /// <summary>
        /// Loads given unmanaged library from the assembly.
        /// This allows to embed .dll file as resource inside assembly.
        /// Example: 
        /// string tempDllPath = LoadUnmanagedLibraryFromResource( Assembly.GetExecutingAssembly(),
        ///                                                         "PInvokeTest.TestLibrary.dll", 
        ///                                                         "TestLibrary.dll");
        /// </summary>
        /// <param name="assembly"></param>
        /// <param name="libraryResourceName"></param>
        /// <param name="libraryName"></param>
        /// <returns></returns>
        public static string LoadUnmanagedLibraryFromResource(Assembly assembly, 
            string libraryResourceName, 
            string libraryName)
        {
            string tempDllPath = string.Empty;
            using (Stream s = assembly.GetManifestResourceStream(libraryResourceName))
            {
                byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);

                string assemblyPath = Path.GetDirectoryName(assembly.Location);
                tempDllPath = Path.Combine(assemblyPath, libraryName);
                File.WriteAllBytes(tempDllPath, data);

            }

            NativeMethods.LoadLibrary(libraryName);
            return tempDllPath;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            string resourceName = "MyApplication.TestLibrary.dll";
            string libraryName = "TestLibrary.dll";

            // create and load library from the resource
            string tempDllPath = CommonUtils.LoadUnmanagedLibraryFromResource(Assembly.GetExecutingAssembly(),
                resourceName, 
                libraryName);
            // invoke native library function
            string output = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(NativeMethods.GetString());

            Console.WriteLine(output);
            
        }
    }
}

3 thoughts on “Embedding C++ library/exe inside .NET assembly

    • You could store the handle returned by LoadLibrary call use FreeLibrary Win32 API to unload the DLL. Once DLL is unloaded you can delete the file.

      Here is the updated native functions
      static public class NativeMethods
      {
      [DllImport(“kernel32.dll”)]
      public static extern IntPtr LoadLibrary(string dllToLoad);

      [DllImport(“kernel32.dll”)]
      public static extern void FreeLibrary (IntPtr h);

      [DllImport(“TestLibrary.dll”,
      CallingConvention = CallingConvention.StdCall)]
      public static extern IntPtr GetString();

      }

Leave a comment