Skip to main content


Hello fedi, any #DotNet and #NuGet experts here please?
I'm trying to prepare a NuGet package where I need to bundle a folder with a DLL and some accompanying files. Everything is good, the nupkg file is created, the folder is there (I can clearly see it with 7-zip). However, when installing the package, the folder is again there in the NuGet global cache, but not in the project where I install it!
I even asked a StackOverflow question [1] about it, but still no dice. Any thoughts please? Thanks!
[1]:stackoverflow.com/questions/78…
in reply to André Polykanine

I took a look at your project file and it looks like the 'additional files' you mention are native binaries, right? If so, you need to package them in separate folders by platform. NuGet has docs here: learn.microsoft.com/en-us/nuge…
in reply to Chet Husk

@chethusk Thanks for replying! As far as I understood, I must use a Nuspec file and cannot do it in the CsProj file, right? Or am I wrong? And still, why does it get copied to the global cache but not to the project itself?
in reply to André Polykanine

no, you don't need a nuspec. You can do all of this using the Pack and PackagePath metadata like you've done with other package contents.

It's not entirely clear what you mean by 'installed into the project', but you should look inside the project.assets.json in your projects obj folder - this file describes how NuGet sees your package and determines which dependencies will actually end up in your project. If you don't see your native binaries in the project.assets.json...

in reply to Chet Husk

@chethusk By "installed in the project" I mean, there is another (private) project using this. I do `dotnet add package myPackage` to the project. I see everything including the binaries in %UserProfile%/.nuget folder, but not in the project itself.
in reply to André Polykanine

you're typically not going to see the package binaries until you publish your application - is that what you mean? Again, this is all driven off of the view of your package as seen in project.assets.json.
in reply to Chet Husk

@chethusk Sorry, probably I'm not clear. So, step by step:
1. I package my NuGet package using `dotnet pack` and the CsProj you looked at. I'll call this "package".
2. I have another project (I'll call it "app") where I want to *use* the package.
3. I do `dotnet add package` to add the package to the app.
Result? My app does not work because the DLL the package imports is not there at all.
in reply to André Polykanine

at this point I would need a binlog or some OSS standalone sample to provide any further guidance I think. At minimum I'd need to see the project.assets.json file I've mentioned before.
in reply to Chet Husk

hello again! I found your project on GitHub and I think I can explain what's happening.

The first image is what your package looks like today, with everything copied into the `lib/net8.0` directory. NuGet only automatically references _managed assemblies_ from folders using the `lib/<TFM>` pattern, which is why only your main `SharpLouis.dll` assembly is here.

To fix this, you need to tell NuGet about your _native dependencies_. This can be done with a line similar to what you have.

in reply to Chet Husk

Here's the line to make NuGet see your native dependency

```xml
<Content Include="./LibLouis/liblouis.dll" Pack="true" PackagePath="runtimes/win-x64/native" />
```

This is very close to what you already had - the key difference here is the PackagePath - NuGet looks for native dependencies at `runtimes/<RID>/native`, so I've placed the native liblouis at `runtimes/win-x64/native`. When you do this, the package changes - the second image shows NuGet seeing the native deps.

in reply to Chet Husk

@chethusk I cannot see the images (I'm blind), but I'm slowly getting what you mean now. However, as you can see, I'd like to bundle the whole LibLouis folder, because it depends on the tables folder and the projects that would use SharpLouis would also depend on tables.json. Should I change anything to do this? thanks immensely for your help!
in reply to André Polykanine

My apologies! I should have added alt-text to my screenshots, I'll edit to do so now. The remaining information (the tables, etc) I _should_ be able to figure out shortly - NuGet has a `contentFiles` mechanism that I am aware of but haven't used in a while so I'm having to refresh my memory. If you like, I can submit a PR to your PR when I have it all figured out for easier review.
in reply to André Polykanine

PR sent! I have one outstanding question that I need your feedback on in the PR, however.
in reply to Chet Husk

@chethusk Thank you so much Chet! Now everything is there but I have one more issue: in the SharpLouis code itself I'm trying to import the DLL as if it was in the same LibLouis folder where the tables folder and tables.json are, but it's actually in runtimes/win-x64/native. Is there any way to moving it or should I change the code somehow appropriately? Thank you once more!
in reply to André Polykanine

what happens if you publish and run your app with 'dotnet publish -r win-x64'? Publishing is what tells the .NET SDK to layout all of your platform specific dependencies for that platform directly next to your app - otherwise you'll need to do a slight amount of work to tell your app how to look in `runtimes/<RID>/...`. I think we have a doc showing this, let me try to find it.
in reply to Chet Husk

@chethusk Hm. If I publish as you said, it puts LibLouis.dll alongside all the files of the app, like .dll, .exe and so on. It's a minimal change in the code. However, what if I need to rebuild the solution from Visual Studio? Or should I always *publish* the app from now on? Sorry if the questions are stupid, it's kind of new to me.
in reply to André Polykanine

you may be able to also build for that RID via 'dotnet build -r win-x64' (I don't recall the exact behavior here) but for apps generally we (speaking for the SDK team here) do expect apps to only be fully packaged via publishing. This becomes even more apparent if you tried to AOT your app - that's a workflow that is only valid for publish, not build.
in reply to Chet Husk

@chethusk Wait, we are talking about apps using that package, not about the package (SharpLouis) itself? If so, how do you debug them then? In my case it's a GUI app using WindowsForms and all the stuff including this DLL wrapper.
in reply to Chet Husk

@chethusk Interesting. If I do just:
<Content Include="LibLouis\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
Then I have my DLL where intended, but I started getting random access violation exceptions with message "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." Any thoughts on this also, please?
in reply to André Polykanine

Sorry for the delay, I spent part of the day talking to some folks inside the .NET org that manage native dependencies like you do. One example I was pointed to was the SkiaSharp library - .NET bindings to the Skia graphics API. Here is some of their logic for making the local-build dev cycle work: github.com/mono/SkiaSharp/blob…

All of the projects in the repo that use the library Import this file: github.com/search?q=repo%3Amon…

in reply to Chet Husk

@chethusk Wow, that is… overwhelming a bit. Will need to wrap my head around it more, probably.
in reply to Chet Husk

@Chet Husk @André Polykanine I am not .net guy like you, I just wanted to let you both know your cooperation and the dialogue is awesome. thanks once again @Chet Husk for being so helpfull in this particular case.
in reply to André Polykanine

I had a similar problem. I wanted to compile the same project into platform dependent variants and distribute them via nuget. The project file is here: github.com/badcel/WCharT.Net/b…