How to suppress logger output when using <MSBuild ...> task? - msbuild

I need to run an external MSBuild thread from inside another MSBuild project. What I need to do is to pass the /noconsolelogger to the task . How can I do this, please help!

foo.csproj
<Project DefaultTargets="BuildAll" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BuildAll">
<Message Text="foo"/>
<Exec Command="MSBuild.exe bar.csproj /noconsolelogger"/>
</Target>
</Project>
bar.csproj
<Project DefaultTargets="BuildAll" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BuildAll">
<Message Text="bar"/>
</Target>
</Project>
Output contains the message 'foo', but not 'bar'.

Related

VS2019 add custom script to publishing process

How to perform own program before/after FolderPublish event in VS2019?
Not interesting at all how to add custom build script, it working and can be adding manually or by VS2019 project editor.
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup>
<PreBuildEvent>echo $(PublishDir)</PreBuildEvent>
</PropertyGroup>
</Project>
My question exactly about processing project publishing event, I try to use
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<Target Name="ActionsBeforePublish" BeforeTargets="BeforePublish">
<Exec Command="echo YES" />
</Target>
<Target Name="ActionsAfterPublish" AfterTargets="AfterPublish">
<Exec Command="echo $(PublishDir)" />
</Target>
</Project>
but its not working. I don't see "YES" in publishing output window.

How to extract directory from property?

I have a property GroupProj storing a full path name. How can I extract the directory of the property?
I have the following code, but it doesn't work as expected:
<PropertyGroup>
<GroupProj>C:\development\project\default.groupproj</GroupProj>
</PropertyGroup>
<Target Name="Default">
<Message Text="Echo: $(GroupProj->'%(RootDir)')" />
</Target>
I will describe my actual intention of doing so. Perhaps there is a way to do the job that I am not aware of.
I have a Delphi groupproj (MSBuild project) file, C:\development\project\default.groupproj:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Projects Include="project1.dproj">
<Dependencies/>
</Projects>
<Projects Include="project2.dproj">
<Dependencies/>
</Projects>
<Projects Include="project3.dproj">
<Dependencies/>
</Projects>
</ItemGroup>
...
</Project>
There are other 3 MSBuild files (project1.dproj, project2.dproj and project3.dproj) stored in same folder as default.groupproj.
I create a MSBuild project file (c:\test.targets):
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="3.5">
<Import Project="$(GroupProj)" />
<Target Name="Build">
<MSBuild BuildInParallel="True" Projects="project1.dproj;project2.dproj;project3.dproj"/>
</Target>
</Project>
And execute as:
c:\> msbuild /p:GroupProj="C:\development\project\default.groupproj" test.targets
The execution shall fail as MSBuild can't find projectN.dproj file. The issue shall be the working directory isn't set to default.groupproj.
One straight solution come into my mind is to extract directory of $(GroupProj) and concat to there projectN.dproj file.
That's the whole story of my question.
Try something like this:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GroupProj>C:\development\project\default.groupproj</GroupProj>
</PropertyGroup>
<Target Name="Build">
<CreateItem Include="$(GroupProj)">
<Output TaskParameter="Include" ItemName="ItemFromProp"/>
</CreateItem>
<Message Text="1. #(ItemFromProp -> '%(RootDir)%(Directory)')"/>
<Message Text="2. %(ItemFromProp.RootDir)%(ItemFromProp.Directory)"/>
<Message Text="3. %(ItemFromProp.Identity)"/>
<Message Text="4. %(ItemFromProp.FullPath)"/>
<Message Text="5. %(ItemFromProp.FileName)"/>
<Message Text="6. %(ItemFromProp.Extension)"/>
</Target>
</Project>
EDIT:
To build the projects in parallel try this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="GetGroupProjPath">
<ItemGroup>
<GroupProj Include="$(GroupProj)" />
<GroupProjPath Include="#(GroupProj->'%(Directory)')" />
</ItemGroup>
<PropertyGroup>
<GroupProjPath>#(GroupProjPath->'%(RootDir)%(Identity)')</GroupProjPath>
</PropertyGroup>
</Target>
<Import Project="$(GroupProj)" />
<Target Name="GetDProjs" DependsOnTargets="GetGroupProjPath">
<ItemGroup>
<DProjs Include="#(Projects->'$(GroupProjPath)%(FileName)%(Extension)')" />
</ItemGroup>
</Target>
<Target Name="Build" DependsOnTargets="GetDProjs">
<Message Text="#(DProjs)" />
</Target>
</Project>

