How I make a single-executable with System.Data.SQLite merge? - c#

My application includes SQLite.dll. How I make a single-executable application in C# WPF without installing via ClickOnce Application or any installation file setup.
How can I bundle System.Data.SQLite into my project so I can produce a single-executable application with no tag-along DLLs?

for the System.Data.SQLite.dll assembly you can embed it as a resource and then use Reflection.Load from the resource before it's used by any of your code so it's ready to go. Or handle when AssemblyResolve is called, then you load it from the resource.
With the SQLite.Interop.dll thats the hard part because it actually makes all the calls to the SQLLite C++ libraries, and the method used by the System.Data.SQLite assembly makes calls to the correct DLL based on X86 or x64. You could possibly couple the 1st part of this with this article to create a memory based load of the 2nd DLL but you'd need to replicate the initial checks for x64/x86 and .NET dll performs and then load the correct one. (You'd just embed both and load the correct one)

Related

How do .NET Framework classes reference native Windows DLLs without becoming bitness-specific?

I've read many questions and answers indicating that if I want to link my C# project against native libraries, I can't use AnyCPU platform target but must make separate 32- and 64-bit builds, each linked against the native DLL of the appropriate bitness.
This makes me wonder how the .NET Framework assemblies themselves are, or at least appear to be, built for AnyCPU. That is, when adding a reference to my GUI application, why don't I have to pick the 32-bit or 64-bit version of System.Windows.Forms? I thought this might just be some Visual Studio magic that would resolve to the appropriate GAC subdirectory (GAC_32 or GAC_64), but I searched for System.Windows.Forms.dll in the GAC and found it in:
C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll
Note the "GAC_MSIL". So how does this DLL manage to wrap a native 32-bit API yet remain linkable in a 64-bit application? And why can't I use a similar strategy to make a single C# DLL that links against a native 32-bit library yet remains runnable in 64-bit mode?
Option 1: In GAC you may register 2 versions of assembly one 32 and one 64 bit with exactly same names. Oracle DB Driver for .NET uses this strategy.
Option 2: With your assembly that will be AnyCPU deploy two versions of native DLL and choose proper DLL at runtime (SQLite works like that). As it turns out .NET Framework is intelligent enough to load proper version of native DLL via P/Invoke (Using a 32bit or 64bit dll in C# DllImport)
I had the same problem and ended up using Fody Costura
DLL Files will be shipped as embedded ressources and the lib takes care of the bitness.
You could find an example for SQLite here
The problem I have encountered was that your application needs to have access to the Windows Temp folder to create the assemblies from the ressource. If you dont need it, you could disable it using a config setting createtemporaryassemblies

Use Of Same dll file in all .Net Applications

I have ConsoleApplication01, ConsoleApplication02, ConsoleApplication03 and using "Mydll.dll" for accessing database.
I want to keep all "exes" of all Console Applications in one folder to run using windows service. So problem is that, Its asking to replace "Introp.Mydll.dll" into my destination folder.
Will it work by Replacing this file "Introp.Mydll.dll".
If its exactly the same dll (same binary) than there is no problem.
If you are using different versions for each application (and there is a good chance you should, or at least be able to, to allow upgrading the version only for a single service), you can use GAC mechanism.
GAC is sort of a centralized storage of a lot of dll's used by .net, and its uniqueness is that you can publish a lot of dll's with the same name that will have different versions or different globalization culture. That way your C# services will find the dlls and load them automatically from GAC, and if you will require to upgrade the dll just for one service, you will only change this reference to point to the new specific version.
You can read about GAC here:
https://msdn.microsoft.com/en-us/library/yf1d93sz(v=vs.110).aspx
and how to install assembly (dll) into GAC here:
https://msdn.microsoft.com/en-us/library/dkkx7f79(v=vs.110).aspx

How to bundle native DLLs with a managed application?

On a .NET project, I have a couple of functions imported from native DLLs.
Currently to add the native DLLs to the project, they are copied to the root of the C# project and their property Build action is set to Copy to output directory.
Is there a better workflow for bundling native DLLs?
One option, which is particularly useful if you want single exe deployment, is to embed the DLL(s) into your manifest as Resources. This is a similar approach to what is often used to create "universal binaries" which can run on either X86 or X64 platforms from a single file. In that case you embed the 64-bit version inside the 32-bit version and extract it at runtime when needed. You can see that in action with the Sysinternals binaries.
In your case, you would embed a native binary within the managed executable, then either load it as an IO stream at runtime or extract it and reference it from the extracted path. In either case, you never have to worry about "losing" the resource because it's part of your project.
If you decide to go that route, the answer to how to do it has been provided several times over. Here's one such question:
Embedding unmanaged dll into a managed C# dll

Loading DLLs with Microsoft Visual C# 2010 Express

I'm using Microsoft C# 2010 Express with the FrameLink Express drivers from Imperx. When I try to load the DLL at runtime, I get an exception:
Unable to load DLL 'VCECLB.dll': The specified module could not be
found. (Exception from HRESULT:0x8007007E)
If I try to add the DLL as a reference, I get this message:
A reference to 'C:\\VCECLB.dll' could not be added. Please
make sure that the file is accessible, and that it is a valid assembly
or COM component.
Two questions:
Is this an Express problem (i.e. some limitation with Express causing the problem)? I believe the source for the DLL is written in C++, but I wouldn't think that would matter.
Is there a different way to reference the DLL and/or add it to the project? Something I'm doing wrong?
Finally, I've tried adding both the x86 and x64 versions, debug and release. Same failure to add as a reference every time.
That DLL doesn't seem to be .NET (nor COM) code - therefore you cannot load it, nor add a reference to it.
Doesn't have anything to do with your Express version - it's just not a .NET "compatible" DLL and thus you can't load or reference it.
In order to use its functionality, you'll probably have to dive into more "arcane" (and more elaborate and more complicated) methods of calling raw C++ code from .NET - or find a .NET compatible counterpart or version of it.
Actually, the answer appears to be in the first line of the message:
Unable to load DLL 'VCECLB.dll': The specified module could not be found. (Exception from HRESULT:0x8007007E
It says it cannot find the DLL, not that the DLL is not compatible.
The DLL should be located with the other DLLs with your program, and you need to add the DLL to the solution.
If by some chance the DLL is compiled as Native C/C++ (i.e., Not .NET style), it can be called from a C/C++ that is a .NET style, but not a C# routine.
So, if the problem is that the module can be found but not loaded, you need to write a C++ (.NET) routine to call from your C# routine (.NET) to call the C++ (Not .NET).
All code that talks directly to hardware must do this at some level. Most do this for you using multiple DLLs.

Understanding IlMerge - how to pack an executable with all it's associated dll's

I know I'm not the first person to ask this question on Stack Overflow and I'm sure I won't be the last. But, after spending hours researching how to do this and then physically trying to do it, I'm near ready to give up.
I have a .NET Framework 4, C#, WinForms application that builds to an executable. I rely on many many many dlls. The dlls fall into multiple categories.
Libraries I have written with no dependencies of their own
Libraries I have written with dependencies on other libraries I've written
Libraries I have written with dependencies on third party dlls
Third party stand alone dlls
Third party dlls with their own dependencies on other dlls
So after I compile my application I have a directory with an executable and approximately 15 dlls.
I want to pack all the dlls into a single executable so that I can simply distribute a single executable.
I know that IlMerge is the typically suggested application to use for this, but I'm curious if there is something easier to use that is more intuitive and works accross both WinForms and WPF.
The problem here is that ILMerge only can merge .Net assemblies. Your file lame_enc.dll isn't a .Net assembly but a standard Windows dll and therefore can't be loaded by ILMerge.
To get around this you could embed lame_enc.dll in your assembly and then extract it when needed in your application. Check out this article for more info on that.
http://weblogs.asp.net/ralfw/archive/2007/02/04/single-assembly-deployment-of-managed-and-unmanaged-code.aspx
In the end, I went an entirely different direction.
I decided to use the Costura Visual Studio Extensions located here.
These extensions use a combination of two methods
Jeffrey Richter's suggestion of using embedded resources as a method of merging assemblies
Einar Egilsson's suggestion using cecil to create module initializers
What's nice here is that you simply install the extensions into Visual Studio. After doing that, for any project where you want to pack your DLLs into a single executable, simply select the project, click Project on the menu bar, Costura, Configure, and then OK. It will ask you to reload the project - click yes. Now whenever you build the project it will create just a single executable (or DLL if you are doing it on a library). Couldn't be more easy.
ILMerge only combines pure (not mixed-mode) CLR assemblies. It works by extracting all of the CIL modules and then relinking them into a single new assembly. Assembly resources are also recombined.
ILMerge cannot merge native executable code. lame_enc.dll is a native DLL file and does not contain any CIL modules, that's why you can't combine it.
If you want to pack your application into a single executable a workaround is to include lame_enc.dll as an assembly resource, then save lame_enc.dll to disk in a temp folder perhaps, and add the folder it was saved in to your application's PATH, so your [DllImport] runtime linker will be able to access it.
To address your exact issue, verify that the file C:\Release\lame_enc.dll exists and that it is in fact a .NET file. ILMerge can only merge .NET assemblies.
Now if you are only worried about distribution of your application, you may consider creating an installer to install all of the binaries, and not worry about merging them using ILMerge.
Another alternative to using ILMerge is to embed the binaries in an assembly as desribed here.

Categories

Resources