Include .sln file in MsBuild file? - msbuild

I'm trying to build Visual Studio project from .msbuild file. The idea is to do some things before the build, then execute build of .sln from the same place.
Something like this:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildClient" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Tools>$(MSBuildProjectDirectory)\tools</Tools>
<NugetExe>$(Tools)\nuget\nuget.exe</NugetExe>
<ClientFolder>$(MSBuildProjectDirectory)\src\Client</ClientFolder>
<ClientSolution>$(ClientFolder)\ClientProject.sln</ClientSolution>
</PropertyGroup>
<Target Name="BuildClient">
<!--Restore Nuget-->
<Message Text="Starting Restoring Nuget Packages" />
<Exec Command=" $(NugetExe) restore $(ClientSolution)" />
<Message Text="Finished Restoring Nuget Packages" />
<Import Project="$(ClientSolution)" />
<!--build project-->
</Target>
</Project>
But line with <Import> is underlined in VS, saying import should be on level up, not within <Target>. When I move <Import> a level up as suggested I get an execution error:
errorMSB4025: The project file could not be loaded. Data at the root level is invalid.
Any idea how to build whole project without major rewriting?

Silly me! the solution turns out to be very simple:
<MSBuild Projects="..\..\MySolution.sln" "/>
This did the trick with executing the build on .sln file
I got the pointer from this answer.

Related

VSTS Continuous Integration: NuGet package are missing on this computer

I am using Visual Studio 2015, i have a solution with 2 different web applications. There exists One Solution and two projects under it. The files related to nuget are distributed as:
Packages Folder is in the Solution Directory
Package.config in each project directory
There is no nuget folder: nuget.config and nuget.exe in my solution.
My Project build and run fine in Visual Studio, but I am facing a problem when using VSTS Continuous Integration with Build Solution Step (which use a build definition that maps to one project) it gives:
This project references NuGet package(s) that are missing on this computer. Use
NuGet Package Restore to download them. For more information, see The missing file is
..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props.
This is MyProject.csproj file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
<Import Project="..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BBD26A49-D1F4-4391-9D60-2469433DEE0D}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AdminUI</RootNamespace>
<AssemblyName>AdminUI</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
<UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
I noticed that it only tries to import the package that generated the error, but it doesn't explicitly import other packages, but it include them as references:
<Reference Include="WebGrease">
<Private>True</Private>
<HintPath>..\packages\WebGrease.1.5.2\lib\WebGrease.dll</HintPath>
</Reference>
<Reference Include="Antlr3.Runtime">
<Private>True</Private>
<HintPath>..\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll</HintPath>
</Reference>
This also the end of the myProject.csproj file:
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
</Target>
I am wondering why it gives this error, taking into consideration that this package is already installed in the previous step "Nugget Install". Why it can't find it? i have spent a lot of time on this issue!
Before you add the build task, you can add nuget install or restore task. This will restore/install the nuget packages on the build agent.
Actually, this worked for me:
Adding the mapping (repository configuration) to the packages folder in the solution
Repository Configuration
Nuget Install Config
Then, it worked like a charm.
Ensure the Package.config file you've mentioned exists in source control.
It may be that everything builds successfully on your machine because Package.config exists there but not in source control for when the continuous integration agent tries to download and build the project.

Set output path for MSBuild task