MSBuild Iterate over properties from a labeled PropertyGroup and retrieve name and value

Is there a way to iterate over the properties of an MSBuild file accessing the name and value of each property within a specific <PropertyGroup>? Perhaps something like this:
<Project ToolsVersion="4.0" DefaultTargets="test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="testPropertyGroup">
<Property1>Value1</Property1>
<Property2>Value2</Property2>
</PropertyGroup>
<Target Name="prop">
<Message Text="Name=%(testPropertyGroup.Name)"/>
<Message Text="Value=%(testPropertyGroup.Value)"/>
</Target>
</Project>
If you use an ItemGroup with several subnodes, it works:
<ItemGroup>
<ApplicationLanguages Include="zh-chs">
<Name>Chinese.Simplified</Name>
<IsAppLanguage>true</IsAppLanguage>
</ApplicationLanguages>
<ApplicationLanguages Include="zh-cht">
<Name>Chinese.Traditional</Name>
<IsAppLanguage>false</IsAppLanguage>
</ApplicationLanguages>
<ApplicationLanguages Include="fr">
<Name>French</Name>
<IsAppLanguage>true</IsAppLanguage>
</ApplicationLanguages>
<ApplicationLanguages Include="de">
<Name>German</Name>
<IsAppLanguage>true</IsAppLanguage>
</ApplicationLanguages>
<ApplicationLanguages Include="es">
<Name>Spanish</Name>
<IsAppLanguage>true</IsAppLanguage>
</ApplicationLanguages>
</ItemGroup>
<Target Name="PrintValues" Outputs="%(ApplicationLanguages.Identity)">
<Message Text="Identity: %(ApplicationLanguages.Identity)" Importance="high" />
<Message Text="Name: %(ApplicationLanguages.Name)" Importance="high" />
<Message Text="IsValid: %(ApplicationLanguages.IsAppLanguage)" Importance="high" />
</Target>
If i understand you correctly you're after something like the ant equivalent of echoproperties?
The only way to get this is to run your msbuild as /verbosity:detailed or /verbosity:diagnostic, however i find that finding info in that output is a little difficult.
The best way ive found is to create a target and write message tasks for each property (a long slog i know) and call that in the project as one of the InitialTargets.
<Project ToolsVersion="4.0"
DefaultTargets="prop"
InitialTargets="CheckProperties"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="testPropertyGroup">
<Property1>Value1</Property1>
<Property2>Value2</Property2>
</PropertyGroup>
<Target Name="CheckProperties">
<Message Text="Property1: $(Property1)"/>
<Message Text="Property2: $(Property2)"/>
</Target>
<Target Name="prop">
<Message Text="Name=%(Names.Identity)"/>
<!--<Message Text="Value=%(testPropertyGroup.Value)"/>-->
</Target>
</Project>

Using MSBuild to buld a solution (.sln) with many projects in how can I make each project build into its own folder?

