code is here https://github.com/Layty/cppnetdll
I have check the cpp dll and c# all is on x86, my pc is x64 ,I have also use both cpp and C# with x64
but it still tell me like
Unhandled exception. System.BadImageFormatException: Could not load file or assembly 'DLLMYX86, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. 试图加载格式不正确的程序。
File name: 'DLLMYX86, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' ---> System.BadImageFormatException: 试图加载格式不正确的程序。 (0x8007000B)
at MYNETX86.Program.Main(String[] args)
In .NET when you compile a managed assembly the compiler generate a intermediate code which is then compile at the fly by the JIT (just in time compiler) for the machine architecture where you are running your application.
A native (C++) dll is compiled for a specific architecture (could be x86 or x64) and the binary image file is specific for that architecture.
If you want to use a native dll from a .NET app you have to be sure that the JIT compiles the code for the same architecture the native dll was made for. The only way to be sure that everything is coherent is to compile the .NET assembly for that specific architecture. In Visual Studio this is possible switching the target architecture from Any CPU to the same of the native dll.
Your native dll is referenced as a regular managed dll. This will not work. Your options are
Rewrite the functionality in managed code
Use C++/CLI to produce a managed dll
Use PInvoke to call a native dll
I would prefer option 1 if possible. Interacting with unmanaged code is kind of a pain in the ass for anything except the most trivial signatures.
Your C# project targets .Net Core 3.1, so you need update your C++ project to target the same version.
In Project Properties > Advanced > C++/CLI Properties.
Set Common Language Runtime Support to .Net Core Runtime Support (/clr:netcore), then click Apply.
Set .Net Target Framework Version to netcoreapp3.1 or .NET Core 3.1.
I have solve this problem. I remove the pch.h and the pch.cpp and dllmain , then every thing run well .
But I dont know why ? it is just pre combile , and I have clean obj dir and clean project befor .
I have update my git code . just fix https://github.com/Layty/cppnetdll/blob/master/DLLMYX86/DLLMYX86/dllmain.cpp
or del this file.
I have make other both include cpp and C# .
othrs if have problem can download it. it works well
now I can new cpp object in c#
Related
I have a solution that contains C# and managed C++ projects.
It compiles in the solution platform x64 and x86. Since it is managed C++ I wanted to create a 'Any CPU' solution and get rid of the old ones.
I changed the C++ project linker settings to Force Safe IL Image for both x64 and x86.
Next, using the Configuration Manager, I created a new solution platform called 'Any CPU'. Next I added a project platform also called 'Any CPU'.
I proceeded to set all the C# projects to 'Any CPU', but for the C++ I can't do that. The project platform 'Any CPU' is not in the drop down, and there is also no option 'New...'.
VS is adement about it, so I kept it like it was and started a build. To my surprise the result DLL (from the C++ project) was MSIL even though the platform for C++ was x64. Same happens when compiling x32, the resulting DLL is in MSIL.
What gives?
Why can't I set the C++ project to 'Any CPU'?
As far as I know, you cannot create an "AnyCPU" project type in Visual Studio for a C++/CLI project. However, you can configure your C++/CLI project (under the "Win32" project type) so that it compiles as pure, safe MSIL, without a target platform. Doing so will allow your C++/CLI DLL assembly to be used with an "AnyCPU" C# project. I.e. it's effectively "AnyCPU", even though that's not its actual name in the Configuration Manager.
In the "C/C++" project settings:
Common Language RunTime Support: Safe MSIL Common Language RunTime Support (/clr:safe)
In the "Linker" project settings:
CLR Image Type: just make sure this isn't set explicitly to IJW or PURE
Notes:
By using the "safe" project type, a few of the compiler and linker options which appear to affect platform type will be ignored. I.e. you don't have to go through and set everything to a non-specific platform type. Just the above. But you may set the other options to something appropriate, if it makes you feel better. :)
"Safe" will prevent the use of pointers. If this is an important issue, it is apparently possible to do albeit with a more complicated process. See Creating a pure MSIL assembly from a C++/CLI project? for details.
Don't forget that by default, Visual Studio will create C# projects that even though they are "AnyCPU" and even though they are executed on a 64-bit OS, will start up as a 32-bit process. This can hide platform-mismatch issues, if a dependency is x86 instead of pure/safe MSIL as intended. Just something be aware of (you can control this by unchecking the "Prefer 32-bit" option in the C# project's "Build" project properties page).
In order for the C++ functionality to be consumed by a C# dll, the C++ project must produce both x86 and x64 versions of the dll. It is not possible to reference just a x86 or a x64 dll from a C# dll compiled with the AnyCPU setting.
The trick to getting the AnyCPU dll to play with the C++ dll, is at runtime make sure the assembly cannot load the C++ dll and then subscribe to the AppDomain AssemblyResolve event. When the assembly tries to load the dll and fails, then your code has the opportunity to determine which dll needs to be loaded.
Subscribing to the event looks something like this:
System.AppDomain.CurrentDomain.AssemblyResolve += Resolver;
Event handler looks something like this:
System.Reflection.Assembly Resolver(object sender, System.ResolveEventArgs args)
{
string assembly_dll = new AssemblyName(args.Name).Name + ".dll";
string assembly_directory = "Parent directory of the C++ dlls";
Assembly assembly = null;
if(Environment.Is64BitProcess)
{
assembly = Assembly.LoadFile(assembly_directory + #"\x64\" + assembly_dll);
}
else
{
assembly = Assembly.LoadFile(assembly_directory + #"\x86\" + assembly_dll);
}
return assembly;
}
I have created a simple project demonstrating how to access C++ functionality from an AnyCPU dll.
https://github.com/kevin-marshall/Managed.AnyCPU
I am trying to reuse an interop DLL that compiled in one project on another, and it doesn't work.
I'll elaborate:
I compile the C++ COM DLL native_com_object.dll
In the same solution I have a C# project called LocalComClient.dll that generates Interop.native_com_objectLib.dll to use the C++ native_com_object.dll.
Last, I have another solution with a C# project (being compiled on another computer) called RemoteComClient.dll that references to native_com_object.dll (registered in that computer). This generates another Interop.native_com_objectLib.dll.
The problem is RemoteComClient.dll tries to load native_com_object.dll it MUST use its own Interop. If I try to use the LocalComClient.dll Interop .Net fails to load the assembly.
Edit: The exact exception message I am getting is:
Could not load file or assembly 'Interop.native_com_objectLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Of course the problem also occurs vice-versa (LocalComClient cannot use RemoteComClient's Interop).
My first question is - why?? As far as I understand it should generate the same interop (which obviously I am wrong).
My second question is, is it possible to make one interop for all the .Net clients of the DLL?
I'll point out I am using VS2013 (both machines), the C# objects are AnyCPU, and the C++ is x64.
Important EDIT: I cannot embed interop types because the C# projects are .Net 3.5 (not 4).
The located assembly's manifest definition does not match the assembly reference.
Very common exception message, the DLL it finds at runtime isn't the same as the reference assembly your program was compiled with. A very basic DLL Hell problem, not otherwise specific to COM interop.
You diagnose these kind of failures with Fuslogvw.exe, its trace for the failed assembly bind shows you what it looked for and what it found. The usual mismatch is the version number, you compiled your program with the 1.0.0.0 version of the interop assembly. That version is generated from the type library version number of the COM server. You were using version 1.0, kaboom if the COM server changed and you use its newer interop assembly.
And the PublicKeyToken can easily be a mismatch, you expect the interop DLL not to have one. Kaboom if the one you load at runtime does have one. Not terribly uncommon in COM interop, you tend to favor them getting stored in the GAC and that requires a strong name. Something you usually do later, forgetting to rebuild the app is an easy mistake.
The solution is to rebuild the client app with the correct interop assembly.
I have a problem when compiling a managed DLL project. The solution consists of two projects, the first is a .NET DLL written in C# and the other is Managed C++ DLL that directly references the C# project.
Both projects/DLLs are strongly named with an snk file on disk. The C# dll has a target framework of "AnyCPU" while the Manage C++ project is compiled twice, one for an x86 target and the other for an x64.
My problem is that when I compile the Managed C++ project to target the x86 platform, the result DLL has a PublicKeyToken = null as reported by ILSpy. When compiling to target an x64 platform, the DLL has the correct PublicKeyToken. I have checked my project properties, the snk file is referenced correctly for both platform targets under Configuration Properties -> Linker->Advanced->Key File with no delay signing; the Target Machine option is also set correctly based on the desired compilation target.
Here is the information shown by ILSpy when I load my DLL.
For the x64 dll:
// MyDll.x64, Version=1.1.1000.1, Culture=neutral, PublicKeyToken=XXXXXXXXX
// Architecture: x64
// This assembly contains unmanaged code.
// Runtime: .NET 2.0
For the x86 dll:
// MyDll.x86, Version=1.1.1000.1, Culture=neutral, PublicKeyToken=null
// Architecture: AnyCPU (64-bit preferred)
// This assembly contains unmanaged code.
// Runtime: .NET 2.0
What concerns me is the Architecture description for the x86 assembly: AnyCPU (64-bit preferred)
I am not sure why its using the AnyCPU configuration and what the 64-bit preferred annotation means exactly?
I also like to mention that my project is built against .NET Framwork 2.0 for the C# project while the Managed c++ project is built against the v90 Platform Toolset. I am using Visual Studio 2010 running on a Windows 7 64-bit machine.
Can someone tell me why this is happening and how can I solve this issue?
It is simply a consequence of how the COR header in the assembly can indicate what processor architecture is desired. You can see the declarations in the CorHdr.h SDK header file, you'll find it in your Windows SDK directory on your machine. You can use the CorFlags.exe utility to display the values.
The only flag available is COMIMAGE_FLAGS_32BITREQUIRED. When set, it indicates to the CLR that you want to run the program in 32-bit mode, even on a 64-bit operating system. An additional flag got added in .NET 4.5, COMIMAGE_FLAGS_32BITPREFERRED, it resolves an ambiguity on ARM cores. Too many assemblies around where 32BITREQUIRED actually means "x86 required" instead of "32-bit required".
So there is nothing similar to a "64 bit required" flag, an assembly can only indicate "32-bit" or "doesn't matter". With the jitter providing the "doesn't matter" glue, it generates the architecture dependent machine code at runtime. Since the 32BITREQUIRED option isn't turned on in your assembly, the disassembler cannot display anything else but AnyCPU.
The next detail is the IMAGE_FILE_HEADER.Machine field in the PE header of the executable file, it indicates what kind of machine the executable can run on. That's a weak signal for .NET assemblies since they don't normally contain any executable code, just MSIL. And it is readily ignored by the Windows loader, .NET assemblies normally have this field set to IMAGE_FILE_MACHINE_I386 to indicate x86. You still get a 64-bit process out of such an EXE assembly, some pretty heroic loader structure patching occurs when such an EXE is loaded. The job of mscoree.dll, the "loader shim". More about that in this post.
Since you targeted x64 in your C++/CLI project, the IMAGE_FILE_HEADER.Machine was set to IMAGE_FILE_MACHINE_AMD64 by the linker. The disassembler saw that, thus producing the "64-bit preferred" annotation.
Don't be fooled by the word "preferred" here. The disassembler didn't look deep enough to see that your assembly actually contains machine code, generated by the C++/CLI compiler. They don't like to, there isn't any disassembler that will decompile the machine code back to C++/CLI source code. The assembly isn't ever going to run on a 32-bit operating system. Kaboom on a 32-bit OS, the program fails with error 11, ERROR_BAD_FORMAT, "An attempt was made to load a program with an incorrect format".
This answers your question, it doesn't otherwise have anything to do with a strong name.
I have several Unmanaged C++ written lib files which I need to link to Managed C++ dll.
Then I need to invoke functions of this Managed C++ from C# application.
First step is OK - Managed C++ dll is created, I can see with ildasm that it exports functions I need. However when I try to call this function from my C#-written test app it says:
An unhandled exception of type 'System.IO.FileLoadException' occurred in Unknown Module.
A procedure imported by {MyManagedCPP.dll} could not be loaded.
This message goes from VS2010.
I made simple experiment - removed dependencies from all lib files in Managed C++ dll and rebuild it.
With this change it is OK - app starts, I can call functions of Managed C++ dll from C# test app.
Is it not possible by design to call managed c++ functions when dll has static linkage with lib files? Technical restriction? Or there is some workaround?
Thanks
You no doubt have an implicit dependency on a native DLL. It isn't clear from the question what DLL that might be. It could be msvcrxx.dll for example, a runtime support library for native C++ code. Which would be rather bad, you don't want to mix CRT versions. Such a missing DLL otherwise prevents the C++/CLI assembly from getting loaded, producing the FileLoadException.
If you have no idea what that DLL might be then you could use SysInternals' ProcMon utility. The trace will show you the program searching for the DLL and not finding it. If it is msvcrxx.dll then be sure to rebuild the .lib files using the same compiler version you used to build the C++/CLI assembly. If it is something else then make sure you copy that DLL to the build directory.
I imported LuaInterface into a console project, referenced it, and wrote a small test script. When i run it, i get this:
Could not load file or assembly 'LuaInterface, Version=2.0.0.16708, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format.
Forgive me for being a newbie or something, but i can't figure out what it means. What am i supposed to do?
Are you running on a 64-bit operating system?
If you are then you'll need to either get an x64 build of LuaInterface or set the platform target of your console project to x86.
You can read up on the platform target option here:
http://visualstudiohacks.com/articles/visual-studio-net-platform-target-explained/