In the following simple MSBuild file I'd like to overwrite the output path that is defined in the .sln or .csproj file. In line 13 you can see that I call an MSBuild task for an existing VS solution. Usually, the projects that are part of that solution have a property where the output is stored. With my script I'd like to overwrite that so that my "build automation" uses a different directory than the default one.
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Default">
<PropertyGroup>
<appname>Some App</appname>
<version>2.9.1</version>
<file_xap>Some.App.WP8_$(version).$([System.DateTime]::Now.ToString(`yyyyMMddHHmmss`)).xap</file_xap>
</PropertyGroup>
<Target Name="Default">
<MSBuild Projects="C:\Users\User\Documents\Visual Studio 2013\Projects\SomeApp\SomeApp.sln" Properties="Configuration=Debug;Platform=Any CPU">
</MSBuild>
<Message Text="Output file: $(file_xap)"/>
</Target>
</Project>
So the actual question is: How can I call MSBuild for that sln in a way that the output (the xap-file in that case) to another directory (having all the output apart from the xap-file is fine as well)?
I will post my full xml here so you can understand it all
the structure of the project is like this:
MyProject----MyProject.sln
----MyProject.Server---
----MyProject.Server.proj
----Other server project classes and stuff
----MyProject.Client---
----MyProject.Client.proj
----Client project related stuff
----BuildFromXmlFldr---
----build_both_proj.xml <---This is the example file i posted here
Here is the build_both_proj.xml
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0"
DefaultTargets="Build">
<PropertyGroup>
<SolutionDir>..\</SolutionDir>
<ServerProjectFile>..\MyProject.Server\MyProject.Server.csproj</ServerProjectFile>
<ClientProjectFile>..\MyProject.Client\MyProject.Client.csproj</ClientProjectFile>
<ServerProjectName>MyProject.Server</ServerProjectName>
<ClientProjectName>MyProject.Client</ClientProjectName>
<ServerOutput>C:\_Publish\Server\</ServerOutput>
<ClientOutput>C:\_Publish\Client\</ClientOutput>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
</PropertyGroup>
<Target Name="BuildServer">
<MSBuild Projects="$(ServerProjectFile)"
Targets="Build"
Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(ServerOutput);">
</MSBuild>
</Target>
<Target Name="BuildClient">
<MSBuild Projects="$(ClientProjectFile)"
Targets="Build"
Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(ClientOutput);"
StopOnFirstFailure="true">
</MSBuild>
</Target>
<PropertyGroup>
<BuildAllDependsOn>BuildServer;BuildClient</BuildAllDependsOn>
</PropertyGroup>
<Target Name="BuildAll" DependsOnTargets="$(BuildAllDependsOn)"/>
</Project>
This is the msbuild.exe command inside the folder BuildFromXmlFldr that I used:
c:\path_to_msbuild\MSBuild.exe build_both_proj.xml /t:BuildAll
so the output is determined in the Properties attribute in the Target tag
Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(ServerOutput);"

Issue with ApplicationFile file not found in MSBuild script

my issue is that the msbuild script can't find my MSI installer file.
Here is the script file bootstrapper.msbuild :
<Project ToolsVersion="3.5"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<BootstrapperFile Include="Microsoft.Windows.Installer.4.5" >
<ProductName>Windows Installer 4.5</ProductName>
</BootstrapperFile>
<!--<BootstrapperFile Include="DotNetFX40" >
<ProductName>Microsoft DotNet Framework 4.5 SP1</ProductName>
</BootstrapperFile>-->
</ItemGroup>
<!-- from http://stackoverflow.com/questions/346175/use-32bit-program-files-directory-in-msbuild
-->
<PropertyGroup>
<ProgramFiles32>$(MSBuildProgramFiles32)</ProgramFiles32>
<ProgramFiles32 Condition=" '' == '$(ProgramFiles32)'">$(ProgramFiles%28x86%29)</ProgramFiles32>
<ProgramFiles32 Condition=" '' == '$(ProgramFiles32)'">$(ProgramFiles)</ProgramFiles32>
</PropertyGroup>
<Target Name="SetupExe">
<GenerateBootstrapper
ApplicationFile="..\MySetup\MySetup\bin\Debug\MySetup.msi"
ApplicationName="MyApplication"
Culture="en"
BootstrapperItems="#(BootstrapperFile)"
ComponentsLocation="HomeSite"
Path="$(ProgramFiles32)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\"
OutputPath="output"/>
</Target>
</Project>
The folders structure is as follows :
The file boostrapper.msbuild is inside Mybootstrapper. I've tried the path using command line and it works fine. Why not in ms build ? Am I missing something ?
The question is what is the directory the task GenerateBootstrapper is referring to ?
Could you advice please ?
It looks like your relative path is not correct. Try:
ApplicationFile="..\MySetup\bin\Debug\MySetup.msi"
The issue was I didn't put MSI file in the path where the generated setup.exe is located. I was thinking that this later will contain all files...
Am I wrong ?

MSBuild project to test a C++ program

