I have a simple class library project (with Class1) and have enabled NuGet Package Restore for the solution.
That imports the restorepackages task into the .csproj file.
I can compile the project with
C:>msbuild myproj.csproj /t:compile
And I can call the restorepackages task successfully before adding packages with
C:>msbuild myproj.csproj /t:restorepackages
However, adding any package will cause the restorepackages task to fail with an error 3.
It seems that the NuGet task is called with a wrong working directory, and you may actually fix the behavior by removing the workingdir attribut in the NuGet.targets file, that was added to the solution.
Edit the task like this:
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="Exists('$(PackagesConfig)')"
WorkingDirectory="$(NuGetToolsPath)" />
and remove the working dir:
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="Exists('$(PackagesConfig)')"
/>
It seems to work as expected both from commandline msbuild and within VS2010.
Does anyone know if this change might break any tooling?
Can it be related to the issue "Package Restore's $(SolutionDir) goes too far"?
Did you check the injected SolutionDir property in your project file? It might be that the generated relative path won't point to the actual solution dir.
Related
I have .NET452 project - lets call it Consumer.csproj that I want to consume nuget lets call it SharedTargets that contained some custom targets files (SharedTargets.targets) from msbuild.
I'm using PackageReference format and now (compared to what it used to be) nuget packages are being restored to shared folder (%userprofile%.nuget\packages), and I'm not sure if it is good idea to reference it via that (doesn't feel right).
Eg:
<PackageReference Include="SharedTargets">
<Version>1.0</Version>
</PackageReference>
<Import
Project="$(USERPROFILE)\.nuget\packages\SharedTargets\1.0\SharedTargets.targets"
/>
Also this works only in VS, running this from command line (msbuild) I'm getting chicken-egg problem:
Confirm that the path in the <Import> declaration is correct, and that
the file exists on disk.
Obviously since I need to restore nuget first before I can use it :)
So question:
is there some more elegant way how to resolve path to the nuget package inside project file
is there a way how to make msbuild succeed (i.e. restore packages before SharedTargets.target is imported)
You shouldn't try to manually import targets distributed via NuGet.
Put your .targets file inside a build subfolder inside the package and name it SharedTargets.targets (package id + .targets) and NuGet will automatically include the targets - for packages.config projects it will modify the project file on install and for PackageReference projects the targets will be imported by modifying an implicitly generated targets file in the obj\ directory.
I am having a problem with nuget (version 4.3.0.4406) and msbuild (version 15.3.409.57025). I am using VS2017 to create class library. Using the pack capability of VS2017 i can successfully create a nuget package (that i can install in another solution). Now i want to add an install.ps1 script to the package in the tools folder that runs when the nuget is installed.
In the csproj file i am specifying multiple target frameworks:
<TargetFrameworks>net45;net452</TargetFrameworks>
I cannot figure out how to do this. I've created a nuspec file using the nuget -spec command which generates a simple nuspec file. When i use the msbuild command with the /t:pack and /p:Nuspecfile=path.to.nuspec I get the following errors:
NuGet.Build.Tasks.Pack.targets(141,5): error : Value cannot be null or an empty string.
I have nuspec files from other projects (from VS2015 solutions) that work without problem, and the structure of the one i am using now is basically the same. Can anyone let me know whether i am trying something that cannot be done?
You can pack any item by updating its metadata in the csproj file:
<ItemGroup>
<None Update="install.ps1" CopyToOutputDirectory="PreserveNewest" Pack="true" PackagePath="\tools" />
</ItemGroup>
Note that the ps1 file is only run for projects using packages.config to reference the NuGet package and you should investigate alternative ways to accomplish what you are trying to do with the script as PackageReference is now more likely to be used instead.
I have tried searching the web for a solution to this problem but it seems very unclear. It sounds like people are seeing this but the solutions don't seem to work for me.
I have downloaded and installed YUICompressor.NET.MSBuild 2.3.0.0 from NuGet into my project.
I have created an MSBuild target file that closely resembles the example file included and exists as part of my .csproj file so I can run it in the AfterBuild step.
I am getting the following error everytime I try to build my VS project:
The "JavaScriptCompressorTask" task could not be loaded from the assembly SolutionDir\packages\YUICompressor.NET.MSBuild.2.3.0.0\lib\NET20\Yahoo.Yui.Compressor.Build.MsBuild.dll.
Could not load file or assembly 'Yahoo.Yui.Compressor, Version=2.3.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Confirm that the declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.
My folder structure is as follows:
\Solution
\packages
YUICompressor.NET.MSBuild.2.3.0.0\lib\NET20\
\build
ProjectFile.csproj
In the csproj I have:
<UsingTask TaskName="CssCompressorTask" AssemblyFile="packages\YUICompressor.NET.MSBuild.2.3.0.0\lib\NET20\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<UsingTask TaskName="JavaScriptCompressorTask" AssemblyFile="packages\YUICompressor.NET.MSBuild.2.3.0.0\lib\NET20\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<Target Name="AfterBuild">
<ItemGroup>
<JavaScriptFiles Include="someFile.js" />
</ItemGroup>
<JavaScriptCompressorTask SourceFiles="#(JavaScriptFiles)" OutputFile="build\combined.js" DeleteSourceFiles="false" CompressionType="None" ObfuscateJavaScript="false" PreserveAllSemicolons="true" />
<JavaScriptCompressorTask SourceFiles="#(JavaScriptFiles)" OutputFile="build\combined.min.js" DeleteSourceFiles="false" CompressionType="Standard" />
</Target>
Am I missing something? Can anyone help me? Thank you.
Did you try to download version 2.3.0.0 directly from codeplex? Then make sure that the Yahoo.Yui.Compressor.Build.MsBuild.dll and Yahoo.Yui.Compressor.dll reside in the same directory. Like this I was able to make it work.
It's been a while since i've played around with the AfterBuild .. but how this works is that the the msbuild program is ran from some directory .. and therefore looks for those assembly files RELATIVE to where the msbuild is being executed from.
I'm not sure if this means the msbuild is being run from C:\program files(x86)\Microsoft Visual Studio\<whatever...>
TAKE NOTE: it's the folder/path (aka execution path) where visual studio is running the msbuild command from ... NOT where msbuild exists.
So therefore, it can't find the assemblies.
Try putting in the full path to the assemblies (just to see if that works).
eg. C:\Projects\Solution\packages\YUICompressor.NET.MSBuild.2.3.0.0\lib\NET20\Yahoo.Yui.Compressor.Build.MsBuild.dll
If it's running it from the \solution\bin directory, then you're in luck! cause then you can do ..\packages\YUICompressor.NET.MSBuild.2.3.0.0\lib\NET20\Yahoo.Yui.Compressor.Build.MsBuild.dll' (the..means: from thisbindirectory, go up one level tosolutionthen down intopackagesand then down intoYUIComp`... etc.
So the answer to your question is this: Find the location Visual Studio is running the msbuild command from, during an AfterBuild. Maybe put in some code in there to say 'write to file => current path i'm in :P'
I have added the xunit.runners package to a solution. The current version is 1.9.1, so I have hard-coded the path to the executable in an MSBuild project file:
<StartAction>Program</StartAction>
<StartProgram>$(MSBuildProjectDirectory)\..\..\Packages\xunit.runners.1.9.1\tools\xunit.gui.clr4.exe</StartProgram>
<StartArguments>"$(MSBuildProjectDirectory)\$(OutPutPath)$(AssemblyName).dll"</StartArguments>
(Off-topic: with this configuration, F5 starts the xUnit GUI runner and I can debug specific unit tests.)
I know that everytime I update the Nuget package, I will forget to change the path. Changing the path is a minor nuisance, since I have to unload the project, edit the file, then reload the project.
How can I start the executable, regardless of the actual version of the package? Can I find the executable in the folder named xunit.runners.* using a wildcard in MSBuild, then use that as a property in the <StartProgram> element?
Edit:
Something like:
<ItemGroup>
<Runners Include="$(MSBuildProjectDirectory)\..\..\Packages\xunit.runners.*\tools\xunit.gui.clr4.exe" />
</ItemGroup>
Will give me all runners in #(Runners), sorted by version. How can I get one of them, preferably the last one?
For filtering you can build a custom task. It can even be inline http://msdn.microsoft.com/en-us/library/dd722601.aspx, were you can write the c# code you need to loop over the items and pick the right one. Then you can expose the chosen path in an output property that you then use to set the value of the StartProgram property.
This question shows a custom inline task that gets an item array and does stuff with it. You can probably start from there.
You'll need to use this task in a target that runs before the target that initiates the debugging.
With fsimonazzi's comment I ended up with this:
<PropertyGroup>
<Package>$([System.IO.Directory]::GetDirectories("$(MSBuildProjectDirectory)\\..\\..\\Packages\\", "xunit.runners.*").GetValue(0))</Package>
<StartAction>Program</StartAction>
<StartProgram>$(Package)\tools\xunit.gui.clr4.exe</StartProgram>
<StartArguments>"$(MSBuildProjectDirectory)\$(OutPutPath)$(AssemblyName).dll"</StartArguments>
</PropertyGroup>
Apparently, NuGet will guarantee there's only one version of the package.
I'm not able to build solution incrementally. I checked diagnostic log and I found that every project containing workflows are always rebuild because of this:
Input file ".NETFramework,Version=v3.5" does not exist.
Workflows are always recompiled, new temporary files are created and project is build again.
Building target "WorkflowCompilation" completely.
Input file ".NETFramework,Version=v3.5" does not exist.
Using "CompileWorkflowTask" task from assembly "System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35".
Task "CompileWorkflowTask"
No files found with '.xoml' extension in the set of input files.
Generated temporary code file: C:\Users\Ludwo\AppData\Local\Temp\uwdnm5th.cs
Workflow markup validations completed with 0 errors and 0 warnings.
Done executing task "CompileWorkflowTask".
Done building target "WorkflowCompilation" in project "Delta.Workflow.Common.Merged.csproj".
Target "CoreCompile" in file "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.targets" from project "h:\Prj\R4x\M\CountrySystems\Delta\Common\Delta.Workflow.Common\Delta.Workflow.Common.Merged.csproj" (target "Compile" depends on it):
Building target "CoreCompile" completely.
Input file "C:\Users\Ludwo\AppData\Local\Temp\uwdnm5th.cs" is newer than output file "obj\Debug\Delta.Workflow.Common.pdb".
I'm building my projects using MSBuild 4.0. My projects are set to build with v3.5 TargetFrameworkVersion, unit tests projects are build with TargetFrameworkVersion set to v4.0. I tried to build it on different PC but the result is still the same. I also played with references in my projects. It seems to be like v4.0/v3.5 conflict, but I don't know how to fix it. Any ideas?
I found it. The root cause is wrong version of Workflow.targets file imported inside my workflow (.csproj) projects. Workflow.targets for .NET v4.0 was imported instead of v3.5. It should be related to projects upgrade from VS2008 to VS2010 I did some time ago.
I changed Workflow.targets Import from
<Import Project="$(MSBuildToolsPath)\Workflow.targets"/>
to
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.5\Workflow.targets" />
Hope it helps someone...