Using NuGet when developing several dependent projects locally - nuget

The problem I want to solve is how to work with NuGet on several local projects that depend on each other without having to copy files around manually and have all sorts of dll issues as a result.
Today my projects (c#) are not using NuGet (working to move them to NuGet), and the way it works is that when working locally all projects build outputs to a "shared bin folder" and all reference from there, so that you alway see the right binaries you are building locally.
On the build server, through some games in the csproj files, projects reference a non-shared bin and get the dependencies there.
How can I achieve the same effect with NuGet? What is the right way to work locally without having to copy dll around manually? (And of course keep the ability to build in the server by getting everything using NuGet normally)
Is there a way to get packages to one bin folder with NuGet or at least folders without version numbers so I can just build and reference from there? And is this even wise?
Assume the latest NuGet, VS versions as required.
Thanks a lot for your help,
Roy.

Related

Why are there similar Nuget package folders in .nuget\Packages directory?

Under c:\Users\<USER NAME>\.nuget\packages\ directory, there are some folders looks similar, for example:
System.IO.FileSystem.4.3.0
system.io.filesystem (and there are sub-folder "4.3.0" under it)
See attached figure.
My question: why are there similar Nuget package folders in .nuget\Packages directory? Can I delete one of them?
Possibly you used an old version of NuGet or Visual Studio on your machine, which used the old format. The other option is that you have a nuget.config that forces that solution packages folder to be your user profile's global packages folder. I really don't recommend this.
Maybe starting with NuGet 3.0 (Visual Studio 2015), NuGet uses the tolower(packageid)\tolower(packageversion)\ folder structure. I'm too lazy to test old versions to validate that earlier versions used something different. Or maybe NuGet has always used the same format for the global packages folder, making the packages.config answer the only possibility. But I really think that lowercase normalisation was something that was added and didn't always exist.
projects that use packages.config have always used the unmodified PackageId.PackageVersion format in the solution packages folder. I believe it was deemed too risky as a breaking change that some customers depend on to change in the solution packages folder. So, if anyone had the misguided idea that they could save disk space by making all their solutions share the same packages folder by using the same one for all solutions, and the folder they used is the global packages folder, then the two different parts of NuGet which intentially use different folder naming conventions, will write to the same directory.
As long as you're not in the middle of a build, it's always safe to delete folders in any packages folder (global packages, as your question is about, or a solution packages folder). If a project needs a package that was deleted, NuGet will download it again, so if you have a download quota, or a slow internet connection, maybe be mindful. Otherwise you can be as liberal with deleting folders as you like. Just make sure to delete the entire folder. There's only one file NuGet looks for when restoring, so if you delete other files but leave that one, NuGet will think it's downloaded and extracted properly, but your machine will behave differently to other machines.

How to prevent NuGet version drift in a big monolithic (sigh :-() application (multiple solutions, many projects in each)?

We are building all the solutions to a shared bin directory. Having different projects reference different versions of the same dependency is not healthy for our build.
So, we consolidated the dependencies - great. But now the versions start to drift again. We do not want to consolidate them manually every now and then - we want to prevent the drift completely.
Why we do not want to use Paket? The main reason is that it seems we would lose the ability to migrate the NuGet package dependencies to the new PackageReference items in the projects. So, currently we have package.config files, but we plan to replace them with the respective PackageReferences. That means we will use internal NuGet support by msbuild, which seems to leave no place for Paket.
Now, I assume we are not unique in this world and others have the same problem as we are. How do you solve it?
EDIT 1
We have our internal NuGet repo, but we use it for dependencies which do not have organic representation in Nuget.org and for sharing our own internal packages.
One approach is to consume only from the internal NuGet repository. This has challenges, like:
Who uploads the dependencies there? Developers? But then how to make sure they do not upload different versions of the same dependency? Dedicated people? Then they become a bottleneck.
Small thing, but we need to block commits to the central NuGet.config
Uploading a dependency to the internal NuGet repo is not immediate. You cannot just download it from NuGet.org and upload to the internal one, because that would miss any transitive dependencies. So, a process should be built around it.
It is all possible, but I am reluctant to go down that route ... Must be a better way.
EDIT 2
While we do plan to migrate to PackageReference, it will take time. And unfortunately as long as we have Silverlight (another year, at least) a whole bunch of projects in the dedicated Silverlight solution (80+) will not be migrated to PackageReference, because by doing so it becomes impossible to debug the code with VS 2015.
Next, suppose we do migrate ALL the projects and then externalize all the PackageReference items to a single targets file imported by all the projects. This is feasible when using a shared bin directory as we plan to do. But when inspected in VS 2017 this setup communicates a wrongful picture that every single project depends on the entire set of NuGet dependencies.
I would rather avoid this.
Once you move to PackageReference, you can take advantage of MSBuild. For example, you can have a MSBuild file that contains all your dependency versions. It could be a file that you need to <Import ... /> in all your csproj files, or you could use Directory.Build.props. Finally, in each of your projects, change the version number in any <PackageReference to a MSBuild variable that uses the property you previously defined. Most of Microsoft's open source repositories use this technique, with minor variations about file names and whether it's imported automatically with Directory.Build.props, or an explicit <Import ... />.
While you can still use the Package Manager UI in Visual Studio to check for updates, you won't be able to update the package versions with it (at least, it won't preserve how and where the versions are defined). However, just make sure your MSBuild file that defines the versions is in your solution, so you can trivially open the file in Solution Explorer and then type the new version number in. Adding new package references is slightly more effort, but it's generally not done often, and it's still very easy with SDK-style projects, since Visual Studio lets you edit the csproj while the project is still loaded.
Since you didn't accept the other solution, maybe you could take a look at paket
It's a package manager for dotnet than (among other feature) holds solution wide dependency lock file. It is very customizable, and while it solves LOTS of problems, as any tool, creates some new ones. In my experience, the new ones are far less infuriating :)

CruiseControl.NET NuGet not working

My CruiseControl.NET build server is not able to restore the nuget packages of my projects. According to some websites it should be enough to set the environment variable EnableNuGetPackageRestore to "true" and restarted Cruise Control after that, but that didn't help in my case.
What else can I do?
Do i need to install something that "enables" Nuget?
I noticed I have a .nuget folder in C:\Users\MyUser\ but I don't have this folder on the build server. Is this required? Who created that on my pc? Visual Studio?
Without seeing the project config, I am assuming you are using either a Microsoft Solution or project, and are building from that using the msbuild task in CC.net. If so, your Solution needs a .nuget folder structure (in the same location as the sln/prj file there needs to be a .nuget folder, inside that folder, you need a NuGet.Config and a NuGet.exe as well as a NuGet.targets).
This should be automatically added to your solution if you right click on it inside visual studio and select "Enable nuget Package Restore".
You can find more information # Nuget Documentation. There is quite a few ways to skin this cat, but, based on your initial statement, you are just missing the .nuget folder in your Solution, and once added it should just work. Otherwise, you have to look at pre-build tasks, and that gets a little more detailed than is usually necessary.

Get current version of package outside of Visual Studio

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.

Managing dependencies with Eclipse and CVS

I have a bit of code for a dll that is needed by two or more projects in eclipse. Currently each project has a copy of the code and builds the DLL separately. I want to separate the dll code into a separate eclipse project so there is a common location. But I want to avoid the situation where we have to build the dll in the one project, then copy the dll back to the other projects and check the dll to each respective project. This will create a dll for each project that isn't traceable to the exact code that it was built with.
Is there a way to somehow symbolically link the dlls to another eclipse project that is using CVS as the version control system so that it is possible to tell which version of the code was used to create the dll? Am I making this too complicated or missing something obvious?
I thought about working sets in the package manager for eclipse, but I have to investigate more on how to use them with CVS to avoid making it a nightmare for the next person who checks it out and can't figure out why their project won't compile.
Thanks.
What about creating a new folder in a separate project. In the advanced section of creating a new folder there is an option to link to another location on the file system.
Or you could also create a container project that makes use of a projectset.psf file. Have the projectset file link to the different projects in your repository. When you want to check out that project, check out the container instead and right click on the projectset file and select Import Project Set...
If you are working with one workspace, you end up with three projects, each mirrored in CVS: One is the dll, the others are the projects using the dll (configured as a project dependency of these projects upon the dll project).
With three projects I wouldn't aim for working sets - they are good for managing a lot of projects within one workspace, for three projects, I'd consider them overkill. I usually tend to aim for several workspaces instead of working sets.
Regarding the next person working with these projects: You need to keep some kind of documentation about how to setup your projects. You might say that your eclipse project files do just that (as they define a project dependency upon another project) but this is for the machine - humans tend to like other communication means.
If you are worried about changes to the dll being incompatible to one project (because the person applying these changes doesn't care about the other project), aim for a build server. This will build all projects and dependent projects whenever something under version control changes, run all tests, provide a build number and package it all ready for use. This way you can be sure that - whatever is in your deliverable - can be reproduced, because the buildserver is not able to make local (uncommitted) changes to the code. Also a buildserver will signal failure (either broken API or broken tests) at the moment of the last commit (well - a few minutes later) and place the burden of repairing the damage on the one causing the damage.