Visual Studio Online - How to deal with nuget packages in this situation? - msbuild

We recently moved from one big SLN file to multiple ones. So now the folder structure is like this:
Root
Solution1WebApp
packages (folder)
Project1 (folder)
Project1.csproj
NuGet.config
Solution1.sln
Solution2Libraries
packages (folder)
Project1 (folder)
Project1.csproj
Project2 (folder)
Project2.csproj
NuGet.config
Solution2.sln
Solution3UnitTests
packages (folder)
Project1 (folder)
Project1.csproj
Project2 (folder)
Project2.csproj
Project3 (folder)
Project3.csproj
NuGet.config
Solution3.sln
When I check-in in Visual Studio Online, a build is triggered. This build is configured to retrieve nuget packages (so the packages folders are not checked in).
In the csproj files of Solution1, I configured all the paths pointing to packages to be like this:
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\Solution1WebApp\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
But the build keeps failing and I get warnings like this:
C:\Program Files (x86)\MSBuild\14.0\bin\amd64\Microsoft.Common.CurrentVersion.targets (1819, 5)
Could not resolve this reference. Could not locate the assembly "Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
And I think these warnings are causing exceptions such as:
The type or namespace name 'xxx' does not exist in the namespace 'yyy' (are you missing an assembly reference?)
So am I missing something? Are the paths correctly configured?
Thanks for any help.

Ok I found the answer. The packages path must remain without the solution name:
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
In VSO build definition, I added a build step for each of the solution (one step for the Libraries, one for the Unit Tests and one for the Web App).
This way, each solution is being built and the paths can remain the same as locally on our PC.

remove the references and the items that it mentions in the packages.json file.
add them back in to the project within the solution that its doesn't find the files.
save and commit.. worked for me.

Related

Copy dll into subfolder in output directory when using NuGet

Let's say I have some NuGet package that contains c++ dll and interop for this dll. When I install this package, I see that my scproj file gets updated with the following reference:
<Reference Include="Interop.MyCppAssembly, Version=1.1.1.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\MyNuGetPackage.1.1.1.1\lib\Interop.MyCppAssembly.dll</HintPath>
<Private>False</Private>
<EmbedInteropTypes>False</EmbedInteropTypes>
</Reference>
You can see that HintPath points to the folder where my packages are installed. You can also see that I set Copy Local to false so Interop.MyCppAssembly.dll won't be copied to my output directory (let's call it bin) during the build. I did it intentionally, because I don't want to put any third party dlls into my bin folder to avoid mess in my output directory. Instead, I would like to create a subfolder in my bin
like bin\ThirdPartyLibs and put all third party dlls there.
But how can I do this? I know I can set CopyLocal to true, and then use Post Build Event to move Interop.MyCppAssembly.dll from bin to bin\ThirdPartyLibs but I don't like this. Is there any other solution how to copy dll to the subfolder of the output directory during the build?

Issues with MsBuild, SpecificVersion, and VSTS

