Different references to the same library in two versions of a project - visual-studio

I have two versions of same project. Both have a reference to the same DLL, but at different locations.
The first csproj includes:
<Reference Include="Microsoft.Expression.Effects, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\3rdParty\Microsoft\Microsoft.Expression.Effects.dll</HintPath>
</Reference>
The second csproj, which uses a NuGet package, includes:
<Reference Include="Microsoft.Expression.Effects, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\3rdParty\NuGet\packages\Microsoft.SDK.Expression.Blend.1.0.0\lib\net45\Microsoft.Expression.Effects.dll</HintPath>
</Reference>
I try to understand the reason for that. Can I use the same hint path for them? Which to choose?

First Project
The Microsoft.Expression.Effects.dll was copied to the ..\..\..\3rdParty\Microsoft\ directory manually and then referenced in Visual Studio by e.g. right-click on the project then Add > Reference... > Browse... and selecting the DLL in the corresponding directory.
Your former co-worker most likely copied the library from the local installation folder of the Expression Blend SDK (or somewhere else) to a folder in the solution, so that it is always available. Otherwise the library would be referenced from the local installation folder and everbody working on the project would have to install the SDK to the same location or else the reference would not be found.
Second Project
In the second case a NuGet package was installed to the project via packages.config. This is just one mechanism to manage packages in your project that stores the information about referenced packages in a file called packages.config in your project. To install a package, right-click the project and choose Manage NuGet Packages.... In the tab Installed, you will see that you use the Microsoft.SDK.Expression.Blend package.
A package can contain a variety of different artifcats like DLLs. The power of packages is that you can manage dependencies much more conveniently than with the common way of referencing DLLs like in the first project. When you install a package, the contained libraries will automatically be referenced in your project file. You do not add or modify these references yourself, the package manager does that for you. Let's have a look at the HintPath.
..\..\..\3rdParty\NuGet\packages\ is the root path where the packages are installed and extracted
Microsoft.SDK.Expression.Blend.1.0.0\ is the root of the concrete package in version 1.0.0
lib\net45\ is the package internal path for libraries for .NET Framework >= 4.5
Can I use same hint path for them? Which to choose?
As you can see, the question is more like whether you should use NuGet packages or reference libraries manually. This depends on the requirements of you project. In general, I recommend to use NuGet packages, since they make it much easier to manage dependencies. However, if there is no package for the library you need, you will have to add references yourself.

Related

Where does the "Go To Definition" version number come from?

In Visual Studio 2019, if you right click on a symbol, you can select "Go To Definition". If the symbol is not defined in your code, it will attempt to generate the code from the dll.
When it generates this file, it puts a #region comment at the top of it. This is an example of what my region comment looks like:
#region Assembly Logging.Client, Version=6.0.1.0, Culture=neutral, PublicKeyToken=null
// C:\Users\myUserId\.nuget\packages\logging.client\7.0.0.43\lib\netstandard2.0\Logging.Client.dll
#endregion
The key part is that it says Version=6.0.1.0. I opened up the NuGet file, and, on the properties of Logging.Client.dll, the version says 7.0.0.43:
So, my question is: Where does the version number shown on the line of the #region comment get pulled from?
NOTE: I looked at this similar question, but the steps of deleting the existing packages, restarting Visual Studio and rebuilding did not resolve my issue: Latest version of nuget package still not up to date
Where does the “Go To Definition” version number come from?
It is from AssemblyVerion attribute on VS and it is set in your nuget project by the nuget author.
Please see the below interpretation.
===================================================================
I assume that logging.client nuget package is your own nuget package.(created by yourself)
This is a normal behavior of the nuget and assembly mechanism. It is not an issue and it is just defined that way by the author of the package.
These make sense and are defined by the author when the nuget package is created and can be modified by the author. It's just that they have different functions from each other to deal with the mechanism of nuget.
The Version=6.0.1.0 is the assembly version of the dll which used by framework. It is a built-in version number which is used during build or used at runtime. It can only be accessed by vs internally. To be precise, this is its real version number.
And File Version 7.0.0.43 is the version of the dll, which is used for external display and can be accessed externally.
And Product Version 7.0.0.43 means the nuget package version which also can access outside VS.
So, they all are defined by the author as he want.
See this official document about the function of these attributes: Use AssemblyVersion and AssemblyFileVersion attributes.
They all have professional terms in VS:
AssemblyVersion means 6.0.1.0, AssemblyFileVersion means File Version 7.0.0.43 and NugetVersion means Product Version 7.0.0.43. And they can be also access outside VS.
====================================================
In my side, I created a net standarad class library project called ClassLibrary1.
Right-click on your net standard class library project, right-click on your project Properties-->Package
1)
The Assembly version is used under Logging.Client, Version=6.0.1.0, Culture=neutral, PublicKeyToken=null.
When you install that package on the main project, on the main project, click on the dll on the References and you will see the internal version 6.0.1.0 under the Properties Window.
And when you install this package on a net framework project with packages.config, it will shows on the csproj file:
<ItemGroup>
<Reference Include="ClassLibrary1, Version=6.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClassLibrary1.7.0.0.43\lib\netstandard2.0\ClassLibrary1.dll</HintPath>
</Reference>
The version is used by the internal framework and at build or runtime and only be seen in VS.
2)
The Assembly File version is the file name, it shows on the dll's properties and shows outside VS as File Version which you described on the case.
3)
The Package Version is the version of the nuget package rather than the assembly dll version. They're different concepts.
In your side, it shows like this:
<ItemGroup>
<Reference Include="ClassLibrary1, Version=6.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClassLibrary1.7.0.0.43\lib\netstandard2.0\ClassLibrary1.dll</HintPath>
</Reference>
And in the dll's properties, it shows as Product Version.
Overall,it is not an issue and each of them has a meaningful and specific function. If you want to change this, you should change your nuget project's Properties-->Package as I said above, modify them as the same. Then, repack its as nuget package.

