Get current version of package outside of Visual Studio - nuget

We are migrating over to using packages and NuGet for managing our dependencies on 3rd party components. This works well when referencing packages from within Visual Studio or building on the build server via msbuild.
However there are a number of files that we would like to access in our build scripts and installers. Previously these would be in source control with a well known path, now as the version of the package that we are consuming changes so the path to the package and hence the files is changing.
Is there a simple way I can get the path to a given package? The best solution I currently have is to search for all packages.config files and extract the package version from them.
Examples of the files that we need to access are
The NUnit console executable from the NUnit.Runners package for running unit tests.
License files from various packages that we redistribute with our installer.

Using the packages.config file is a pretty good solution. NuGet itself uses two approaches:
Reading the package information from the packages.config and using that to resolve to the packages path.
Enumerating all the directories in the packages directory.
You could use NuGet.Core to do either of the above if you do not want to write the code yourself. The classes that can be used are the DefaultPackagePathResolver, the PackageReferenceFile and LocalPackageRepository or SharedPackageRepository.
One problem with the second approach is that sometimes NuGet may occasionally leave behind NuGet packages that are not necessarily referenced by a project. In that case looking at the package directories may give you the incorrect information.
The only other approach I can think of might be to read the project files looking for the assembly references. Although that would not work for a solution level package such as NUnit.Runners.

Related

How to wrap a NUnit Engine Extension as a NuGet package?

I am working on a nunit engine extension which will be shipped as a nuget package.
Following the advises in How to implement NUnit's NUnit.Engine.ITestEventListener i was able to write the extension.
This solution is working as long as the project which contains the extension (the .cs file as well as the .addins file) is being imported to the target project which will perform the nunit tests.
As soon as I create a nuget package (following Quickstart: Create and publish a NuGet package using Visual Studio (.NET Standard, Windows only)) from the extension project and install this package to a test project, the extension doesn't work anymore.
I assume there is a problem with providing the .addins file within the nuget package so that the nunit engine in the target project can find the extension.
I already tried to ship the .addins file within the nuget package by adding the following lines to the .csproj file of the extension project.
<ItemGroup>
<Content Include="file.addins">
<Pack>true</Pack>
</Content>
</ItemGroup>
If I add the .addins file to the target project by hand, the engine extension starts working.
How can a nunit engine extension be shipped as a nuget package without any adjustments by hand?
Im using NUnit(3.13.2).
Im quite new to nunit, nuget and writing questions on stack overflow. So if I'm missing something obvious here, I'm sorry.
This is one of those areas where I wish things were less complicated, unfortunately. Since extensions are found through a relative path from the NUnit engine to the package content, it depends on where both the engine and runner are located and where the package is located on your machine.
Here are some initial guidelines...
How to structure the package itself... your extension assembly itself should be in the tools directory. If there are other assemblies with it, which it references, it's best to also include a .addins file in the same directory, which lists that assembly on a single line. That way, the NUnit engine will save time by only examining the extension assembly.
A NuGet extension package will automatically be found by the engine if the runner has been installed as a nuget package as well. This works no matter how the packages are installed on your machine, i.e. using packages.config or in a nuget cache, provided both packages were installed the same way. (That proviso is a real gotcha and it may be that a future version of the engine needs to actually understand nuget.) See the addins file provided with the the NUnit 3 console runner as an example of why this works.
The same thing is true if both the runner and the extension are installed as chocolatey packages, because they are both in the chocolatey cache. If you do provide one (which I recomend) it has to be a "native" package - one that includes the actual binaries. A chocolatey package that merely invokes the nuget package will not work. See the source for any of the NUnit-provided extensions for an example of how this this is done.
If the executing copy of the engine (usually in the same directory as the runner) is anywhere else, there is no automatic way for the extension to be found. This includes the case where you are building a runner yourself and want the extension to be available while you are developing. In that case, you need to fully understand how the engine finds extensions (see the docs) and manually create an addins file (next to any that was distributed with the engine) containing the proper relative path.
This is especially complicated if you are developing an extension for general release. Then you have to deal with various runners installed in different ways by different people. OTOH, if you are doing this for internal use in your company, you may only need to deal with one of them. If you add more specifics about your goal to the question, I'll edit this with some more specific suggestions.

Install NuGet package with dependencies into same folder

I have a project (a PowerShell module) that relies upon a NuGet package, whose assemblies are loaded into my module via the Add-Type cmdlet. I would like to install this package via NuGet instead of manually copying it into the correct folder. This would save me from committing it's binaries to source control. Also: when thinking about CI/CD, I'd hate to have them in my repo.
I know I can curate a packages.config file and use nuget install instead. But this command installs the package together with it's dependencies into a separate folder and therefore the framework will (runtime) not find the required dependencies.
I know I could also provide a script that performs the nuget install and then copies the required .dll files into a single folder. But I would have to deal with the fact that the package might have different versions for different target frameworks and I'd need to handle the compatibility. Or maybe the package has other additional required files that I know nothing about.
So here my question: there has got to be a simpler way to do this? Something less ... circuitous and cumbersome?

How do I correctly install nuget packages outside of VS and keep track of them?

