I'm using mkbundle and trying to create an embedded version of a little program IdaTester that uses Isis2. That system in turn uses features from Mono that depend on MonoPosixHelper
My problem is that mkbundle doesn't recognize the dependency and I end up with an executable that still needs to dynamically link against ~/bin/lib/libMonoPosixHelper.so, causing problems when I move this executable to a system where I don't have Mono installed. In effect, the bundle is missing one of the things it should be statically linked against.
My executable does work, but only if I make sure to run it only on machines that have the dynamic library in the "right place". This defeats the purpose of an embedded executable... I was hoping to be able to hand people this program as a kind of server they could put anywhere and launch as a binary, and obviously if they need to install the library for this to work, the server isn't exactly standalone!
I see how to force mkbundle to include any dll files the program depends upon, but MonoPosixHelper doesn't exist as a dll; this is a Linux-only library and exists only as a shared library. Does anyone know of a way to "force" the bundle to embed it statically?
In case this helps, my little compile script is as follows:
mcs -debug+ IdaTester.cs Isis.cs -r:System.dll -r:Microsoft.CSharp.dll -r:Mono.Posix.dll
mkbundle --static -o IdaTester IdaTester.exe --deps
I then run IdaTester; this works on platforms where the libMonoPosixHelper library can be found, but will fail at runtime when trying to dynamically load that library if running on a platform where libMonoPosixHelper hasn't been installed...
One needs to distribute libMonoPosixHelper.so with the application and change the dll map to make this work.
Background on the problem - Library is Loaded at Runtime
libMonoPosixHelper is not statically linked but searched for and loaded as a P/Invoke call, such as the example below:
[DllImport ("MonoPosixHelper")]
static extern int zipClose (ZipHandle handle, string globalComment);
That is, it is only requested at runtime, not compile time, and so cannot be linked in ahead of time.
Fixing it - Distributing libMonoPosixHelper.so
Four steps are required.
Copy libMonoPosixHelper to the directory you will be distributing the program with.
Update the DllMap config file to avoid a hard coded location.
Embed the config file with mkbundle
Add the path with libMonoPosixHelper.so to the LD_LIBRARY_PATH on the install machine.
To perform each:
1. Copy libMonoPosixHelper to the directory you will be distributing the program with.
libMonoPosixHelper is usually located in the lib folder, simply copy it to the folder you will be making a tarball out of.
cp $MONO_ROOT/lib/libMonoPosixHelper.so ~/MY_PROGRAM/
2. Update the DllMap config file to avoid a hard coded location.
This is the critical bit to avoid the hard coded paths issue. We need to embed a config file with mkbundle that does not specify the path. To do this, first find the mono config file, and also copy that to the local directory
cp $MONO_ROOT/etc/mono/config ~/MY_PROGRAM/config
Now we need to alter this file to remove the specific path for the dll, open it with your favorite editor and change the paths to avoid the specific prefix:
<dllmap dll="MonoPosixHelper" target="MACHINE_SPECIFIC/lib/libMonoPosixHelper.dylib" os="!windows" />
to
<dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.dylib" os="!windows" />
3. Embed the config file with mkbundle
Add the following option to your mkbundle command to embed the newly edited config file:
--config MY_PROGRAM/config
4. Add the path with libMonoPosixHelper.so to the LD_LIBRARY_PATH on the install machine.
Now you can zip up your mkbundled executable, libMonoPosixHelper.so and any other files for distribution. When unzipped and run on a machine, dlopen will now look for libMonoPosixHelper.so just like any other dll. So simply add whatever directory contains your distributed version of libMonoPosixHelper to their LD_LIBRARY_PATH environmental variable
As far as I can tell, the best option available to me is either to build a non-shared Mono library containing the same methods as are currently found in MonoPosixHelper.so, or to provide a copy of MonoPosixHelper.so as a component to be installed in the same folder as my server. Neither seems ideal: the former forces me to "reach into" the Mono distribution, which creates a longer term maintenance issue, while the latter forces me into a more complex distribution and installation mode. But it seems that once one generates a shared library, you simply can't statically link against that version of the library; the Linux loader just doesn't treat such a thing as a library in the way it handles more standard libraries.
In contrast, if I do generate a standard library from the same .o files, the loader will be happy to statically link against it, and because mxbundle ultimately runs cc and hence uses the standard ld, that option would work for me. So I guess that's the answer to my question.
Related
I coded a simple program and I compiled it with dotnet publish -c Release -r osx.10.11-x64
It creates a binary file that works well but if I move this file somewhere else without the other files in the same directory, the program can't run:
A fatal error occurred, the required library libhostfxr.dylib could not be found at /Users/me/
Is there any way to make the binary independent?
I remember on Windows and with .NET it was possible using ILMerge (but it uses .dll files, and not .dylib)
This is not possible at the moment. .NET Core is still a modular system and by deploying a self-contained application, you essentially ship a copy of the entire runtime. While it is possible to use the new linker (in preview) to reduce the size of the managed assemblies (or use ILMerge to merge all managed assemblies), there are still native assets (the .dylib) files that are reference by name in the code.
There is a different runtime project - CoreRT - which aims to create a single native executable by compiling the managed part ahead of time to machine code. This project is still under development.
Im searching for a way to make my c#.net Application portable (or at least no installation needed). Some Background: I'm developing a small File-Manager for our Customers. As not every Employee of our Customer got Admin rights I need to hold it as easy as possible to use it.
My idea was to just deliver an .exe or Zip(containing .exe + dll of .net), that all Employees can use it by double clicking.
Is there any way to "bind" the dll to the exe?
Why not just use ClickOnce deployment?
http://msdn.microsoft.com/en-GB/library/142dbbz4%28v=vs.90%29.aspx
No admin rights required... auto updating... what's not to like?
(Just deploying executables is a great way to eliminate your ability to update your clients... why do that?)
You can combine multiple .NET assemblies together using ILMerge: http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx
It's somewhat equivalent in concept to a static linker from C/C++ (except pretend that .lib files are directly executable).
Try ILMerge,
ILMerge is a utility for merging multiple .NET assemblies into a single .NET assembly
http://www.microsoft.com/en-in/download/details.aspx?id=17630
I also use this command line tool to merge several dlls and exe into single exe, use is very simple:
ilmerge /target:winexe /out:destination.exe source.exe dll_1.dll dll_2.dll dll_3.dll
In basic the program written in .net is 'portable' - you do not need to install it. (but the compatible .NET framework must be installed on client machine)
If you like to provide single assembly, you need to download and install the IlMerge utitlity (see Dai's answer) and then have either post-build command defined or I usually do a bat file with content like this:
"c:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe" /target:winexe /targetplatform:"v4,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0" /out:ALLINONE.exe PROGRAM.exe LIBRARY1.dll LIBRARY2.dll
Note, the paths depends on how it is on your system...
Also I recommend to 'obfuscate' your assembly - you can use for example good opensource utility 'ConfuserEx'
I made a WPF program which uses SQLite. And by using Visual Studio 2012, it generates both Debug and Release version exe file. When I go to Debug or Release directory and run my exe file, e.g. MultiStart.exe, it can run normally.
But if I copy the MultiStart.exe to my Desktop and try to run it, it failed.
By several tests, I found that I also need to copy files MultiStart.exe.config and System.Data.SQLite.dll to my Desktop. And then it can run now.
But why? Do we have better solution so that I can make it run without addition files?
Thanks!
Why my WPF program cannot run without Visual Studio?
The question title is not really accurate since it's not really related Visual Studio. MultiStart.exe is dependent on configuration (MultiStart.exe.config) as well as other assemblies (System.Data.SQLite.dll). Without these dependencies the application cannot run (because that is how .NET works).
WPF doesn't necessarily need a config file to run so the question is what is in your config file that the application needs. It might be possible to move this configuration information into the code (e.g. connection string) and remove the app.config but then the values will be hard coded in the application.
In terms of dependent assemblies, instead of deploying them it is possible to embed them as resources and then use the AppDomain.AssemblyResolve Event to read the assembly from a resource (see Embedding assemblies inside another assembly for an example).
Another approach instead of embedding assemblies as resources is to merge them into one assembly. ILMerge is a popular choice for merging assemblies but I read that it can have issues with WPF assemblies (not sure if that applies to you). See Merging dlls into a single .exe with wpf for some other ideas for merging assemblies with WPF.
Note that setting PATH variables does not work because .NET does not use the PATH for resolving assemblies -- see How the Runtime Locates Assemblies for the details.
Another, option instead of copying the MultiStart.exe to the desktop is to use a shortcut on the desktop that links to the appropriate directory. Perhaps that is a simpler solution
You can also use ILMerge to merge all dependencies into single .exe file to simplify distributiuon of your application.
More detaiils on ILMerge can be found here: ILMerge on CodeProject
Example of usage: ilmerge /target:winexe /out:YourDestinationApp.exe
YourCurrentProgram.exe System.Data.SQLite.dll
Better solution that i used to do with my windows form apps is, Copy the entire folder, which contains supporting files. place it where you want. then create a shortcut of your .exe on your desktop. That always worked for me.
Because you are missing some dependency. You can open your config file and set the dependency...but I wouldn't recommend you to change config file manually.
You can also copy the dependent dll in system32 folder. ..but its only a trick because exe first search dlls in current folder than system 32 folder.
Because you're missing things from your PATH. Visual Studio is probably set to copy DLLs to the target directory on build.
You're almost certainly pulling in external libraries. Some of these are part of .NET, while others are packaged in libraries in specific folders. When you start your exe, it looks in your PATH and the current folder for everything (which includes all DLLs Visual Studio copied).
When you moved the exe to the desktop, suddenly it had no idea where those DLLs are. You haven't specifically added them to your PATH, and they are no longer in the current folder. This is why copying those DLLs to your desktop magically made them work.
Unless you stop use SQLite, there is not a way for you to not need that DLL (there are lots of ways to package/reference it though).
I have two applications which will be installed by a single executable. The problem I'm facing is that one of them uses a .dll. And whenever the IExpress package tries to run the first executable it says that the .dll could not be found, even tough I added the .dll inside and outside the package.
There is any way to make it work with IExpress, which has the required characteristics?
There is any alternative to my problem, as a similar software, for instance?
This sounds vaguely similar to this question:
Iexpress is extracting to %temp% folder... How do I prevent this?
As I mentioned in my answer, check: (1) is long file name (LFN) support enabled? and (2) is the .dll actually in the archive?
If checking those things doesn't resolve it, I would use Process Monitor to see which directories the executable is searching to locate the .dll file. It should ideally be looking in the extraction directory (eg %temp%\IXP000.TMP), since that's the current directory when the executable is running.
Of course there are several other utilities that do what IExpress does that you might try instead: 7-Zip, Inno Setup, NSIS, WinRAR, WiX – just to name a few.
It's a beginners question, but...
Image of dll reference and dll included in project file http://a3.vox.com/6a00c2251e5b66549d00e398ca81eb0003-pi
If you look at the image above, there is the "Bass.Net" dll added as reference and also directly as file in the project.
Can someone tell me what's the point of doing that?
No reason, really. It could be that Visual Studio is set to display files not in the project (hard to tell from the picture) and the dll's happen to be in the main directory. The text is pretty clear that the extra files are
bass.dll
bassenc.dll
lame.exe
The .net one happens to be with the others in the same directory and you need to add it as a reference.
Within Windows, a DLL is a dynamic link library, which packages a set of programmatic functionality together. In this example, bass.dll exposes the features and functionality relevant to audio processing through this file (and any files it depends on). In order to use this functionality, you need the reference in the solution, so that Visual Studio can link it at compile time. The DLL will then typically be copied to your output directory when the application is built.
That's all that is necessary to get the code to work properly, the rest is really just preference or convention. Some people prefer to have all the files that exist in the project directory in the solution, so that the Solution Explorer reflects the file system. Typically you will want to have libraries your application depends on somewhere in your solution directory hierarchy so that the entire application is packaged together (making source code control use easier, for instance). You won't want to put this library in the BIN directory or any directory that Visual Studio generates, though, to avoid accidental deletions. In any event, having the reference is the important part, the file being in the project or solution is not necessary.
Typically, you'll want to keep external libraries out of your source directories, though, so I wouldn't actually recommend this structure. I tend to use a structure like this, but, again, this is all preference:
Source: Source code and project files
Libraries: DLLs
Support: Miscellaneous code or projects, but not actually part of the application (perhaps deployment scripts)
Having those in your project and output directory allows the final executing code to reference them without any issues running on different machines.
It sounds as it they put the reference dlls in the project directory, reference them from there, and also include them in the project. That way, when the project directory is copied, the reference dll will be copied with it. Additionally, if the reference dll is missing, the project will complain in Visual Studio.
If an assembly (Bass.Net.dll in your case) contains classes you want to use, you must add a reference to that assembly to your project.
No point the best thing to do is get all your dependenicies and store them in a seperate folder and only reference them do not copy them to your solution ;)
It's really hard to guess why someone else did something, but if I really had to guess, I'ld say that the guy thought to embed the necessary dlls as resources to be sure it was availale to the application. I have seen this technique used to embed fonts or sounds and am not sure if it works at all with dlls; but it's just a guess.
Of course the best way to be sure the files were available would have been to create a deployment project, with Visual Studio or some other installation tool loke Wise or InnoSetup, just to name a few.
This actually might be a good idea in a lot of circumstances. In my opinion their are 3 types of dependencies
Assemblies from the .Net standard library. Never include those locally.
Assemblies that you expect other developers to install as part of an MSI or exe setup package. This usually means their strongly signed and have a copy in the GAC.
Assemblies that you don't expect other developers to install via an MSI or exe installer. Maybe because you have a third party or in house library not in the GAC.
In the third case, the simplest thing to do is store a copy of the DLL in the source repo.