The scenario is as follows:
We have a set of common .net libraries:
CommonLib.Main
CommonLib.Specialized
We have a CI build that builds both of these libraries, and places them into our NuGet repo. Both are available as individual NuGet packages - a user may want to load just Main, or they can pull the Specialized package, which will include Main.
Specialized references Main as a Nuget package.
I'm currently making some upgrades to these packages.
First, I upgraded Main. I updated the version of Main in AssemblyInfo from 1.1.0. to 2.0.0.
MsBuild will include the build number in the "*" location.
The CI Build ran, and a version of Main called "CommonLib.Main, version=2.0.0.345" was published to our NuGet repo. On the Nuget repo, the version is listed as "2.0.0", as I would expect.
Next, I upgraded CommonLib.Specialized, and I updated the NuGet reference to CommonLib.Main, version=2.0.0.
I checked in these changes, and the CI build ran again.
So now, the CI build has create a new version of Main, with version 2.0.0.346, and placed it on the NuGet repo.
Here's the problem:
Now, when we run our CI build again, the build of CommonLib.Specialized fails, because in the .csproj, it looks like this:
<Reference Include="CommonLib.Main, Version=2.0.0.345, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CommonLiib.Main-2.0.0\lib\net461\CommonLib.Main</HintPath>
</Reference>
But, in packages.config, it has
<package id="CommonLib.Main" version="2.0.0" targetFramework="net461" />
Which pulls down CommonLib.Main, Version=2.0.0.346.
Our build fails here:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\amd64\Microsoft.Common.CurrentVersion.targets(1964,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "CommonLib.Main, Version=2.0.0.345, Culture=neutral, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
For SearchPath "{HintPathFromItem}".
Considered "..\packages\CommonLib.Main-2.0.0\lib\net461\CommonLib.Main.dll",
but its name "CommonLib.Main, Version=2.0.0.**346**, Culture=neutral, PublicKeyToken=null"
didn't match the expected name "CommonLib.Main, Version=2.0.0.**345**, Culture=neutral, processorArchitecture=MSIL".
I think I could fix this by setting SpecificVersion to false in the project, but that seems rather crude. Is there a better way to resolve this issue? I feel like I shouldn't have to refresh the NuGet references after every build.

MSBuild unable to find metadata file for PresentationCore

I am writing a MSBuild file for one of my .NET projects. I do not want to use the Visual Studio generated .sln and .csproj files for certain reasons. I am also aiming to get some experience writing my own build files.
One of my source files is referencing the System.Windows.Media namespace and the build failed with the below message
error CS0234: The type or namespace name 'Media' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?)
So I added the following snippet in my build file...
<ItemGroup>
<Reference Include="PresentationCore">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
I made changes in the CSC task as follows...
<Target Name="ReleaseBuild">
<MakeDir Directories="$(ReleaseDir)"/>
<Csc Sources="#(SrcFile)"
OutputAssembly="$(ReleaseDir)\$(OutputAssemblyName)"
TargetType="Library"
References="#(Reference);
$(LibDir)\MyOwnLib.DLL"
Platform="$(ProcessorPlatform)">
</Csc>
</Target>
only to get the following error - CSC : error CS0006: Metadata file 'PresentationCore' could not be found
Why is MSBuild not able to find the PresentationCore assembly in the GAC? Is there some additional version information that I should give? I searched in many forums but seem to be going around in circles and I would be glad for any useful pointers as to what the problem could be.
I am using MSBuild 4.0 on an x64 machine and building for an x86 target. My build files which referenced only the MS core libraries worked fine. My VS2008 projects also build fine.
Some Progress
I was able to progress in this issue by making the following changes...
1) I added a property to specify the path of the presentation core library - <PresentationCoreLibDir>C:\Windows\Microsoft.NET\assembly\GAC_32\PresentationCore\v4.0_4.0.0.0__31bf3856ad364e35</PresentationCoreLibDir>
2) Added an additional parameter to the CSC task like this - AdditionalLibPaths="$(PresentationCoreLibDir)"
3) Finally appended the .DLL suffix to the reference tag -
<ItemGroup>
<Reference Include="PresentationCore.DLL">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
I am relieved that I was able to get around this, but is there a neater way of doing this? I thought that the MSBuild engine would be able to figure this out in a more seamless way. Can anyone throw more light on this?
For x86 make sure you use the correct MSBuild which should be at:
c:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
Rather than the x64 MSBuild that is located at:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe

TeamCity - MSBuild unable to locate NuGet references