Reference nuget package project from another nuget package project in same solution

I am creating couple of .NET Standard 1.6 libraries that I want to publish as Nuget packages. They share a common libary that is a 3rd project in the same solution as the first two. The shared library has no value by itself, but I am assuming that if I want people to use both of these two libaries in the same project I should publish the shared library as a Nuget package as well. If I don't I am worried about multiple copies of the same shared library "colliding" or not properly warning when there are version mismatch issues.
Am I correct that the shared library needs to be a Nuget package as well? Is there a way to reference the shared library as Nuget package, but use is as if it was a project reference when developing / debugging the 2 main libraries in this solution? If I had to publish to Nuget.org and wait for the package be propagate through the Nuget.org system before using a changed version in a debug session that is REALLY going to slow down development. Note that these are .NET Standard projects. I found How to reference related projects in the same solution when Nuget packages are the required output but that doesn't seem to work with .NET Standard (getting errors during pack) and I am also not sure if .NET Standard not using nuspec files anymore also would cause a problem.
I am also not sure if .NET Standard not using nuspec files anymore also would cause a problem.
The .NET Standard still using .nuspec files, and using old school nuget pack and a .nuspec will resolve this issue.
As per document dotnet pack:
NuGet dependencies of the packed project are added to the .nuspec
file, so they're properly resolved when the package is installed.
Project-to-project references aren't packaged inside the project.
Currently, you must have a package per project if you have
project-to-project dependencies.
So, to include project-to-project references in NuGet packages, you need manually maintain a .nuspec file and add dependencies. You can refer to the Create .NET Standard packages with Visual Studio 2015 for detail info.
Besides, dasMulli has provided a simpler way to do this by involving adding and hooking up a custom target :
<Project>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\testprivatelib\testprivatelib.csproj" PrivateAssets="All" />
</ItemGroup>
<Target Name="IncludeP2PAssets">
<ItemGroup>
<BuildOutputInPackage Include="$(OutputPath)\testprivatelib.dll" />
</ItemGroup>
</Target>
</Project>
The source code comes from: "donet pack" is not including project references

NuGet newbie mayhem

