MSBuild Exec fail when UseCommandProcessor set to True - msbuild

I define a target to call an exec
<Target Name="BuildInstaller" >
<Exec Command="attrib -R /S /D $(MSBuildProjectDirectory)\Environment\Installer\ServicePlatform\*.*" />
<Exec Command="dir *.* /s" />
</Target>
it Works perfectly
but if I add the UseCommandProcessor set to True
<Target Name="BuildInstaller" >
<Exec Command="attrib -R /S /D $(MSBuildProjectDirectory)\Environment\Installer\ServicePlatform\*.*" />
<Exec Command="dir *.* /s" UseCommandProcessor="True"/>
</Target>
I got this:
c:\Dev>/Q /C:\Users\MyUser\AppData\Local\Temp\tmp63250fcf10714224b92eeeb09e25b6f5.exec.cmd
'/Q' is not recognized as an internal or external command, operable program or batch file.
why this happen? What am I doing wrong?

Related

MS Build Task not accepting properties

I am trying to build my project using MSbuild. The solution builds perfectly fine if I hardcode the configurations
<MSBuild Projects="%(SolutionsToBuild.Identity)" Properties="Configuration=Debug" ContinueOnError="false"/>
<MSBuild Projects="%(SolutionsToBuild.Identity)" Properties="Configuration=Release" ContinueOnError="false"/>
but if I use batching like this the values are not assigned
<MSBuild Projects="%(SolutionsToBuild.Identity)" Properties="Configuration=%(ConfigList.Identity)" ContinueOnError="false"/>
where ConfigList
<ItemGroup>
<ConfigList Condition=" '#(ConfigList)' == '' and $(Configuration) != '' " Include="$(Configuration.Split(';'))" />
<!-- parse all requested configurations into a list -->
<ConfigList Condition=" '#(ConfigList)' == '' " Include="Debug" />
<!-- if no configurations were specified, default to Debug -->
</ItemGroup>
and Configurations are provided from CLI
msbuild build.proj -p:Configuration="Release;Debug"
Also interestingly I am getting the value in
<Message Text="Build for configuration %(ConfigList.Identity)"/>
Whole Code
<Target Name="BuildApplication">
<ItemGroup>
<ConfigList Condition=" '#(ConfigList)' == '' and $(Configuration) != '' " Include="$(Configuration.Split(';'))" />
<!-- parse all requested configurations into a list -->
<ConfigList Condition=" '#(ConfigList)' == '' " Include="Debug" />
<!-- if no configurations were specified, default to Debug -->
</ItemGroup>
<Message Text="Build for configuration %(ConfigList.Identity)"/>
<MSBuild Projects="%(SolutionsToBuild.Identity)" Properties="Configuration=%(ConfigList.Identity)" ContinueOnError="false"/>
<!--<MSBuild Projects="%(SolutionsToBuild.Identity)" Properties="Configuration=Debug" ContinueOnError="false"/>-->
</Target>
I am not sure what I am doing wrong. Any help would be appreciated. Thanks !
Sources referred:
Using MSBuild to Build Multiple Configurations
Passing properties to MSBUILD Task

msbuild - export all properties defined in block to MSBuild calls

<Target Name="micropython_prebuild">
<PropertyGroup>
<uP_PrebuildPyExe>"$(ProjectDir)\Source\micropython\py\make_prebuild_wrapper.exe"</uP_PrebuildPyExe>
<GnuCat>$(uP_PrebuildPyExe) gnu_cat</GnuCat>
<GnuSed>$(uP_PrebuildPyExe) gnu_sed</GnuSed>
<uP_GenHdrFolder>$(ObjectFolder)\genhdr</uP_GenHdrFolder>
<uP_QSTR_GEN_EXTRA_CFLAGS>-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB -DN_ARM -DN_XTENSA</uP_QSTR_GEN_EXTRA_CFLAGS>
<uP_SRC>$(ProjectDir)\Source\micropython</uP_SRC>
<uP_MPY_CROSS>"$(ProjectDir)\Source\micropython\mpy-cross\mpy-cross.exe"</uP_MPY_CROSS>
</PropertyGroup>
<MakeDir Directories="$(uP_GenHdrFolder)\"/>
<MSBuild
Projects="$(MSBuildProjectFile)"
Condition="'' == ''"
Targets="prebuild_mpversion"
Properties="uP_PrebuildPyExe=$(uP_PrebuildPyExe);
uP_GenHdrFolder=$(uP_GenHdrFolder)"
/>
</Target>
How do I "export" all the properties I've defined at the top to the calls to MSBuild within this target?
Otherwise, I have to set the Properties of each MSBuild.
You can also create a single property that contains all the definitions:
<Target Name="micropython_prebuild">
<PropertyGroup>
<PrebuildProperties>
uP_PrebuildPyExe="$(ProjectDir)\Source\micropython\py\make_prebuild_wrapper.exe";
GnuCat=$(uP_PrebuildPyExe) gnu_cat;
GnuSed=$(uP_PrebuildPyExe) gnu_sed;
uP_GenHdrFolder=$(ObjectFolder)\genhdr;
uP_QSTR_GEN_EXTRA_CFLAGS=-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB -DN_ARM -DN_XTENSA;
uP_SRC=$(ProjectDir)\Source\micropython;
uP_MPY_CROSS="$(ProjectDir)\Source\micropython\mpy-cross\mpy-cross.exe";
</PrebuildProperties>
</PropertyGroup>
<MakeDir Directories="$(uP_GenHdrFolder)\"/>
<MSBuild
Projects="$(MSBuildProjectFile)"
Condition="'' == ''"
Targets="prebuild_mpversion"
Properties="$(PrebuildProperties)"
/>
</Target>