I am trying to create a simple build process for a quite complex (many projects) vs2010 solution.
I wish for a folder structure such as this
-Build
-Proj1
-proj1.exe
-proj1.dll
-Proj2
-proj2.exe
-proj2.dll
......
-Projn
-projn.exe
-projn.dll
What I am getting from my attempts below is
-Build
-proj1.exe
-proj1.dll
-proj2.exe
-proj2.dll
-projn.exe
-projn.dll
I currently have this as a .proj file. (see below)
This builds things fine, however it puts everything in the "build" folder that I specify. I want each project to be in its own seperate folder within that 'build' folder. How can I achive this?
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildOutputDir>C:\Projects\BuildScripts\Build</BuildOutputDir>
<SolutionToCompile>PathToSolution.sln</SolutionToCompile>
</PropertyGroup>
<Target Name="Clean">
<RemoveDir Directories="$(BuildOutputDir)" />
</Target>
<Target Name="Compile">
<MakeDir Directories="$(BuildOutputDir)" />
<MSBuild Projects="$(SolutionToCompile)"
properties = "OutputPath=$(BuildOutputDir)" Targets="Rebuild" />
</Target>
<Target Name="Build" DependsOnTargets="Clean;Compile">
<Message Text="Clean, Compile"/>
</Target>
</Project>
I call the .proj with a simple bat
"%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" /nologo externalBuild.proj /m:2 %*
pause
I have also tried a more complex version (copy and paste!) that looks more like it should work, but still puts things in a single folder.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildAll" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectsToBuild Include="path to solution folder\**\*proj" Exclude="$(MSBuildProjectFile)"/>
</ItemGroup>
<PropertyGroup>
<Configuration>CI</Configuration>
</PropertyGroup>
<Target Name="CoreBuild">
<MSBuild Projects ="#(ProjectsToBuild)"
ContinueOnError ="false"
Properties="Configuration=$(Configuration)">
<Output ItemName="OutputFiles" TaskParameter="TargetOutputs"/>
</MSBuild>
</Target>
<PropertyGroup>
<DestFolder>Build\</DestFolder>
</PropertyGroup>
<Target Name="CopyFiles">
<Copy SourceFiles="#(OutputFiles)"
DestinationFiles="#(OutputFiles->'$(DestFolder)%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<Target Name="CleanAll">
<!-- Delete any files this process may have created from a previous execution -->
<CreateItem Include="$(DestFolder)\**\*exe;$(DestFolder)\**\*dll">
<Output ItemName="GeneratedFiles" TaskParameter="Include"/>
</CreateItem>
<Delete Files="#(GeneratedFiles)"/>
<MSBuild Projects="#(ProjectsToBuild)" Targets="Clean" Properties="Configuration=$(Configuration);"/>
</Target>
<PropertyGroup>
<BuildAllDependsOn>CleanAll;CoreBuild;CopyFiles</BuildAllDependsOn>
</PropertyGroup>
<Target Name="BuildAll" DependsOnTargets="$(BuildAllDependsOn)"/>
</Project>
Using devenv.com to build from the command line will do what you want. It will use the output directories specified in the project files. This is what we're using, because at the moment we don't need more control over the build mechanism.

Why won't the copy task item work in my msbuild script?

I have the following code in my msbuild script:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" InitialTargets="Build">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SolutionName>CommTrac.Web\CommTrac.Web</SolutionName>
<SolutionFileName>$(SolutionName).csproj</SolutionFileName>
</PropertyGroup>
<Target Name="Build">
<Message Text="Building the solution"/>
<MSBuild Projects="$(SolutionFileName)" ContinueOnError="false" Properties="Configuration=$(Configuration)" />
</Target>
<Target Name="CopyOutput" DependsOnTargets="Build">
<ItemGroup>
<BinFolder Exclude="*.pdb" Include="$(ProjectDir)bin\**\*.*"/>
<BuildOutputFolder Include="C:\BuildOutput" />
</ItemGroup>
<Message Text="Copying from directory: $(BinFolder)"/>
<Copy SourceFiles="$(BinFolder)" DestinationFolder="$(BuildOutputFolder)"/>
</Target>
</Project>
For some reason, it will not copy the files to my output directory. I have tried all the similar
solutions with other questions that I have seen similar to this issue. Anyone have any ideas?
BindFolder and BuildOutputFolder are items, not properties. So you need to reference them using #(BindFolder) and #(BuildOutputFolder) instead of using '$'.