Attempting to build a C# project which has numerous references to assemblies in NuGet packages fails in TeamCity but works fine in Visual Studio.
Found in the log;
For SearchPath "{HintPathFromItem}".
[13:48:15][ResolveAssemblyReference]
Considered "..\packages\AspNetMvc.4.0.20126.16343\lib\net40\System.Web.Mvc.dll", but it didn't exist.
The reference in the project file is;
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\AspNetMvc.4.0.20126.16343\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
Any ideas? It seems like it's not starting from the correct directory so can't resolve "../packages" which exists one level above the .csproj file.
I know this has been answered, but maybe someone else has had the same problem I did.
My hint paths in my project file were incorrectly pointing to packages and changing it to ..packages fixed it for me.
So changing it from this:
<Reference Include="Newtonsoft.Json">
<HintPath>packages\Newtonsoft.Json.5.0.5\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
To this:
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.5\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
Fixed it.
I had restructured my projects since installing the NuGet packages so even though '../packages' was correct for the main project, it wasn't for the other projects which had been moved.
Uninstalling and re-installing the NuGet packages writes the paths correctly or more straightforward, doing a find and replace on the paths in each .csproj file.
My understanding at this point is based on the information here: http://youtrack.jetbrains.com/issue/TW-20525
But I am just diving into both TeamCity and NuGet at the same time (coming from CruiseControl.NET)
So what I did for the time being is to add a "NuGet Installer" build step before my vs.net solution build step and everything worked great.
You either need to add the packages directory to source control or enable nuget to automatically download packages (its a feature in the right click menu of nuget 1.6)
See http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
Sorry for resurrecting this old post, but in addition to the above excellent points (Tjaart, SeeNoWeevil, Luke), you might also want to check the property CopyLocal=true for the references that you nuget'ed down.
For myself, this has often been the one tiny oversight that leads to exactly the error that the OP was mentioning.
You can highlight the file in Solution Explorer and got to Properties, and verify that Copy to Output Directory is set to True
Ensure that the .dll and .pdb files are included in source control (or have been downloaded).
For TFS (not TeamCity), by default, .pdb files and .dll files are excluded. So double-check that all files for each package sub-directory have been included, not just the nuget .xml file.
Background: I came to this question with the same thought as some other posters - that the relative reference in the .csproj file might be incorrect. After using a path in the .csproj file to ensure that the reference was absolute with regards to the project...
<HintPath>$(MSBuildProjectDirectory)\..\.nuget\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll</HintPath>
..only to get the same error, I double-checked that the required files existed. I also did an MSBuild build on my local machine (as opposed to Visual Studio build), and it worked. Further investigation on the build server revealed that the specified files did not exist, even though the directory, and .nuget package .xml files did.

Building a .NET assembly which uses Crystal Reports on a build server

I'm trying to Build a .NET assembly which uses Crystal Reports on a build server without installing Visual Studio or the Crystal Reports Runtime.
The version of Crystal Reports we are targeting in our code is the one that came along with Visual Studio 2008 and we are using MSBuild to build this project.
I've copied what seems to be all of the referenced dlls in my project into a folder called Assemblies on the build server and I've tried setting the reference path in my csproj.user file and also by copying this same PropertyGroup into my project file but still no luck. The error I'm getting looks like the example below.
MyFile.cs(5,7): error CS0246: The type
or namespace name 'CrystalDecisions'
could not be found (are you missing a
using directive or an assembly
reference?)
[c:\MySolution\MyProject...]
Does anybody have any suggestions on how or whether I should be able to get this to work?
It looks like I may have figured out this one myself after experimenting around with the element for my references in the project file. My Crystal Reports assembly references now look like the example below.
<Reference Include="CrystalDecisions.CrystalReports.Engine, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304">
<HintPath>$(MSBuildProjectDirectory)\..\Libraries\CrystalReports\CrystalDecisions.CrystalReports.Engine.dll</HintPath>
</Reference>
<Reference Include="CrystalDecisions.ReportSource, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304">
<HintPath>$(MSBuildProjectDirectory)\..\Libraries\CrystalReports\CrystalDecisions.ReportSource.dll</HintPath>
</Reference>
<Reference Include="CrystalDecisions.Shared, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304">
<HintPath>$(MSBuildProjectDirectory)\..\Libraries\CrystalReports\CrystalDecisions.Shared.dll</HintPath>
</Reference>
And even more importantly it works!