Call executable inside Nuget package cache from launchSettings.json - nuget-package

I created a small executable that is used to run and debug specific libraries from other solutions. The executable is given the path to a library as a command line argument which the executable loads at runtime.
I want to put my executable in a Nuget package, and have consuming libraries just add the Nuget package to be able to run and debug, using a launchSettings.json.
Because the executable is in the tools/ directory of the Nuget package, its path is put into the PATH environment variable by the Package Manger Console. Therefore the launchSettings can simply just call the executable.
I create my Nuget package with nuget.exe pack my.nuspec -Version 1.0.0, with my.nuspec containing:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>DebugHost</id>
<version>$version$</version>
<title>DebugHost</title>
<authors>Some company</authors>
<owners>Some company</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>DebugHost</description>
<summary>DebugHost</summary>
<copyright>2020, Some company</copyright>
</metadata>
<files>
<file src="bin\Debug\netcoreapp3.1\*" target="tools" />
</files>
</package>
From consuming library projects I put in Properties\launchSettings.json containting:
{
"profiles": {
"DebugHost": {
"commandName": "Executable",
"executablePath": "my.exe",
"commandLineArgs": "$(ProjectDir)$(OutDir)$(TargetName)$(TargetExt)"
}
}
}
I have three different questions that are somewhat related, as any might answer another:
This setup only works as long as I keep the Package Manager Console opened. If I try to Debug / Launch the library without first opening the Package Manager Console, the launch fails because it cannot find the executable. Unable to start program 'my.exe'. The system cannot fint the file specified.
Can I for example add a targets file in the Nuget package that will hint its path during build/launch, which in turn I can use as a variable in the launchSettings.json? (If so, how?)
This setup requires that a Properties\launchSettings.json is used in the consuming project. Can I make my Nuget package create that file?
Can the file be an asset in the Nuget that gets copied to the correct place?
Or can I even have an install.ps1 script that creates the json, with the correct absolute path to the executable in it? This would make question 1 answered as well.
The above situation only works with nuget.exe pack and a .nuspec.
Can I instead move stuff into my (new style) .csproj and get this to work with just dotnet.exe pack and the .csproj? (or msbuild.exe -t:pack and the .csproj?) So ultimately I can also just create the package by simply right clicking the project in Visual Studio and selecting Pack from the context menu?

Related

Ho to trace dll to some nuget package

I'm working on relatively big solution with many projects in it. Almost each project has dependencies on some nuget packages. In the output folder bit/debug/net6.0 of startup project I have found BouncyCastle.Crypto.dll and I would like to find out where it's comming from.
I have checked all the project files but there is no references to BouncyCastle.Crypto neither any reference in any of .cs files. So it must be a transient dependency.
Question is there easy way to find out nuget package from which this DLL is comming?
Is there is UI for it e.g. in Visual Studio / Resharper or if there is some command for dotnet CLI?
You can use build with --verbosity flag, like this:
dotnet build --verbosity detailed
And then, in output you can grep or search for relevant dll, you'll find something like this:
1:7>Target "_CopyFilesMarkedCopyLocal" in file "/opt/.dotnet/sdk/6.0.403/Microsoft.Common.CurrentVersion.targets" from project "/SOME_PATH/SOME_PATH/SomeProjectName.csproj" (target "CopyFilesToOutputDirectory" depends on it):
Task "Copy"
Copying file from "/SOME_PATH/.nuget/packages/bouncycastle/1.8.9/lib/BouncyCastle.Crypto.dll" to "/SOME_PATH/SOME_PATH/bin/Debug/net6.0/BouncyCastle.Crypto.dll".
Done executing task "Copy".
from project line, will point you to the actual project. Copying file from and to will point to the actual dll.

MSBuildTasks and NuGet - How can I restore MSBuild.Community.Tasks.dll?

I have a project which has a NuGet package called MSBuildTasks installed. It installs two files: MSBuild.Community.Tasks.targets and MSBuild.Community.Tasks.dll to the .build directory within the solution directory. This package reference has been added to the packages.config file in that project directory so that when I build the project (and with the NuGet package restore settings enabled) it will restore the package which is great because then I can distribute the source to other developers and build it on our build server without any missing files...
However, the problem is that when NuGet restores the package, it doesn't restore these two files to the expected location it was originally in when I first installed it with the Install-Package MSBuildTasks command, which was in to the $(SolutionDir)\.build directory. Instead, it has installed it to the $(SolutionDir)\packages\MSBuildTasks.1.4.0.78\tools directory, so now if I wish to include the MSBuild.Community.Tasks.targets file, I must reference this path absolutely in my .csproj or other .targets file. This presents a problem since the version number will undoubtedly change, requiring manual work to correct.
Is there some way that I can restore the MSBuildTasks .targets and .dll files to the original location of $(SolutionDir)\.build where it first installs to? The current behaviour of restoring in to the packages directory, while it makes sense for other packages, seems like a bug for this particular package since I will not be able to know the version number of the directory to include in my other .targets or .csproj files.
NuGet restore will only download files to the packages directory. It will not make any other modifications.
Looking at the MSBuildTasks NuGet package the files added to the $(SolutionDir)\.build are added by a PowerShell script. This PowerShell script will not be run when restoring the NuGet package.
You should add the $(SolutionDir)\.build to your source control repository.
With the newer versions 1.5+ the Nuget package doesn't install itself in the solution directory; this worked for me though:
<PropertyGroup>
<MSBuildCommunityTasksPath>$(USERPROFILE)\.nuget\packages\msbuildtasks\1.5.0.235\tools</MSBuildCommunityTasksPath>
</PropertyGroup>
It does involved adding the version, but if someone knows a way to remove having to update the version on the path when you update the package that would be awesome.

