Avoiding local dependencies for MSBuild Community Tasks within Visual Studio 2010 - visual-studio-2010

I'm trying to start taking advantage of the MSBuild Community Tasks so right after installing the .msi package I've imported MSBuild.Community.targets within the <Project> element this way:
<Import Project="lib\MSBuild.Community.Tasks.targets" />
Interestingly I've noticed such file have a reference to the local installation path in MSBuildExtensionsPath and given that in lieu of keeping code dependencies as clean as possible I'm willing to pay the overhead of distributing/versioning them with every project, I was wondering if is it possible to sort of override the default/installation location with a project-relative one in the .cproj file?
The actual layout would be like:
Dotnet.Samples.Foobar
\src
Foobar.cs
\lib
MSBuild.Community.Tasks.targets
MSBuild.Community.Tasks.dll
Any guidance will be sincerely appreciated. Thanks much in advace for any suggestion you might want to share.

In MSBuild.Community.Tasks.targets specified the path to the dll.
<PropertyGroup>
<MSBuildCommunityTasksPath Condition="'$(MSBuildCommunityTasksPath)' == ''">$(MSBuildExtensionsPath)\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
<MSBuildCommunityTasksLib>$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll</MSBuildCommunityTasksLib>
</PropertyGroup>
You can override the path in the project.
<PropertyGroup>
<MSBuildCommunityTasksPath>lib</MSBuildCommunityTasksPath>
</PropertyGroup>
And leave import the same:
<Import Project="lib\MSBuild.Community.Tasks.targets" />

Related

MSBuild - want to get the output assembly

I have a .targets file in a folder named .pack I have this:
<PropertyGroup>
<TaskAssembly>$(OutputPath)netstandard2.1\Test.dll</TaskAssembly>
</PropertyGroup>
Why instead of MyProject\bin\Debug\netstandard2.1\MyProject.dll it locates like the below line?
MyProject\.pack\bin\Debug\netstandard2.1\MyProject.dll
Why .pack is there!?
Then wanted to use it with a Using task
<UsingTask
TaskName="brand.ProBuild.Tasks.TestFunction"
AssemblyFile="$(TaskAssembly)"
/>
Defined as inline address, played with slashes, cleared bin/obj, restarted, don't why it can't understand some addresses.
Defined and used several path variables in my targets files, some working correctly and some are troublesome especially when want to use parents or some problems with slashes '/', don't know maybe some addresses are working randomly. But what is wrong with the $(OutputPath) ?!
Visual-studio 2019, .Net Standard 2.1 (It has multiple targets I want to get that specific dll)
You should check in your main project, before the import node like <Import Project=".pack\xxx.targets" />, check whether you defined the outputpath property again like
<outputpath>.pack\bin\Debug\</outputpath>
Suggestion
From your description, you created a custom MSBuild task dll to use its new custom task in another project, first, please make sure that the Test.dll is in the output folder of your project called MyProject.
Then, check whether you have redefined the outputpath before the import xml node.
Like this:
<PropertyGroup>
<outputpath>.pack\bin\Debug\</outputpath>
</PropertyGroup>
..........
<Import Project=".pack\xxx.targets" />
........
<UsingTask
TaskName="brand.ProBuild.Tasks.TestFunction"
AssemblyFile="$(TaskAssembly)"
/>
If so, you should change OutputPath to bin\Debug\.
In addition, if it does not help you, please share the xxx.csproj of project MyProject with us so that we can troubleshoot your issue more quickly.
Update 1
Since you have only one targets file in your project, I suggest you could follow these suggestions:
1) close VS Instance, enter your project folder, delete the .vs hidden folder under the solution folder, bin and obj folder. Then ,restart your project to test again.
2) you can define the correct value in the xxx.csproj file before the imports xml node to force the correct value of outputPath.
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
.......
<Import Project="xxx.targets"/>

How to build VS 2015 solution with projects which import targets and props from nuget packages using msbuild 14?