I have a .vcxproj file that compiles a C++ program. I would like to create a second MSBuild project file that tests the program by running it, but only if the program has been rebuilt since the last successful test. How can I access the "TargetPath" of the program from the second project file?
If I could access TargetPath as an "item" from the .vcxproj file, then the the tester project file will look like this:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build" Inputs="#(TargetPath)" Outputs="#(TargetPath->'%(filename).test-passed)'">
<Exec Command="#(TargetPath)" />
<Touch Files="#(TargetPath->'%(filename).test-passed)'" />
</Target>
</Project>
I would like to execute the test using a separate project file from the compilation of the program, to make it easier to choose between build-and-test or build-and-debug within Visual Studio, without multiplying the build configurations.
It is possible to run a native program compiled by a separate .vcxproj using the MSBuild task. Use the <Output> element to create an Item with the "TargetOutputs" from the C++ application build. However, if you are building a "native" program, "TargetOutputs" is normally blank. In this case, use the "GetNativeTargetPath" target to get the output path. The following project .vcxproj file works with Visual Studio. It builds test_build.vcxproj. The test_build.exe file is run, if it has changed since the last successful run.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{80DB0D71-72E0-4FB1-B53F-EFB858A1D5A8}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>nordic_test_run</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
<ProjectReference Include="test_build.vcxproj" />
</ItemGroup>
<Target Name="BuildExecutable">
<MSBuild Projects="#(ProjectReference)" Targets="Build" BuildInParallel="True" />
<MSBuild Projects="#(ProjectReference)" Targets="GetNativeTargetPath" BuildInParallel="True">
<Output TaskParameter="TargetOutputs" ItemName="NativeTests" />
</MSBuild>
</Target>
<Target Name="Build" DependsOnTargets="BuildExecutable" Inputs="#(NativeTests)" Outputs="#(NativeTests->'%(filename).test-passed')">
<Exec Command="#(NativeTests)" />
<Touch Files="#(TestTargets->'%(filename).test-passed')" />
</Target>
</Project>

Log4Net configuration error causing MSBuild to fail

I'm trying to set up a CI environment at a new client site using Team City and MSbuild and the MS build community extensions. Compiling the code seems to work fine. However, when I run my unit tests I get the following error coming from the NUnit task:
log4net : error XmlConfigurator: Failed to find configuration section 'log4net' in the application's .config file.
I've identified the two test projects that are causing this issue. However, I've ran the tests directly from nunit-console, and the resharper nunit test runner and though I see the warning the tests don't fail. I don't want to do anything with the Log4net configuration file or the assembly.cs in any project. All I want to do is make the MSBuild script behave like Visual Studio which doesn't consider the log4net error as a failure.
Here's the build file
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Compile">
<Import Project=".\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
<Configuration Condition="'$(Configuration)' == ''"> Debug</Configuration>
</PropertyGroup>
<ItemGroup>
<BuildArtifacts Include=".\build_artifacts\"/>
<SolutionFile Include ="..\Core.Services.sln"/>
<NUnitPath Include="..\Packages\NUnit.2.5.10.11092\tools"/>
</ItemGroup>
<Target Name="Clean">
<RemoveDir Directories="#(BuildArtifacts)"/>
</Target>
<Target Name="Init" DependsOnTargets="Clean">
<MakeDir Directories="#(BuildArtifacts)"/>
</Target>
<Target Name="Compile" DependsOnTargets="Init">
<MSBuild
Projects="#(SolutionFile)"
Targets="Rebuild"
Properties="OutDir=%(BuildArtifacts.FullPath)">
</MSBuild>
</Target>
<Target Name="DevelopmentBuild" DependsOnTargets="Compile">
<Message Text="Running Unit Tests from %(BuildArtifacts.FullPath)...." ContinueOnError="true"></Message>
<CreateItem Include="%(BuildArtifacts.FullPath)*.Tests.dll">
<Output TaskParameter="Include" ItemName="TestAssembly" />
</CreateItem>
<NUnit Assemblies="#(TestAssembly)"
ToolPath="#(NUnitPath)\"
ContinueOnError="false"
OutputXmlFile="%(BuildArtifacts.FullPath)test-results.xml"
DisableShadowCopy="true"/>
</Target>
</Project>