Retrieving the nupkg version number in msbuild

I've modified a csproj file in VS2017 to create a Nuget package when my .NET 4.5 project is release-built. The next automation step is to add this package to my private feed on a network share. Here are the commands I'm using:
<Exec Command="nuget.exe pack -Properties "Configuration=Release" -Symbols $(ProjectName).csproj" />
<Exec Command="nuget.exe add $(ProjectName).$(ProductVersion).nupkg -source \\MYSERVER\Nuget packages" />
Line 1 works and produces a nupkg file of the form productname.nn.nn.nn.nn.
However line 2 is not returning a value for the ProductVersion token (which was a guess on my part).
I've struggled to find a reference for MSBUILD tokens (that in itself would be useful to know), but what I really need to know is the correct MSBUILD token/variable/property for the the version - and that is the same value as the generated Nuget package.
I explored $(PackageVersion) suggested by Martin Ullrich, but it's not going to work with older projects even with Nuget 4.10 installed. Also I couldn't get Troopers sample to work how I wanted and I ended up with a variation on one of the posts here. I adapted it to give me the assembly version as opposed to the file version.
<UsingTask TaskName="GetVersionParts" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<AssemblyPath ParameterType="System.String" Required="true" />
<MajorVersion ParameterType="System.Int32" Output="true" />
<MinorVersion ParameterType="System.Int32" Output="true" />
<BuildVersion ParameterType="System.Int32" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.Reflection" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Version v = AssemblyName.GetAssemblyName(this.AssemblyPath).Version;
this.MajorVersion = v.Major;
this.MinorVersion = v.Minor;
this.BuildVersion = v.Build;
]]>
</Code>
</Task>
</UsingTask>
<Target Name="AfterBuild" Condition=" '$(Configuration)' == 'Release'">
<Message Text="**** After-build process starting ****" />
<Exec Command="nuget.exe pack -Properties "Configuration=Release" -Symbols $(ProjectName).csproj" />
<GetVersionParts AssemblyPath="$(OutputPath)$(AssemblyName).dll">
<Output TaskParameter="MajorVersion" PropertyName="MajorVersionNumber" />
<Output TaskParameter="MinorVersion" PropertyName="MinorVersionNumber" />
<Output TaskParameter="BuildVersion" PropertyName="BuildVersionNumber" />
</GetVersionParts>
<Exec Command="nuget.exe add $(MSBuildProjectName).$(MajorVersionNumber).$(MinorVersionNumber).$(BuildVersionNumber).nupkg -source "\\My feed server\Shared location"" />
<Exec Command="move *.symbols.nupkg "\\My feed server\Shared location\Symbols"" />
<Message Text="**** After-build process completed ****" />
</Target>
Although this works, I can't help feeling that it should be easier.
Further reading
https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-inline-tasks
https://learn.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-properties
https://learn.microsoft.com/en-us/nuget/tools/nuget-exe-cli-reference#add
You could get the assembly version with this macro. I call it before the postbuild event for example
<!--Macro to get the version -->
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="CurrentAssembly" />
</GetAssemblyIdentity>
<ItemGroup>
<VersionNumber Include="%(CurrentAssembly.Version)" />
</ItemGroup>
</Target>
<!-- override PostBuildEvent to call PostBuildMacros -->
<PropertyGroup>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
<PostBuildEvent>
...
</PostBuildEvent>
</PropertyGroup>