I'm really new to NuGet and having all kinds of trouble with it. So the latest problem is that I generated a bunch of .nupkg files and put them in a shared folder on the network and then set NuGet up to look there for updates. So let's say in the folder I have:
Author.library.2.1.0.nupkg
Author.library.2.2.0.nupkg
Author.library.2.2.1.nupkg
I then found out that the target framework (.net) is different for some of my projects (under the same solution), so I generated new packages for each target:
Author.library.net40.2.1.0.nupkg
Author.library.net40.2.2.0.nupkg
Author.library.net40.2.2.1.nupkg
Author.library.net45.2.1.0.nupkg
Author.library.net45.2.2.0.nupkg
Author.library.net45.2.2.1.nupkg
Next I right-clicked on the solution and chose Manage NuGet Packages for Solution and then went to Online, pointed to the Installed Packages and was able to install each package to the applicable projects (.csproj files). But now when I open the NuGet Package Manager for the solution and click on Installed Packages, all I see is once instance of library. If I click on it, on the right I can see that it's pointing to the Author.library.net45 package, but I have no way of seeing the .net40 version of the library. So I can't add it to the .40 projects.
And lastly, what if I want some of the projects to point at an older version of a package. I know that I am suppose to be able to specify that in the packages.config file:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Author.Library" version="2.2.0" allowedVersions="
[2.0.0,2.3.0)" targetFramework="net45" />
</packages>
which should load anything above (and including) 2.0 through 2.3)
or
<package id="Author.Library" version="(,2.4.0" targetFramework="net45" />
which should load any version below 2.4.
So my main question is why can't I see the two versions of the package in the NuGet Package Manager? And also, how do I best limit the versions that will apply to a particular library.
It looks like you cannot see the different packages since they both have the same package id of Author.Library. This is based on what you have shown in your packages.config file.
Also I would not have separate NuGet packages just for assemblies that target different frameworks. Instead put them in a single NuGet package in their own lib directory (e.g. lib/net40 lib/net45). You can have multiple assemblies targeting different frameworks in the same NuGet package. NuGet will pick the best match when installing the NuGet package into the project. Also note that you can use a NuGet package that contains just .NET 4.0 assemblies with a .NET 4.5 project since the assembly is compatible.
The allowedVersions attribute in the packages.config file is the thing to use if you want to restrict the NuGet packages that a project can update to.

Visual Studio Project template add packages.config without downloading Nugets

I have .vstemplate file which has a reference to the Nuget like this:
<WizardExtension>
<Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName>
</WizardExtension>
The default behavior is that VisualStudio will go online, get needed packages, create packages.config and put references in there. But if you are offline, VisualStudio will throw an exception saying he cannot find packages and will not create package.config.
Now, is it possible to override that behavior? I want to get packages.config file regardless of the VisualStduio ability to download packages.
is it possible to override that behavior?
The answer for this questions is negative.
As we know the packages.config, The packages.config file is used in some project types to maintain the list of packages referenced by the project. If we install package to the project, nuget will add the packages.config to the project automatically. If you do not have any packages installed, the packages.config will not be added. This is the default behavior of nuget. It is so designed.
Besides, as far as I know for the template with preinstalled packages, to add preinstalled packages to your project template you need to:
1. Edit your vstemplate file and add a reference to the NuGet template wizard by adding a WizardExtension element
2. Add the list of packages to install in the project
There is no override for nuget default behavior. So If you want to override the nuget default behavior via Visua Studio template is not possible.
As a suggestion, your question is about challenging the design of nuget, you can ask this question on the GitHub.

Change reference path from GAC to folder at compile time

I have a project that depends on some 3rd party libraries. These assemblies are registered int the GAC. Everythings works fine so far.
But when building the project on the build server, the 3rd party assemblies are not in the GAC, but in an extra folder (called external) that is also in the SVN-repository the build server uses.
The build will fail due to the fact that MSBuild can't find these assemblies. Is there a way to tell MSBuild on the buildserver to use the assemblys from this folder instead of the GAC?
The best practice is NOT to reference 3rd-party assemblies from the GAC on build time. Instead, have all 3rd-party assemblies referenced from a common source controlled folder.
If you open the projects with an editor, ideally you will have a HintPath for each 3rd-party reference. I.e:
<Reference Include="Microsoft.Practices.Unity">
<HintPath>..\..\..\3rd Party\Prism4\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
This should work
MSBuild.exe "%BUILD_TARGET%" /t:rebuild /p:OutputPath="%OUTPUT_PATH%" /p:ReferencePath="%REF_PATH%"
The relevant bit would be the 'ReferencePath' parameter ofc :)

Resources