The scenario
You add a nuget package, which in turn injects <Import .../> statement into your csproj file which references a targets or props file from the package itself.
This works fine when building the code in Visual Studio, but fails miserably when building the same solution with msbuild.
The root cause
There are several. First, the logic to restore the packages is executed by the VS itself outside of the build proper. We can solve it by importing Nuget.targets which would run the RestorePackage target before the build. Check.
But the second problem is more serious. The Import statements importing targets/props from the packages can only be resolved after the packages are restored. Meaning restoring the packages cannot be part of the build. It must happen before the msbuild is given the solution to build. Yes, Visual Studio does it already, but I do not use Visual Studio on my Gated Check-In or CI server. I need it to work with msbuild.
What one can do?
As far as I understand, I need to be able to run the same logic VS does only on the command line. I.e. identify the packages and restore them before running msbuild. But devil is in details. Cannot be I am the first one to face this problem.
How do you do it?
Found the answer in this blog post - http://sedodream.com/2013/06/06/HowToSimplifyShippingBuildUpdatesInANuGetPackage.aspx
Following this blog I have created before.MySolutionName.sln.targets file with the following content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Restore">
<Target Name="Restore" BeforeTargets="Build">
<Exec Command=".nuget\nuget.exe restore $(MSBuildProjectName)" LogStandardErrorAsError="true" />
</Target>
</Project>
Now all the packages in the solution are restored before the build.
Thank you, Sayed Ibrahim Hashimi.

Is it possible to get NuGet.exe running disconnected from Visual Studio?

