dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.75k stars 1.07k forks source link

No Ijwhost.dll when referencing C++/CLR NuGet package from .NET 6 C# app #24310

Open james-uffindell-granta opened 2 years ago

james-uffindell-granta commented 2 years ago

It's possible I'm missing something, but I can't find any clear documentation on how Ijwhost.dll is supposed to work, so I thought I'd ask here.

I have a C++/CLR project targeting .NET 5, and when this is built in Visual Studio, Ijwhost.dll ends up in the bin/ folder alongside the compiled dll. If I reference this from a .NET 6 C# project in the same solution using <ProjectReference>, then Ijwhost.dll ends up copied into the output folder of the C# project as well, and everything works fine. (I don't know where Visual Studio is sourcing this Ijwhost.dll from, but it clearly knows somewhere to look for it.)

If I reference the C++/CLR as a NuGet <PackageReference> from a .NET 6 C# project in a different solution, however, then no Ijwhost.dll ends up in the output folder. Nothing in the build seems to notice that I'm referencing a C++/CLR project and locate Ijwhost.dll, and if I try running the C# app, it fails to load my C++/CLR dll with a Failed to load file or assembly error. Manually copying an Ijwhost.dll into the output directory (eg, from the C++/CLR project in the other solution) fixes this, so it’s definitely this missing shim dll that’s the problem.

What's the expected way to get this working? Is there an option I can specify in the .nuspec file or <PackageReference> tag that flags the package as C++/CLR and triggers the inclusion of Ijwhost.dll? Should be bundling Ijwhost.dll into the NuGet alongside the C++/CLR library? Should I be copying it from somewhere else (where?) in the C# csproj build steps?

There are a few other Ijwhost.dll-related issues in this repo already, but as far as I can tell they all seem to be about dynamically loading a C++/CLR dll via LoadLibrary, or about referencing the C++/CLR project as a project reference from elsewhere in the same solution – not about pulling it in as a NuGet dependency.

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost commented 2 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
It's possible I'm missing something, but I can't find any clear documentation on how Ijwhost.dll is supposed to work, so I thought I'd ask here. I have a C++/CLR project targeting .NET 5, and when this is built in Visual Studio, Ijwhost.dll ends up in the bin/ folder alongside the compiled dll. If I reference this from a .NET 6 C# project in the same solution using ``, then Ijwhost.dll ends up copied into the output folder of the C# project as well, and everything works fine. (I don't know where Visual Studio is sourcing this Ijwhost.dll from, but it clearly knows somewhere to look for it.) If I reference the C++/CLR as a NuGet `` from a .NET 6 C# project in a different solution, however, then no Ijwhost.dll ends up in the output folder. Nothing in the build seems to notice that I'm referencing a C++/CLR project and locate Ijwhost.dll, and if I try running the C# app, it fails to load my C++/CLR dll with a `Failed to load file or assembly` error. Manually copying an Ijwhost.dll into the output directory (eg, from the C++/CLR project in the other solution) fixes this, so it’s definitely this missing shim dll that’s the problem. What's the expected way to get this working? Is there an option I can specify in the .nuspec file or `` tag that flags the package as C++/CLR and triggers the inclusion of Ijwhost.dll? Should be bundling Ijwhost.dll into the NuGet alongside the C++/CLR library? Should I be copying it from somewhere else (where?) in the C# csproj build steps? There are a few other Ijwhost.dll-related issues in this repo already, but as far as I can tell they all seem to be about dynamically loading a C++/CLR dll via `LoadLibrary`, or about referencing the C++/CLR project as a project reference from elsewhere in the same solution – not about pulling it in as a NuGet dependency.
Author: james-uffindell-granta
Assignees: -
Labels: `area-Host`, `untriaged`
Milestone: -
vitek-karas commented 2 years ago

The ijwhost.dll needs to be part of NuGet when published, after that the rest should work fine. @jkoritzinsky would you know how to make it part of the NuGet package?

Also: moving this to the SDK repo where it belongs.

jkoritzinsky commented 2 years ago

I’d have to think about the right place to put it in the NuGet package so the loader finds it correctly. Then we’d need to figure out how the C++/CLI targets copy it to the output directory and either update those targets to put it in the right spot in the package or add a target here that puts it in the right spot.

Qiu233 commented 2 years ago

The ijwhost.dll needs to be part of NuGet when published, after that the rest should work fine. @jkoritzinsky would you know how to make it part of the NuGet package?

Also: moving this to the SDK repo where it belongs.

Well is there any possibility that two NuGet packages use different versions of ijwhost.dll? I think that would lead to something like dll-hell.

miloush commented 1 year ago

@jkoritzinsky any recommendations on how to include the Ijwhost.dll in a NuGet package? Searching GitHub gives a few approaches:

You don't want the dll to be referenced by the project (so not lib), you do not need it at compile time (so not ref), but it needs to be copied to the output directory. According to the documentation only runtimes and content remains. The content seems like it would end up in wwwroot for web projects, which is wrong, and the runtimes suggests there should always be a corresponding AnyCPU assembly under ref, which does not exist.

Anyway, if I do target="runtimes\win-x64\native" it ends up in a similar subfolder:

image

i.e. nowhere near the assembly where it needs to be.

lkluc commented 1 year ago

I had already part of the solution, because I previously needed to include another native DLL. so I had found and used the following solution on Stack Overflow (to include a target file with the NuGet package, which instruct VS to include the native DLLs into customer's project as to be copied to output dir) :

https://stackoverflow.com/questions/19478775/add-native-files-from-nuget-package-to-project-output-directory

... then it was just a matter of adding the self-name-mocking "It Just Work" DLL to the NuGet list of files in the .nuspec file, under "build" subdirectory :

(...)
    <file src="..\..\x64\Release\ijwhost.dll"  target="build\ijwhost.dll"/>
(...)
lkluc commented 1 year ago

But I admit my solution seems to me a workaround and I guess the Visual Studio teams should work to address this issue... ?

lkluc commented 1 year ago

It seems my solution is not working for F# interactive, still searching a new solution! :| However, I found a solution to reference the DLL in the target file rather than include the ijwhost.dll in the NuGet package, see https://github.com/AmpScm/SharpProj/issues/25#issuecomment-1482915538

elliz commented 1 year ago

It seems my solution is not working for F# interactive, still searching a new solution! :| However, I found a solution to reference the DLL in the target file rather than include the ijwhost.dll in the NuGet package, see AmpScm/SharpProj#25 (comment)

That works for Microsoft.NET.Sdk ... but not for Microsoft.NET.Sdk.Web ... any idea why, or how to fix?