Winform/wpf development inevitably refers to many third-party DLLs, but every time you package it, you need to copy the files in the Debug directory to the customer or share them, which is not very convenient to use. I have tried several software to merge dll files before, such as ILMerge, Enigma Virtual Box, etc., but until I learned about "Costura.Fody", I felt that the world was much better~
The following is a program written by Winform, referencing the two DLLs of "HttpHelper.dll" and "Newtonsoft.Json.dll", when we generate the program, there will be an exe file and these two DLL files, which makes people feel very uncomfortable, and if there is one less DLL, the program may report an exception, as shown in the figure below:
The link below is the previous usage (not recommended)
Using the Costura.Fody tool, you can merge the source DLL into the target EXE
Project Homepage: https://github.com/Fody/Costura
How to use, directly install the nuget package:
Once you have successfully added Costura.Fody, the solution will automatically add FodyWeavers.xml file.
Regenerate the solution, you can see your success in the program generation directory, all the DLLs are perfectly merged into the exe, you can directly copy the exe file to the client to run independently. As shown below:
1>------ All rebuilds have been started: Project: itsvse, Configuration: Debug Any CPU ------ 1> Fody: Fody (version 2.0.0.0) Executing 1> Fody/Costura: No reference to 'Costura.dll' found. References not modified. 1> Fody/Costura: Embedding 'E:\project\itsvse\itsvse\HttpHelper.dll' 1> Fody/Costura: Embedding 'E:\project\itsvse\itsvse\Newtonsoft.Json.dll' 1> Fody: Finished Fody 609ms. 1> Fody: Skipped Verifying assembly since it is disabled in configuration 1> Fody: Finished verification in 3ms. 1> itsvse -> E:\project\itsvse\itsvse\bin\Debug\itsvse.exe ========== Regenerate all: 1 succeeds, 0 fails, and 0 ========== skipped
As can be seen from the above picture, the generated file does not contain Newtonsoft.Json.dll, HttpHelper.dll and Costura.dll are not generated, only two files, itsvse.exe can be run directly without errors! (The PDB file can be deleted).
Let's use the ILSpy tool to decompile our program and take a look at the generated source code, as shown in the figure below:
Introduction to the implementation principle
When the CLR tries to load an assembly but fails to load, it raises the AppDomain.AssemblyResolve event. Our program can listen for this event and return the assembly that the CLR is trying to load in the event handler so that the program can continue to function normally.
Fody.Costura embeds all the DLLs referenced by the EXE into the EXE file when building the project. When a program uses one of these DLLs during execution (the AppDomain.AssemblyResolve event is triggered because the CLR cannot find the DLL file), the required DLL is extracted from the embedded resources of the EXE file.
You can see that the Attach method listens to the AppDomain.AssemblyResolve event. When the CLR fails to load an assembly successfully, the AssemblyResolve event handler is executed. AssemblyResolve attempts to get the target assembly from the loaded assembly's embedded resource via the Common.ReadFromEmbeddedResources method and returns it to the CLR.
Seeing this, you may ask, when was the Attach method implemented?
In fact, for the C# language, the CLR hides a big trick - the CLR can execute some initialized code before each module (each assembly contains one or more modules) is loaded. Unfortunately, the C# language has no control over this part of the code. Fody.Costura injects IL code directly into the initialization function of the internal module of the EXE assembly, and this part of the IL code actually executes the Attach method. This way, once the EXE assembly is loaded, the Attach method can be called immediately.
The above is a brief introduction to the implementation principle of Fody.Costura.
Advanced configuration
These configurations are added or modified in CosturaFodyWeavers.xml files.
CreateTemporaryAssemblies Default: false This embeds the embedded file into disk before loading it into memory. This is useful for certain scenarios where you want to load an assembly from a physical file.
IncludeDebugSymbols Default: true Controls whether the .pdbs of the reference assembly are also embedded.
DisableCompression Default: false Embedded assemblies are compressed by default and uncompressed when loaded. You can turn off compression using this option. Note: Be sure to turn off this property when referencing non-standard DLLs, or encrypted DLLs. Otherwise, it will lead to the situation that the exe cannot be opened. This was discovered when I was using DSkin.dll.
DisableCleanup Default: false As part of Costura, embedded components are no longer included in the build. This cleanup can be turned off.
LoadAtModuleInit Default: true Costura is loaded by default as part of module initialization. The flag disables the behavior. Make sure you can use CosturaUtility.Initialize() somewhere.
ExcludeAssemblies How to use: ExcludeAssemblies="DLL1| DLL2" A list of assembly names to exclude from the default action of "embed all copy local references".
IncludeAssemblies How to use: IncludeAssemblies="DLL1| DLL2" A list of assembly names included in the default action of Embedding All Copy Local References.
Unmanaged32Assemblies&Unmanaged64Assemblies How to use it: Unmanaged32Assemblies="DLL1| DLL2" Unmanaged64Assemblies="DLL1| DLL2" Mixed-mode assemblies cannot be loaded in the same way as managed assemblies. Therefore, to help Costura identify which components are in mixed mode, and in which environments to load them, their names should be included in one or both lists. Do not include .exe or .dll in the name.
PreloadOrder Usage: PreloadOrder="DLL1| DLL2" Local libraries can be automatically loaded by Costura. To include a local library, include it in your project as an embedded resource called a folder costura32 or costura64 depending on the instability of the library. Alternatively, you can specify the loading order in which the preloaded libraries are loaded. When you mix temporary components from disk, they are also preloaded.
CosturaUtility How to use:
CosturaUtility is a class that allows you to manually initialize the Costura system in your own code.This is mainly for scenarios where the module initialization program does not work, such as libraries and Mono.
Finally, download the source code in the text:
Tourists, if you want to see the hidden content of this post, please Reply
|