I'm trying to use nuget.exe outside of Visual Studio as part of our build infrastructure. The idea is that the various build tools are fetched by a bootstrapper script that initializes a working copy. The bootstrapper does this by using a file that specifies the required tools and their version.
Broken approach 1 - use manually edited packages.config
At first, it seemed like a good idea to keep a manually edited packages.config file and use nuget restore to install them during bootstrapping. However, this does not work for tools that have dependencies, unless I list every single dependency in the packages.config as well, a much to arduous approach to be feasible, because I found no easy way to recursively find all dependencies of a package.
See also using nuget.exe commandline to install dependency .
Broken approach 2 - use nuget install to update packages.config
The second idea was then to use nuget install to install the packages, and let that command update the packages.config, very similar to the Install-Package cmdlet in the package manager console. But, surprisingly, nuget install does not support this! It either takes a packages.config or a package ID as parameter, but I found no way to update the packages.config with the new package and its dependencies.
This problem can also be found in another (two year old) SO question, see nuget.exe install not updating packages.config (or .csproj)?.
Is there a working (and non-hacky) approach at all?
This must be a problem that many people face when using nuget outside of VS, so what is the best approach in that case?
Of course, I could just parse the packages.config and emit a nuget install for each package, but I really don't want to re-invent the dependency management part of nuget, this is what I'm using nuget for in the first place. So I'm left with the feeling that either an -WithDependencies switch on nuget restore or an -UpdatePackagesConfig switch on nuget install is missing...
Note that there are other SO questions regarding the broken approaches described above. What I'd like to know it what the best approach is to solve the root problem, i.e. manage packages with dependencies outside of VS.
nuget install does not currently make changes to the project file.
nuget install can be used to either restore the NuGet packages listed in a packages.config file or download and extract them.
If you do not need the project being modified then your solution of reading the packages in the packages.config file and calling nuget install seems like a reasonable approach.
If you need the project to be modified then you could look at one of the following:
Ripple - a command line tool that adds extra features to NuGet. It has a ripple install command line which is similar to nuget install but it also updates the project file. It has a lot of other features for supporting build servers so this might be a good fit.
NuGet packages outside of Visual Studio with SharpDevelop - this was an experiment I put together to see whether full NuGet support could be achieved, including PowerShell scripts, from the command line without using Visual Studio. It uses PowerShell and quite a bit of SharpDevelop.
Customise NuGet.exe to do what you need. nuget update, for example, does modify the project file, at least for file references, but will not run PowerShell scripts. So you could take the NuGet.exe source code and extend it.
Of the above only 3) would give you exactly what you need. The other two would require a bit of work to read the packages from the packages.config file or some other list and then install them.
See my answer to Why does the nuget command line tool not follow dependencies?
nuget install My.Package.Id will follow dependencies. However, if you want to install multiple packages, you will need to create a batch file with a separate nuget install command for each package. These are top-level packages. You don't need to "install" the dependencies, as they will get downloaded automatically.
If you ultimately want a packages.config file, I imagine you can generate one by enumerating all the packages that were downloaded. However, you would have to take care not to include multiple versions of the same package.
I believe that how nuget 3 works with project.json files may do what you are looking for. Essentially my understanding is that the unit of dependency becomes the package and not necessarily individual assemblies. From what I recall, the idea is the have only one place to manage these types of package references which the project (IDE/Editor), package manager, and other command line tools can use.
What I don't understand and feel somewhat frustrated about is that it appears that the project.json concept is being canceled. I don't know if plans are to reintroduce it at anytime in the future. In the mean time I keep on hearing updated info on tooling that takes advantage of project.json such as nuget so where you can actually rely on this is something that is unclear to me at this point.

How to best use NuGet for source file deployment

I would like to use NuGet packages for building packages for core helper libraries which I would like to add as source files into other projects. I want to use source files instead of libraries for several reasons, the main one being that I need them in SharePoint Projects, which is on the one hand much easier to deploy than additional libraries, and on the other hand helps to reduce version conflicts.
I know that I can add the source files as content to NuGet Packages, which would install them with the package. But this won't work together with package restore, and I don't want to have these files checked into source control in all projects.
Is it somehow possible to make a NuGet package which doesn't copy the files to the project, but instead adds file links, which point back to the file in the package folder, to the project? I think this approach would solve my use case.
Thanks
pascal
It is possible to add linked files with the use of PowerShell scripts, for example with this NuGet script: http://www.nuget.org/packages/Baseclass.Contrib.Nuget.Linked/

Nuget - packing a solution with multiple projects (targeting multiple frameworks)

Say I have the following solution with multiple versions of the same code each targeting a different framework and I would like to generate a nuget package from it.
SharedLib.sln
SharedLib.Net35.csproj
packages.config
SharedLib.Net40.csproj
packages.config
SharedLib.Phone.csproj
packages.config
SharedLib.SL4.csproj
packages.config
The expected nupkg has the following structure
SharedLib.1.0.nupkg
lib/net35/SharedLib.dll
lib/net40/SharedLib.dll
lib/sl4-wp/SharedLib.dll
lib/sl4/SharedLib.dll
nuget.exe pack SharedLib.SL4.csproj will automatically determine that the target framework is SilverLight4 and place the binaries in lib/sl4
I know I can add a SharedLib.SL4.nuspec file with a <file> section to include binaries from the other projects but is there a way to make nuget automatically place the combined solution output into the proper structure (and also detect dependencies in packages.config from all projects?
No, there's currently no way to do this other than to write a custom build script that puts the files in the right place and then runs NuGet pack on them, or to take the .nuspec approach you described.
This is a feature we'd like to have, but haven't thought of a good way to do it. However, your post just gave me an idea.
Today, you can point nuget pack at a .csproj file.
We could consider an approach that allowed you to point it at a .sln file and if the project names follow some convention, we'd package all the projects into a single package.
If you really want this feature, consider logging an issue in the NuGet issue tracker. http://nuget.codeplex.com/workitem/list/basic