adammarks / netcoreproto

.NET Core C++/CLI Prototypes
0 stars 0 forks source link

ManagedInteropApp - BadFormatException when loading C++/CLI assembly #5

Open adammarks opened 4 years ago

adammarks commented 4 years ago

Steps-

  1. Build ManagedInteropApp as Debug/x64
  2. Run

Results: I get a BadFormatException when I try to load the C++/CLI assembly Snag_1d140ddb

Expected: It should run fine

adammarks commented 4 years ago

Using ILSpy, the CPPCLIInteropLibrary.dll looks like it is good - It is x64 and does contain unmanaged code Snag_38529fe8

adammarks commented 4 years ago

My .NET core environment

> dotnet --list-sdks
2.1.509 [C:\Program Files\dotnet\sdk]
2.2.110 [C:\Program Files\dotnet\sdk]
3.0.101 [C:\Program Files\dotnet\sdk]
3.1.100 [C:\Program Files\dotnet\sdk]
3.1.200-preview-014879 [C:\Program Files\dotnet\sdk]

> dotnet --list-runtimes
Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
mjrousos commented 4 years ago

@adammarks, I found the issue here. It was pretty simple, the error message is just really misleading. The issue appears to be that CPPCLIInteropLibrary.dll isn't loading because it can't find its dependency NativeDLL.dll. If I copy NativeDLL.dll from the parent directory into the /netcoreapp3.1 directory the app runs from, it works.

So, an easy workaround is just to make sure everything builds into the same directory. Still, this isn't a very good experience. @nguerrera and @tgani-msft, any ideas why the C++/CLI library's native dependency isn't copied transitively with the C++/CLI library when a managed app depends on it?

The C++/CLI library lists the native dll as a dependency in its csproj:

<ItemGroup>
  <ProjectReference Include="..\NativeDLL\NativeDLL.vcxproj">
    <Project>{4fcb1ab9-2f37-4037-a488-265a0fb6bd20}</Project>
  </ProjectReference>
</ItemGroup>

The native dll even shows up in the managed app's deps.json that transitively depends on it:

{
  "runtimeTarget": {
    "name": ".NETCoreApp,Version=v3.1",
    "signature": ""
  },
  "compilationOptions": {},
  "targets": {
    ".NETCoreApp,Version=v3.1": {
      "ManagedInteropApp/1.0.0": {
        "dependencies": {
          "CPPCLIInteropLibrary": "1.0.0"
        },
        "runtime": {
          "ManagedInteropApp.dll": {}
        }
      },
      "CPPCLIInteropLibrary/1.0.0": {
        "dependencies": {
          "NativeDLL": "1.0.0"
        },
        "runtime": {
          "CPPCLIInteropLibrary.dll": {}
        }
      }
    }
  },
  "libraries": {
    "ManagedInteropApp/1.0.0": {
      "type": "project",
      "serviceable": false,
      "sha512": ""
    },
    "CPPCLIInteropLibrary/1.0.0": {
      "type": "project",
      "serviceable": false,
      "sha512": ""
    }
  }
}

If a repro would be helpful, just clone this repository and launch the ManagedInteropApp project. You'll see the failure when you click the form's button (which attempts to load CPPCLIInterop and fails because NativeDLL isn't in the output directory).

adammarks commented 4 years ago

By changing the output directory for NativeDLL.dll to include the netcoreapp3.1 directory, everything does work perfect!

@mjrousos @nguerrera @tgani-msft I recall experiencing this same thing with .NET framework and Native DLLs where they aren't copied over. I can live with that, but, I recall more specific error messages when this occurs on .NET framework, the "Bad format exception" is misleading, it doesn't tell me that the real problem is the DLL isn't in the right location.

mjrousos commented 4 years ago

Agreed. The error message here is pretty poor/misleading. @nguerrera @tgani-msft, can we improve the error messages for missing native dlls? BadFormatException on the C++/CLI library looking for the dependency is confusing.

tgani-msft commented 4 years ago

I believe @jkoritzinsky @dotnet/coreclr knows about the poor diagnostic.

jkoritzinsky commented 4 years ago

We have a tracking issue for improving the diagnostics here. https://github.com/dotnet/coreclr/issues/24220