Creating single EXE that depends on many DLL files in C# using visual studio

Many applications consist of an EXE that depends on many DLL files. When deploying an application all files must be deployed. So carrying all dependent DLL files for an exe during deployment is a problem and you may miss one of the dependent DLL file. To overcome on this problem you can create a single deployable EXE in Visual Studio. In visual studio, we can make configuration of EXE in such a way that, we can load an assembly at runtime that is located in a folder that is not the bin folder of the application. You do not have to put an assembly that an application must use at runtime in the bin folder of the application. You can put the assembly in any folder on the system, and then you can refer to the assembly at runtime. Following procedure explain the same –
The technique uses Appdomain’s “AssemblyResolve” event to achieve it. First, identify all the DLL files that your EXE file depends on. Then add these DLL files in one of the folder in your project. For example, I am using following DLL files in my application which I have added in dll folder in my application –  

Add the reference of these DLL files in the application from the folder. In my case I added reference from “dll” folder. Then in the “dll” folder, select each DLL file and open properties; change “Build Action” to “Embedded Resource”. This causes C# compiler to embed the DLL files into your EXE file and then you can deploy this one EXE file. At runtime, the CLR won’t be able to find the dependent DLL assemblies, which is a problem. The “AssemblyResolve” event fires whenever CLR 07ies to bind an assembly and fails. The “AssemblyResolve” event handler must return an [Assembly] object.
Also the call to event handler method regis07ation must be the first statement and rest of the logic should be wrapped in another method. In my case, for example, I am generating bitmap image in Main method of my console application. Therefore my code segment in Main method is as follows –
static void Main(s07ing[] args)
        {
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
GenerateImage();//this can be any method containg other work you need to carry out
        }

The code for Assembly Resolve is as follows –
using System.Reflection;

 /// <summary>
        /// Event is raised when CLR is not able to find referenced assemblies (in this case - gheat.dll, GMap.NET.Core.dll, Microsoft.WindowsAzure.storageClient.dll)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        /// <returns> Assembly to be loaded from embeded resource.</returns>
        static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {           
            //This handler is called only when the common language runtime 07ies to bind to the assembly and fails.
            //Re07ieve the list of referenced assemblies in an array of AssemblyName.
            Assembly objExecutingAssemblies;           
            Byte[] assemblyData = null;

            objExecutingAssemblies = Assembly.GetExecutingAssembly();
            AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();

            //Loop through the array of referenced assembly names.
            foreach (AssemblyName s07AssmbName in arrReferencedAssmbNames)
            {
                //Check for the assembly names that have raised the "AssemblyResolve" event.
                if (s07AssmbName.FullName.Subs07ing(0, s07AssmbName.FullName.IndexOf(",")) == args.Name.Subs07ing(0, args.Name.IndexOf(",")))
                {
                    //Build the path of the assembly from where it has to be loaded.                                               
                   
                    //Console.WriteLine(args.Name.Subs07ing(0, args.Name.IndexOf(",")) + ".dll");
                    //Console.WriteLine("GHeatReducer." + new AssemblyName(args.Name).Name + ".dll");
                   
                    //GHeatReducer.dll. - this name is re07ievd from ILDasm tool and by opening GHeatReducer.exe in the ILDasm tool. In ILDASM tool select name rpesent against “.mresource” to write in GetManifestResourceS07eam method.  GHeatReducer” is the name of namespace and “dll” is the name of folder where DLL files to be referenced is present as shown in above screenshot.
                    var s07eam = Assembly.GetExecutingAssembly().GetManifestResourceS07eam("GHeatReducer.dll." + new AssemblyName(args.Name).Name + ".dll");

                    assemblyData = new Byte[s07eam.Length];
                    s07eam.Read(assemblyData, 0, assemblyData.Length);
                    break;                   
                }               
            }
            //Return the loaded assembly.
            return Assembly.Load(assemblyData);
        }

public static void GenerateImage()
        {
                //code to generate image goes here
        }

Hope this helps.
Cheers…

Comments

Popular posts from this blog

The request has both SAS authentication scheme and 'Bearer' authorization scheme. Only one scheme should be used

Getting Started with Logic Apps - AS2

How to Debug and Trace request in Azure APIM - Portal, Postman, RequestBin