dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.97k stars 4.65k forks source link

BadImageFormatException when trying to load c++/cli .net 5 assembly into c# .net 5 project #57642

Closed wwelias closed 3 years ago

wwelias commented 3 years ago

Title hopefully already explains the main problem.

When I create a project reference to the c++/cli project it all works perfectly but when I build it into a dll and add it to the project in form of a assembly it throws the "System.BadImageFormatException" and "Could not load file or assembly ... An attempt was made to load a program with an incorrect format."

But if I try the same thing with a c++/cli .NET Framework project there aren't any issues at all.

I thought .NET core 3.1 and later support c++/cli?

Can someone explain this to me and maybe help me solve this problem?

ghost commented 3 years ago

Tagging subscribers to this area: @vitek-karas, @agocke, @vsadov See info in area-owners.md if you want to be subscribed.

Issue Details
Title hopefully already explains the main problem. When I create a project reference to the c++/cli project it all works perfectly but when I build it into a dll and add it to the project in form of a assembly it throws the "System.BadImageFormatException" and "Could not load file or assembly ... An attempt was made to load a program with an incorrect format." But if I try the same thing with a c++/cli .NET Framework project there aren't any issues at all. I thought .NET core 3.1 and later support c++/cli? Can someone explain this to me and maybe help me solve this problem?
Author: wwelias
Assignees: -
Labels: `area-AssemblyLoader-coreclr`, `untriaged`
Milestone: -
AaronRobinsonMSFT commented 3 years ago

@wwelias Some comments/questions around the C++/CLI scenario.

When I create a project reference to the c++/cli project it all works perfectly but when I build it into a dll and add it to the project in form of a assembly

It sounds like the statement here is a ProjectReference from C++/CLI project to .NET application works but doing a MSBuild Reference tag to the C++/CLI assembly doesn't, correct? If so, are all the associated build artifacts copied with the C++/CLI assembly?

/cc @jkoritzinsky @tgani-msft

wwelias commented 3 years ago

@AaronRobinsonMSFT it's enough if the ijwhost.dll is in the same directory as the C++/CLI assembly right? Because loading it doesn't work. And if that's the case: yes ijwhost.dll is adjacent.

Bitness of the C++/CLI assembly and runtime attempting to load the assembly match and it still causes BadImageFormatException.

And how do I check if all of the associated build artifacts are copied with the C++/CLI assembly?

wwelias commented 3 years ago

@albertogregoriophios

wwelias commented 3 years ago

Here is a demo version of my problem: https://github.com/wwelias/demo_core.git

AaronRobinsonMSFT commented 3 years ago

@wwelias I've run your demo. This appears to be an issue with how the SDK copies dependencies when doing a Reference. The issue is the ijwhost.dll is missing from where the dotnet_cs.exe is running. In this case, demo_cs\bin\Debug\net5.0. The solution here is to copy the ijwhost.dll binary from the build output of the demo_cli project.

The error code in this case is a red herring and that issue was fixed in .NET 6 to propagate the real error code – see https://github.com/dotnet/runtime/pull/45997.

There does seem to be a potential fix here for an MSBuild Reference tag to pull over the ijwhost.dll if it can detect the assembly is a C++/CLI assembly. I would recommend opening an issue in https://github.com/dotnet/sdk or https://github.com/dotnet/msbuild – @marcpopMSFT or @rainersigwald can determine which repo should consider this issue.

wwelias commented 3 years ago

@AaronRobinsonMSFT

The solution here is to copy the ijwhost.dll binary from the build output of the demo_cli project.

This didn't work for me.. It sadly still caused the same error. But thank you very much for the help so far! I now opened a new issue in https://github.com/dotnet/sdk as you recommended.

AaronRobinsonMSFT commented 3 years ago

@wwelias I'd like to confirm the current state to help ensure we are on the same page. Here is my directory list:

...\demo_core\demo_cs\bin\Debug\net5.0>dir
 Volume in drive F is Source2
 Volume Serial Number is F83C-EC20

 Directory of ...\demo_core\demo_cs\bin\Debug\net5.0

19-Aug-21  10:06    <DIR>          .
19-Aug-21  10:06    <DIR>          ..
19-Aug-21  07:33           124,416 demo_cli.dll
19-Aug-21  07:33         1,044,480 demo_cli.pdb
19-Aug-21  07:33               147 demo_cli.runtimeconfig.json
19-Aug-21  07:33               820 demo_cs.deps.json
19-Aug-21  07:33             4,608 demo_cs.dll
19-Aug-21  07:33            99,840 demo_cs.exe
19-Aug-21  07:33             9,620 demo_cs.pdb
19-Aug-21  07:33               322 demo_cs.runtimeconfig.dev.json
19-Aug-21  07:33               147 demo_cs.runtimeconfig.json
09-Jul-21  18:36           102,792 Ijwhost.dll
19-Aug-21  07:33    <DIR>          ref

From the above directory, the application runs as expected:

...\demo_core\demo_cs\bin\Debug\net5.0>demo_cs.exe
Hello World!
Created the Class!
Created the Class!
DoStuff from Wrapper!
Result: 3

We should also verify all assets containing native code are the same bittness. The dumpbin utility can be found from a Developer Command prompt.

...\demo_core\demo_cs\bin\Debug\net5.0>dumpbin /headers demo_cli.dll | findstr machine
             14C machine (x86)
                   32 bit word machine

...\demo_core\demo_cs\bin\Debug\net5.0>dumpbin /headers demo_cs.exe | findstr machine
             14C machine (x86)
                   32 bit word machine

...\demo_core\demo_cs\bin\Debug\net5.0>dumpbin /headers Ijwhost.dll | findstr machine
             14C machine (x86)
                   32 bit word machine
wwelias commented 3 years ago

@AaronRobinsonMSFT Thank you for your help! I tried to recreate the project at my private pc over the weekend and somehow managed to make it work! The ijwhost.dll was indeed the issue. But I'm wondering what was wrong with the way I did it at my internship... gonna look for that tomorrow!