I've been wrestling with NuGet for a few days now and I'm turning to StackOverflow in frustration - hopefully someone here can be kind enough to point me in the right direction.
I've used NuGet several times for simple one-man pet projects, but this is the first time I've used it for something I really care about and want to have fully continuous builds, etc. I'm trying to create a simple NAnt build script to get the source for Git, ensure the external dependencies have been brought down, compile, and run tests - vanilla CI.
I originally went down the path of trying to get solution restore working, but it just didn't work or I didn't how it worked. Visual Studio is not on the build server and will not be installed there - that is not an option. As an aside, I couldn't get solution restore to work just with two developers (one trying to bring down the source fresh and build cleanly). I'm assuming it's because "allow solution restore" must be turned on everywhere (and is not by default). I punted on that approach before I got to the bottom of it - frankly, having my package manager so tightly coupled to the IDE makes me uncomfortable and was hoping I could do it another way. The package managers I'm used to using are simple command line tools - the CI build script invokes it on build, and developers do it on demand. I've spent the last two hours trying to get this working with the last 30 minutes in the NuGet source code. I feel like I'm fighting the tool and need to reboot.
Does anyone have any examples of the best to use NuGet in a multi-developer + CI scenario? This is what I want:
Any and all developers can get the source and run the tests in 3 or
less clicks (preferably 1). If the binaries are not present locally, that will be JIT fetched. If they are there, they will be updated if necessary, etc. This would ideally not even require NuGet to be installed (i.e. NuGet.exe would need to be in my repo).
Do #1 via a CI server like Jenkins, TeamCity, etc. (preferably using the same script)
If its not overly fighting the tool, I would like to have all this disconnected from Visual Studio with a single packages.config file and all binaries dumped into a single Lib folder in the root of the repo.
Any pointers would be very much appreciated.
Below, how I think you can achieve each your requisites:
You need to "Enable NuGet Package Restore" in your solution: http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
As #alexander-doroshenko mentioned for TeamCity you can use Nuget Installer: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer, but if you want a script to run in Jenkins, try this (works at TC too, as a command line step) for each project:
nuget.exe install "[Project folder]/packages.config" -source "" -solutionDir "" -OutputDirectory "packages"
This requisite will be done by item 1 and 2.
TeamCity has a build step for that, called "NuGet Installer", it fetch required packages from .sln file and download the locally. It does not require Visual Studio to run.
Read more about it here: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer
There are several different solutions for integrating NuGet into your build process depending on how much integration you require. In our case we wanted to use NuGet as package manager and allow developers to build their solutions even if they haven't got NuGet installed on their machine. For that to work we enabled package restore which adds the NuGet binaries to your solution folder and updates the project files. Note that NuGet doesn't always do the update of the project files correctly. In our case we found that some project files got updated but others didn't. To verify that the project was updated you will need to open the project file as XML file. To achieve this load the solution and right click the project in question and select unload project. Then right click the project again and select edit [PROJECT_NAME]. In the project file you should see
A RestorePackages property in the first propertygroup. This property should have the value true
An import statement at the very end of the project file. This import statement should point to the 'NuGet.targets file that accompanies the NuGet binary.
Below is an example of one of our project files (heavily edited)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">$(MSBuildProjectDirectory)\..</SolutionDir>
<ProjectGuid>{8B467882-7574-41B2-B3A8-2F34DA84BE82}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>MyCompany.MyNamespace</RootNamespace>
<AssemblyName>MyCompany.MyNamespace</AssemblyName>
<!-- Allow NuGet to restore the packages if they are missing -->
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<Import Project="$(SolutionDir)\BaseConfiguration.targets" />
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="MyClass.cs" />
<!--
.... MANY MORE FILES HERE
-->
</ItemGroup>
<!-- Import the Nuget.targets file which integrates NuGet in the build process -->
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
The next step you'll need to take is to provide a solution level NuGet configuration file in which you'll indicate where the packages need to be 'installed' and what the URL of the package repository is. In our case the solution directory structure looks like:
(D) root
(D) build
(D) packages
(D) source
(D) .nuget
NuGet.config
NuGet.exe
NuGet.targets
(D) MyCoolProject
MyCoolProject.csproj
MyCoolProject.sln
(D) templates
NuGet.Config
Where (D) indicates a directory.
The NuGet.config file contains the following configuration settings.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="True" />
</packageRestore>
<config>
<add key="repositorypath" value="packages" />
</config>
<packageSources>
<add key="OurPackageServer" value="PACKAGE_SERVER_ADDRESS" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>
This configuration file indicates that package restore is enabled, that the repository path (where the packages are placed) is the packages directory and which package sources are active.
By placing a NuGet.config file in the root directory we can use the hierarchical configuration option with NuGet. This allows the individual solutions to override computer specific configurations. The other benefit is that this way we don't need to have NuGet installed on the build server (because the executable and the configurations are in the repository).
With this setup developers can build the solution from Visual Studio. The build should work fine on developers machines even if they don't have NuGet installed. Note however that they won't be able to add packages to a project without having NuGet installed in visual studio.
On the build server you can simply use MsBuild to build the solution which will automatically download the packages from your package repository. Visual Studio is not required to be installed on the build machine for that (just the .NET framework of your choice).

SlowCheetah executes after post-build events

