I have a 32-bit .net application that uses a native 32-bit DLL
via DllImport(). The native DLL is our internal file analysis library, and I need to use it as porting it to C# would be a problem if people update it (other software uses it).
The problem is that when I try to execute any method in the native DLL I get a System.ExecutionEngineException thrown. In fact, I've reduced the managed application to a simple tester that just calls a native method, but it still fails.
I am on 64-bit Windows 7, but that should not matter as I'm compiling everything as 32-bit binaries.
What is also interesting, when I look at the native DLL in the Dependency Walker, it shows that it can't find msvcr90.dll - but when I open any other of our native DLLs in the Dependency Walker, it can find their referenced msvcr90.dll just fine. Can there by some wrongness in the compilation of native DLL that messes up its DLL references?
OK - the problem was a little bit misty. Apparently a colleague modified the native DLL's method to contain one parameter with default value (that C++ handles just fine), but, as we know, C# 3.5 does not. After supplying a value for that parameter, everything worked fine!
Related
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
I have a DLL exception I am encountering:
response threw exception: Could not load file or assembly or one of its dependencies. An attempt was made to load a program with an incorrect format.
I have all source code for the following DLL/library combinations. I am trying to figure if I have a strange combination or what I need to check to ensure this runs. I have a native C++ code in a static library which is called by a managed C++ CLR supported DLL. Everything seems to work fine until the following point.
I created a test C# EXE console application to call the managed C++ CLR supported DLL. This works as expected. The difference where the exception is thrown when there is a C# Class library calling this same managed C++ CLR supported DLL. Is this supported at all or is this the reason why the exception gets thrown? If this combination is incorrect, is there any workaround to get a C# Class DLL to call the managed C++ CLR supported DLL.
Everything is created with Windows 7 64 bit with Visual Studio 2012. All projects are in Release mode with x64 bit platform selected.
In every case I've seen, this is where a 32-bit C# app is trying to load a 64-bit C++ or C++/CLI DLL or a 64-bit C# app is trying to load a 32-bit C++ or C++/CLI DLL.
The next step I usually take is to use Dependency Walker to load the C++/CLI dll. Dependency walker will show you what DLLs your DLL is trying to load. In some cases I've had a 32-bit DLL with the same name as a 64-bit DLL appear in the Path first, hence it tries to load the wrong DLL.
Note that Dependency Walker will show a 64 on the icon next to 64-bit DLLs and will show a message along the lines of: "Error: Modules with different CPU types were found." in the info box at the bottom
my best bet is that the c++ dll is compiled as win32 your c# dll is set to Any CPU and you are running on a 64 bit system...
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.
Premise:
Wrote a COM-callable wrapper (CCW) written in C# to be called by VB6 code.
The C# code has .NET libraries (third party) that it must utilize.
The wrapped C# class instantiates fine, raises events properly, takes method calls properly.
Problem:
The VB6 code, when running the C# code, gets an error when the C# code attempts to access the additional .NET libraries mentioned above.
Process tested:
C# wrapped code completed.
VB6 code written, references the COM dll created.
"File not found..." error received when the C# code tries to access the .NET libraries from inside itself.
Copied the third party .NET libraries into the main folder of the VB6 code (also into system32 folder).
Still "File not found..." error.
Wrote a C# Windows Form test project. Referenced the C# wrapped code.
Received the same error as the VB6 code.
In C# Windows Form test project, referenced the .NET libraries used by the C# wrapped code.
The program ran just fine.
Conclusion/Question:
Can VB6 call/use a com-callable wrapped C# program that references other third party .NET libraries?
I've done this with tons of third party libraries and as long as the third party library DLL's are in the same directory as your C# DLL's there shouldn't be a problem.
Copying them into the same directory as your VB6 code will do nothing, the effective directory of VB6 code when running the in VB6 debugger is %ProgramFiles%\Microsoft Visual Studio\VB98, so the code running will have no visibility of that.
The system32 directory has nothing to do with DotNet dll's (the only DLL's they would affect is PInvoke'd dll's and you say you add a reference so that isn't the case).
Adding the third party library to the GAC should fix things, however that is not necessarily possible/easy due to the need to sign the DLL. So just make sure the Libraries you are referencing are in the directory of YOUR library and that VB6 is actually referencing that version of your library (Debug/Release whatever what last compiled). You may want to hand RegAsm the library to make sure the correct library is Com Registered.
So to sumerize, suppose your source code looks like this:
c:\projects\vb6project
c:\projects\c#project
And your project is set to Debug, the third party libraries should be in:
c:\projects\c#project\bin\Debug
When you actually want to distribute the application, make sure that ALL the libraries are in the same directory as your VB6 exe.
This will mirror somewhat the answer by Kris Erickson.
First, for my usage which solves these problems, I did not use the GAC. Assuming that my VB6 application is in c:\program files\mycompany\vb6app.exe, I placed the COM-friendly .NET dll (lets call it net4vb.dll) in the folder with the executable. I then regsiter that dll there with RegAsm using the /codebase option. Finally, I place the .NET assembly that I'm wrapping or using (lets call it purenet.dll) in that folder as well.
At this point, vb6app.exe should run with no errors.
It is important to note that if you select the "Register for COM Interop" in Visual Studio then it will overwrite the registration you did above. So do not use this option. Stick with the command-line tools only for this.
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.