Can't compile project after adding SFML.NET by Nuget

After adding SFML.NET through Nuget Packge manager I got the following error:
Error 4 The "UnzipNuspec" task was not found. Check the following: 1.) The name of the
task in the project file is the same as the name of the task class. 2.) The task class is
"public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is
correctly declared with <UsingTask> in the project file, or in the *.tasks files located
in the "C:\Windows\Microsoft.NET\Framework\v4.0.30319" directory.
I'm using Visual Studio 2012.
As pointed out in other similar questions, I've tried to close and open MSVS, it didn't helped.
I also checked out the build tools path in the registry, and it points to right directory.
I tried to install and uninstall Nuget packeage.
I found out that error possibly somehow connected to it's dependency : Baseclass.Contrib.Nuget.Output, but I can't find out how to fix it.
It's a bug in their build script.
Go to the packages folder for your solution and locate the following file:
Baseclass.Contrib.Nuget.Output.1.0.6\build\net40\Baseclass.Contrib.Nuget.Output.targets
Around line 84 in that file you'll find a couple of <Using Namespace=... /> tags. Add this after those, before the <Code...> tag:
<Using Namespace="System.Threading" />
I've reported this on their github issues list as well.

How do I include an XSD file for a configuration section with a NuGet package?

I have a library with a pretty verbose configuration section. I've created an XSD and would like to distribute that with my package so that when a user installs the package, Visual Studio knows about the XSD without the user needing to do anything extra. How do I do this?
You can include any files you want in a nuget package by placing them in the content directory. These will then be installed into the root of your target project when the package is installed. If you're using a nuspec file to build your package you would add the following element under the element.
<files>
<file src="Configuration\MyXsd.xsd" target="content\TargetFolderName" />
</files>
This will create the following file in the target project
\TargetFolderName\MyXsd.xsd
Once the xsd is in the target project visual studio should pick it up automatically for validating your config section.
This has recently become more complicated with SDK style projects and the different ways of referencing nuget packages.
Note the end of this section.
Basically, if a nuget project is referenced by package.config file, the files from the content folder of the nuget package will be copied to the referencing project. If the nuget package is referenced by PackageReference in the project file, the files from the contentFiles folder within the package will be used. It is recommended to include both.
Now if you are using a .nuspec file to configure your nuget package, you can use SynXsiS answer to include the file to both directories:
<files>
<file src="Configuration\MyXsd.xsd" target="content\TargetFolderName" />
<file src="Configuration\MyXsd.xsd" target="contentFiles\any\any\TargetFolderName" />
</files>
However, if you want to configure it in the .csproj file of SDK projects, you have to add the file you want to include in the nuget package into the project file with the following properties:
<ItemGroup>
<None Include="MyXsd.xsd">
<Pack>true</Pack>
<PackagePath>contentFiles\any\any\TargetFolderName;content\TargetFolderName</PackagePath>
</None>
</ItemGroup>
The any\any\ part of the path for the contentFiles specifies for which language (cs, vb, ...) and target framework the file is meant.
Note, that the item not necessarily has to be of type "None" it could also be "Content" and others as described here.
You can find all information for this structure here, general information of the folder structure can be found here and help for the SDK style projects here.

Is NuGet suitable for downloading runtime binaries?

Is NuGet suitable for pulling down assemblies which are not required for compilation, but are at runtime? I have a Visual Studio solution which contains a number of NuGet packages required for compilation - these packages are not kept in source control. At runtime there are a couple of extra dll's which are required. Would it be bad practice to create a VS post-build step which calls NuGet.exe to download these packages and then copies the binaries to the required location? It doesn't look like the intended use of NuGet, but I don't see any obvious flaws with this approach.
I not sure if this would be a good way to do it, but it might solve your problem:
Create a NuGet-package with the DLL's in question as content. You should have the following in your nuspec-file:
<files>
<file src="path\to\dll\one.dll" target="content\dlls\one.dll" />
<file src="path\to\dll\two.dll" target="content\dlls\two.dll" />
</files>
When installing this NuGet package in your project, you'll get a folder dlls added to the project root. You can then go to the property tab of all the included files and set Always for Copy to Output Directory.

Resources