Including Unmanaged DLL in NuGet Package Using csproj - .net-core

I'm developing a .NET Core 2.1 library that depends on an unmanaged DLL. I'd like to include the unmanaged DLL in the NuGet package as well. The problem that I am running into is that if I try to specify all of the information in the .csproj file, the dotnet build process throws the following warning:
warning NU5100: The assembly 'content\lib\subdir\somedll.dll' is not
inside the 'lib' folder and hence it won't be added as a reference
when the package is installed into a project. Move it into the
'lib' folder if it needs to be referenced.
I know that I can embed the unmanaged DLLs by writing a .nuspec (in fact, I have). However, it seems like I shouldn't need to write one with the latest .csproj file format.
Question: How can I use the .csproj file to embed unmanaged DLLs in a NuGet package?
Specifying <ItemGroup><None> in the .csproj file seems to include the files in the output directory but they do not make it into the NuGet package.
Specifying <ItemGroup><Content> in t he .csproj file will get them added to the NuGet package but in the Content directory instead of in the Lib directory.
If I really have to have both a .csproj file and a .nuspec file, what is the best practice for where to put the metadata? In t he .csproj file? In the .nuspec file? Maintain and sync both? Is there a something in the tool chain that can do this for me?
I'm working in Visual Studio Code V1.24, and .NET Core/dotnet V2.1.

You need to specify explicit package path metadata on the element so that the dll/so/dylib file ends up at the right place in the package so that it is recognised as runtime-specific native DLL:
<ItemGroup>
<None Include="unmanaged.dll" Pack="true" PackagePath="runtimes\win-x64\native" />
</ItemGroup>

Related

Define C# preprocessor symbol in NuGet package

Can a NuGet package define a preprocessor symbol for the consuming project? And if so, how?
If your package (My.ExamplePackage) contains an MSBuild file named like the package name + .targets in the build directory (so build\MyExamplePackage.targets), you can use it to amend the DefineConstants property that may have been set to defaults or reset in the project:
<Project>
<PropertyGroup>
<DefineConstants>$(DefineConstants);MY_PREPOCESSOR_SYMBOL</DefineConstants>
</PropertyGroup>
</Project>
While the package can contain both a .props and .targets file, the .targets file will be imported after the main body of the csproj file being built so if it the project re-sets DefineConstants (meaning not adding to it by prepending $(DefineConstant);), the .targtes file has a chance of adding to this property.

How to use my own DLLs instead of the one referenced by a dependent package

I'm using a nuget package (let's call it A) which has dependency to another package, let's call it B.
To include A in my project, I changed .csproj file to:
<ItemGroup>
<PackageReference Include="A" Version="2.0.5" />
</ItemGroup>
When I run nuget restore package B is consumed from some nuget source too.
I want to replace dlls of package B with my own DLLs, I've created myself.
I can do it on my local machine by just copy pasting the desired dlls in bin folder. But how can I do the same on Azure Websites? Is there anyway to automate this process?
Is there any way to tell nuget not to fetch DLLs of B from nuget source and instead use my desired ones?
Update:
Thanks to Shahryar's contribution, we can also choose to add the dll file and set it to be copied to the compilation folder for implementation (define properties in the .csproj file).
In fact, it is mainly to change the content of final compiled files, because after the final deployment, it runs according to the compiled files.
Original Answer:
You can compile the web app locally first, and then replace your dll file with the corresponding file in bin. Use zip to package the entire compiled file, and then use zip deployment to directly upload the final compiled file to Azure (the operation of the web app deployed to Azure depends on the file uploaded in this way)
Have a look of Zip Deploy.

Can .Net Core 3 self-contained single executable be decompiled?