How to use msbuild.exe cmd line in NANT using <exec program >

How to use msbuild.exe long cmd line using Nant script.MSBuild command is -->
<target name="publish-project-release-folder">
<exec program="C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe" verbose="true" >
<arg value="/target:Build;PipelinePreDeployCopyAllFilesToOneFolder" />
<arg value="/p:Configuration=Release;_PackageTempDir=C:\cicheckout\outdir\;AutoParameterizationWebConfigConnectionStrings=false" />
<arg value="C:\a\testteamcity\demo\WebApp\webapp.csproj" />
</exec>
Error : C:\245\hello.build(9,6):
'C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe' is not a valid value for attribute 'program' of <exec ... />.
Illegal characters in path.
Total time: 0 seconds.

MSBuild copy task and condition name from file with wildcards

I have a FilesToExclude2.txt file which contains all excludes like this :
*.settings
*#*
*.vbproj*
*.csproj*
*\Errors\*
*\Errors
*\_vti_*\*
*\_vti_*
*\CVS\*
In my tasks file, there is a copy task
<Target Name="CustomModuleCopy">
<ItemGroup>
<ModuleFiles Include="$(SolutionModuleName)\$(ProjectModuleName)\**\*.*" />
<FileToExclude Include="$(BasePath)\$(SolutionModuleName)\FilesToExclude2.txt" />
</ItemGroup>
<ReadLinesFromFile File="#(FileToExclude)">
<Output TaskParameter="Lines" ItemName="FileContents" />
</ReadLinesFromFile>
<Copy SourceFiles="#(ModuleFiles)" DestinationFiles="#(ModuleFiles->'$(DestFolder)\$(ProjectModuleName)\%(RecursiveDir)%(Filename)%(Extension)')" Condition="'%(ModuleFiles.Identity)' != #(FileContents)" ContinueOnError="false" />
<!--CallTarget Targets="RemoveCustomModuleConfigFiles" /-->
</Target>
Without the "condition" attribute on the copy task, everything's works fine, but I do not know how to implement the condition with wildcard and if it is possible
Any kind of help would be greatly appreciated :) this is freaking me out for few hours...
Would it not be easier to just use the exclude property instead?
as in
Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ModuleFiles Include="c:\code\**\*.*"
Exclude="#(FileContents)" />
</ItemGroup>
<!--<Copy SourceFiles="#(ModuleFiles)" DestinationFolder="Some|Destination" Condition="'%(ModuleFiles.Identity)' != #(FileContents)" ContinueOnError="false" />
CallTarget Targets="RemoveCustomModuleConfigFiles" /-->
the following code
<Target Name="CustomModuleCopy">
<ItemGroup>
<FileToExclude Include="$(BasePath)\$(SolutionModuleName)\FilesToExclude.txt" />
</ItemGroup>
<ReadLinesFromFile File="#(FileToExclude)">
<Output TaskParameter="Lines" ItemName="FileContents" />
</ReadLinesFromFile>
<ItemGroup>
<ModuleFiles Include="$(SolutionModuleName)\$(ProjectModuleName)\**\*.*" Exclude="#(FileContents)" />
</ItemGroup>
<Copy SourceFiles="#(ModuleFiles)" DestinationFiles="#(ModuleFiles->'$(DestFolder)\$(ProjectModuleName)\%(RecursiveDir)%(Filename)%(Extension)')" ContinueOnError="false" />
<Message Text="Exclude = #(FileContents)" />
<!--CallTarget Targets="RemoveCustomModuleConfigFiles" /-->
</Target>
produce this output in console :
copy /y "CPBMessaging\CPBMessagingWeb_NotificationMessage\Web.Debug.config" "C:\__CPB\CPBSite\CPBMessagingWeb_NotificationMessage\Web.Debug.config"
Copying file from "CPBMessaging\CPBMessagingWeb_NotificationMessage\Web.Release.config" to "C:\__CPB\CPBSite\CPBMessagingWeb_NotificationMessage\Web.Release.config"
copy /y "CPBMessaging\CPBMessagingWeb_NotificationMessage\Web.Release.config" "C:\__CPB\CPBSite\CPBMessagingWeb_NotificationMessage\Web.Release.config"
Exclude = *.cab;*.config;*.vb;*.cs;*.resx;*.xsx;*.bak;*.myapp;*.settings;*#*;
*.vbproj*;*.csproj*;*\Errors\*;*\Errors;*\_vti_*\*;*\_vti_*;*\CVS\*;*\CVS;