I use SlowCheetah to transform my app.configs. I have a multi-project solution where one of the projects executes a post-build event where the output of the bin is copied elsewhere. I've found that SlowCheetah does it's transforms after the post-build event, so the app.config I'm copying is the pre-transformed version.
Does anyone have a suggestion of how I can execute my copy after the SlowCheetah transforms? Is this going to require that I write a custom build task?
If you are using msbuild 4.0 for building your projects - you can hook to slowcheetah targets with new AfterTargets BeforeTargets attributes.
I dont know what exactly target name you want to hook after but this code could gave you base concept how to do this
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Some_Target_Name" AfterTargets="TransformAllFiles" >
<Message Text="= Script here will run after SlowCheetah TransformAllFiles ="/>
</Target>
<Project>
Edited: I installed SlowCheetah and found that AfterTargets attribute should be "TransformAllFiles".
Just set up your target dependency AfterTargets="TransformAllFiles"
Alexey's answer leads to the correct solution but here it is in full:
Right-click your project and select Unload Project
Now right-click the project and select Edit [your project name].csproj
Scroll to the bottom and uncomment the target named AfterBuild and add this attribute AfterTargets="TransformAllFiles"
Move your post build actions into this target using the Exec command:
An example:
<Target Name="AfterBuild" AfterTargets="TransformAllFiles">
<Exec Command="ECHO Hello PostBuild World!" />
</Target>
I have bumped into this problem too... decided to update to latest version of SlowCheetah (current 2.5.8), and this problem appears to have been fixed! No more problems using post-build events to deploy a project with transformed XML!
After the NuGet package upgrade process, I had a strange issue, though... transforms were no longer happening. Editing the project like Naeem Sarfraz suggested, I have found that the SlowCheetah's PropertyGroup section was placed at the end of the .csproj.
It was just a matter of moving it to the top, near the other PropertyGroup sections, and now it works like a charm!
If you need to copy/move other .config files (other than web.config) around after the build before publishing here is how it can be done with Visual Studio 2013 (I didn't test it on earlier versions). This section can be added at the end of the .csproj file right before the closing tag </Project> and it'll be fired just before MSDeploy starts the Publishing process.
<Target Name="MoveConfigFile" BeforeTargets="MSDeployPublish">
<Move
SourceFiles="$(IntermediateOutputPath)Package\PackageTmp\ThirdPartyApp.config"
DestinationFolder="$(IntermediateOutputPath)Package\PackageTmp\bin"
OverwriteReadOnlyFiles="true"
/>
</Target>
The company I work for purchased a third party product that needs to have a .config files in the bin folder along with its assembly in order to work.
At the same time we need to process the product's .config file and be able to move it to the bin folder after transformations.
The $(IntermediateOutputPath)Package\PackageTmp folder contains the whole application that will be copied over the target server.

How can I exclude a project from a build in MSBuild?

I need to build a solution, but exclude one project. How should I do it?
I searched a lot about this issue, but nothing could help.
An ItemGroup section rises the following exception:
Invalid element . Unknown task or datatype.
PropertyGroup also rises the exception.
Below is my code sample:
<project name="TI 8.1.6 build script">
<ItemGroup>
<Solution Include="${ROOT}\Core\TI Core.sln" Exclude="${ROOT}\Utilities\DTS Indexing Service\Tdi.Origami.IndexUpdaterServiceSetup\Tdi.Origami.IndexUpdaterServiceSetup.wixproj"/>
</ItemGroup>
...
</project>
How can I do this?
You can exclude projects at the solution level for a specific build configuration by using the Configuration Manager Dialog in Visual Studio:
Then you can simply invoke msbuild on the solution file specifying the build configuration to use:
msbuild /property:Configuration=Release MySolution.sln
The solution suggested by Enrico is the most versatile solution that would work always. An alternative solution might be to use a <MSBuild> task directly. This will work for you if you have all your project files under a particular directory, or be able to easily enumerate all projects you want to build (i.e. number of projects in your solution is not very big).
For example, this MSBuild file will build every project under your current directory except for a specific project:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MyProjectReferences Include="**\*.*proj" />
<MyProjectReferences Exclude="Utilities\DTS Indexing Service\Tdi.Origami.IndexUpdaterServiceSetup\Tdi.Origami.IndexUpdaterServiceSetup.wixproj" />
</ItemGroup>
<Target Name="BuildAllExceptWixProject">
<MSBuild Projects="#(MyProjectReferences)" Targets="Build" />
</Target>
</Project>
Then you can build that using command line msbuild <myproject> /t:BuildAllExceptWixProject
In your solution file (.sln), remove the Build.0 entries. For example:
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyProject", "MyProject.vcxproj", "{2281D9E7-5261-433D-BB04-176A61500CA3}"
EndProject
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2281D9E7-5261-433D-BB04-176A61500CA3}.Debug|x86.Build.0 = Debug|x64
If you delete this "Build.0" entry, it will load in the solution fine, but will not be built, either through the GUI or via external MSBuild.
Since VS 2019 and MSBuild 16.7, the right way is to use Solution filters. Ref
create a master.proj file:
in another ItemGroup add DefaultExclude properties for programs - put it in front of the solution
-- BA was Canadian
Configuration=Release
Release
drop the master.proj into the directory with the programs and msbuild the master.proj
compiles everything except... that HelloWorld

Resources