Ngen output of C# executable is not valid Win32 application - c#

I have a windows console application on C# that I'm trying to compile natively, because I need it to run on machines that don't have .Net 4.0 . I used ngen.exe and grabbed the output (myproject.ni.exe) and the DLL's, but when I copy it to another machine and try to run the exe it says it's not a valid win32 application. am I missing something?
Thanks.

Yes, NGen does not produce executable/native DLL, it does produce pre-JIT-ed code to be used with .Net assembly.
There are other tools (i.e. see Compiling C# to Native?) that may create standalone executable out of .Net assemblies, but NGen is not one of them.

Related

How to link a .so file to a managed DLL with mono

I'm writing a program for embedded linux on an ARM processor in .net that uses mono to execute. I have found that I can simply compile to either x86 or x64 architecture on my PC, copy the Debug directory over to linux, and run the program using mono myProgram.exe. The program is working perfectly like this and mono seems to take care of the architecture mismatch. This was true until today when I tried to incorporate an external native DLL.
I have both an x86 and x64 bit architecture of the external DLL and both work on the desktop environment fine. I have a shim class that uses [DllImport] to load the extern functions. However, when I try this on embedded linux with Mono I am getting a BadImageFormat exception. My guess is that Mono somehow transitions the compiled DLLs in the exe at start up but doesn't do the same for the external.
Some other info:
1. I don't have source for the native external library. I have x86, x64, and a .so library.
2. I have tried making a manage C++ shim that accesses the .so but can't get it to compile on the desktop since windows doesn't recognize the .so file.
Some thoughts:
1. Is there a way to embed the native DLL into a managed so that Mono will transition the native DLL too?
2. Can I link the .so file to a managed C++ project?
3. Is there a way to tell Mono to incorporate that Dll during execution?
Ultimately I'm looking for a solution that is wrapped in the exe that allows me to simply run it like I did before and control the native system.
If you have all the .dll and .so files for Windows and Linux, you can probably use dll maps feature of Mono. (https://www.mono-project.com/docs/advanced/pinvoke/dllmap/) which are used to map Windows dll names to Linux so names.
.Net does not recognize this, but Mono does.

How to fix 'cannot open shared object file: No such file or directory' error?

I'm trying to run a C# application in a ubuntu Docker container with mono. The application runs correctly in a windows environment. I just copied all the directories to the docker volume.
I can build the application using the following command without errors or warnings:
msbuild CSharpSampleLSV2.csproj /t:Rebuild /p:Configuration=Release
/p:Platform="x86"
But when I try to run the application using the following command:
MONO_LOG_LEVEL=debug mono CSharpSampleLSV2.exe
I'm getting some errors like this:
Mono: DllImport error loading library 'P_LSV2.DLL': 'P_LSV2.DLL:
cannot open shared object file: No such file or directory'.
I don't understand why I get this errors. The libraries are located in the same place than in the windows environment.
If more information is needed I'll provide it.
Extension ".dll" of P_LSV2.DLL library mentioned in exception hints that this is windows-specific native library you are trying to pinvoke too (DllImport suggests pinvoke). Linux native libraries almost always have extension ".so". So you are trying to invoke something from native library compiled for windows while you are on linux - this isn't going to work.
.NET compiles into IL (Intermediate Language) and that language is then compiled at runtime into native code for platform this code is executing at. In contrast to that - native library contains already compiled code for target platform. So using native library compiled for windows platform is not possible on linux.
So you need to grab that library compiled for linux somewhere. If such version is not available and source code is also not available (from source code you can try to compile for linux, though this might be not easy) - you are out of luck.

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

Compile .NET assembly into x86 machine code

Is there any way to compile a .NET assembly into native code (i.e for x86) output, that is, without MSIL.
For what I understand if you just specify x86 as architecture this would only change the PE Header to point that out to the JIT, but still the assembly will contain MSIL and will be JITTed as needed.
NGen does produce assembly files for the specified architecture but it's not a compiler, it's designed to improve performance but you do still need the original DLL, the presence of the native image only serves to avoid JIT compiling the assembly but you just can't get that native image and use it, can you?
So, is there any way to actually compile from .NET to native machine code?
Spoon Studio (was named Xenocode before) seems to be able to do that: http://spoon.net/Studio/Features.aspx
RemoteSoft also have a product but the website looks quite old: http://www.remotesoft.com/linker/
You can do this using the new precompilation technology called .NET Native. Check it out here: http://msdn.microsoft.com/en-US/vstudio/dotnetnative
Currently it is only available for Windows Store Apps. It performs single component linking. So .NET Framework libraries are statically linked into your app. Everything is compiled to native and IL assemblies are no longer deployed.

What are general steps for me to port my project to mono?

I have a dll. and visual C++ source for it. (my dll is visual c++ wraper around some ffmpeg av* libs - another precompiled dll's) while in the same solution (.sln) I have C# project that uses my dll.
what are general steps for me to port my project to mono?
Mono does not support mixed-mode assemblies on non-Windows operating systems.
Remove your C++ wrapper and rewrite your application to only use P/Invoke to call into native code.
See also: www.mono-project.com/CPlusPlus
Compile your project in Visual Studio, but enable the following compiler options:
/clr:pure: This will make a pure CLR assembly (without any x86/x86-64 asm), that should run on mono, unless you use some C runtime calls (CRT).
/clr:safe: The same as pure, but you can't have CRT references, so your project might not compile. If it doesn't, replace those function calls with other portable calls.
The resulting assembly should be pure CLR and will work with Mono.
This page contains everything you might encounter when compiling a version that works on Mono.
I would suggest also take a look at this -
http://mono-tools.com/store/
There are various tools available to help you port to Mono - you can even debug within visual studio and package it for deployment on Linux.

Categories

Resources