I tried using Dotpeek and ILSpy.Net to decompile (my own code), they failed.
Do I need special obfuscation on distributed binaries of .Net Core 3 self-contained single executable ?
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
<PublishSingleFile>true</PublishSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
</Project>
The single-file exe is really an unmanaged wrapper and ILSpy doesn't support decompiling this. But when you run the exe, it unwraps its contents to a temp folder. So you can find the managed dll there and decompile it using ILSpy.
To find the temp folder, you can use any tool that shows locations of assemblies loaded by a process. SysInternals Process Monitor (procmon) is a good one.
You can setup procmon to filter by your exe name, and when you launch your exe, procmon should show some events for assemblies being loaded from a temp folder:
You can browse to that folder and find your managed dll there. And you can decompile using ILSpy from that location.
I wrote a blog entry: https://eersonmez.blogspot.com/2020/02/ilspy-decompiling-net-core-self.html
I wrote a small dotnet tool after I stumbled upon this question and couldn't find a lightweight tool myself other than ILSpy.
You can install it using the following dotnet command: dotnet tool install -g sfextract.
After installing it, run it using the following command: sfextract application.exe -o output-dir
The bundle format for .NET 5.0 (bundle version 2) is identical to previous versions. .NET 6.0 (bundle version 6) has an additional field for each file entry containing the compressed size, since single-file applications can now be compressed using gzip by setting EnableCompressionInSingleFile to true.
https://www.nuget.org/packages/sfextract/
https://github.com/Droppers/SingleFileExtractor
Update 07/2022: .Net 5 single-file does not automatically unpack to the same temporary location as before. to force it to be unpacked you would need to add the following:
in the project file add these properties (according to theseMicrosoft docs):
<PublishSingleFile>true</PublishSingleFile>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
Add an environment variable DOTNET_BUNDLE_EXTRACT_BASE_DIR with the location you want the files extracted to.
Update: One of the announcements made regarding .Net 5 states that the way single-file executables will be made would change, so this method will not work for them.
I wanted to add on #Eren Ersönmez's answer, that while ILSpy DotPeek don't support this at the time, since the self-contained single file is just a wrapper that contains all your DLLs and gets extracted on runtime, simply knowing where it is extracted to can save you using ProcMon or ProExp or windbg.
If you use windows you can go to c:\Users\{Local Username}\AppData\local\temp\.net\{Name of executable}
which should lead to somewhere similar to
c:\Users\alenros\AppData\Local\Temp.net\MyTestApplication
Launch your exe, and a folder with the same name will be created in that location.
The folder will contain randomly named folders. open the latest one and there you will find all your extracted DLLs, which can then be decompiled.

xml documentation file of nuget dependencies not part of publish - .net core 2.2

I have a project which is referring packages from nuget. These packages from nuget have their XML documentation file included as part of the package (present in .nupkg file at /lib/netstandard2.0/<projectName>.xml along with <projectName>.dll file)
The XML documentation file is getting generated by adding below in csproj file:
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Now when I am publishing the project which has these nuget packages references, the xml documenation file of the referred nuget packages is not becoming part of publish.
It seems this is an ongoing issue.
Is there a workaround to include xml documentation of referred packages ?
Found a solution which is making this work. Added below in the `.csproj' file:
<Target Name="_ResolvePublishNuGetPackagePdbsAndXml"
AfterTargets="RunResolvePublishAssemblies">
<ItemGroup>
<ResolvedFileToPublish
Include="#(ResolvedAssembliesToPublish->'%(RootDir)%(Directory)%(Filename).pdb')"
RelativePath="$([System.IO.Path]::ChangeExtension(%(ResolvedAssembliesToPublish.DestinationSubPath), '.pdb'))"
DestinationSubPath="$([System.IO.Path]::ChangeExtension(%(ResolvedAssembliesToPublish.DestinationSubPath), '.pdb'))"
Condition="'%(ResolvedAssembliesToPublish.PackageName)' != ''
and Exists('%(RootDir)%(Directory)%(Filename).pdb')" />
<ResolvedFileToPublish
Include="#(ResolvedAssembliesToPublish->'%(RootDir)%(Directory)%(Filename).xml')"
RelativePath="$([System.IO.Path]::ChangeExtension(%(ResolvedAssembliesToPublish.DestinationSubPath), '.xml'))"
DestinationSubPath="$([System.IO.Path]::ChangeExtension(%(ResolvedAssembliesToPublish.DestinationSubPath), '.xml'))"
Condition="'%(ResolvedAssembliesToPublish.PackageName)' != ''
and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
</ItemGroup>
</Target>
It will make xml (and pdb if present) files of referred packages become part of published files.

.nupkg does not contains dll of project instead it copies whole project in package after vsts build

****i'm building the nuget package using vsts build, once the build is created it does not contains dll of project instead it's just copying whole project in nuget packages.which is not expected****
Based on the code of nuspec file, you include all files, so all files will be in the package, you need to specify the files/folders that you want to include into the package.
The simple way is that you can specify the project file instead of nuspec file to package.

Resources