How do I get MSBuild Message task to display a property? - msbuild

According to the MSDN documentation, the MSBuild Message task should be able to output the contents of a property to the console.
This can be demonstrated quite simply with the following line:
<Message Text=" MSBuildProjectDirectory = $(MSBuildProjectDirectory)" />
When I run the above line as part of a build target I get something like this:
[exec] MSBuildProjectDirectory = .../somefolderpath
Within my build scripts I have a property that defines the path to an executable file. It's definition looks something like this:
<MyDir Condition="'$(MyDir)' == ''">somepath</MyDir>
<MyEXE Condition="'$(MyEXE)' == ''">$(MyDir)\somefile.exe</MyEXE>
I would like to print out the content of the $(MyEXE).
My expectation was that this would work:
<Message Text=" MyEXE= $(MyEXE)" />
...but it doesn't. In fact, it behaves as though the line wasn't there at all.
For the following:
<Message Text="TEMP START"/>
<Message Text=" MSBuildProjectDirectory = $(MSBuildProjectDirectory)" />
<Message Text='dollar1 "$(MyEXE)"'/>
<Message Text="dollar2 '$(MyEXE)'"/>
<Message Text='dollar3 $(MyEXE)'/>
<Message Text="dollar4 $(MyEXE)"/>
<Message Text='at1 "#(MyEXE)"'/>
<Message Text="at2 '#(MyEXE)'"/>
<Message Text='at3 #(MyEXE)'/>
<Message Text="at4 #(MyEXE)"/>
<Exec Command='echo "$(MyEXE)"' />
<Exec Command='echo FOO' />
<Message Text="TEMP END"/>
...I get the following output:
[exec] TEMP START
[exec] MSBuildProjectDirectory = .../somepath
[exec] at1 ""
[exec] at2 ''
[exec] at3
[exec] at4
[exec] echo FOO
[exec] FOO
[exec] TEMP END
The very next line is
<Exec Command='"$(MyEXE)" /someparameter' />
...which executes the exe successfully, so it clearly contains a value.
It's worth noting that my use of #(MyEXE) is entirely my ignorance clutching at straws.
Does anyone know how I print the content of $(MyEXE) to the console?

In my case, MSBuild.exe is being called from an ant exec task. If this step is removed and MSBuild called directly from the command line, the problem goes away.
Update 2017.02.08:
Investigating further, I have found that our ant build scripts parse the console output from msbuild to 'helpfully' remove 'unwanted' content using an array of regex-based string replacement.
As an aside, the '[exec]' at the beginning of the output that I posted in the question is added by ant.

Related

Why doesn't Visual Studio Build output the Message in the Target element having a custom name?

My project has a different behaviour locally and on production.
I have concluded that some Tasks in my .vbproj don't get executed locally neither in DEBUG or RELEASE mode. For example, I have a Message in a element, and it doesn't appear in the OUTPUT window after build.
Is my conclusion wrong? Am I missing something here?
doesn't display message in console:
<Target Name="test12345">
<Message Text="This is a test message" Importance="high" />
</Target>
displays message in console:
<Target Name="AfterBuild">
<Message Text="This is a test message" Importance="high" />
</Target>
The AfterBuild name makes it automatically run after a project is built (to be specific, AfterBuild is already defined but meant to be overwritten in custom projects).
When you define a target with a custom name, you need to hook it into the build as well, e.g. by using AfterTargets:
<Target Name="test12345" AfterTargets="Build">
<Message Text="This is a test message" Importance="high" />
</Target>

How do I run a jar file with msbuild?

I'm trying to make Visual Studio do my entire build, currently I've got my extra build steps written in nant. But it's not ideal having to run ant separately.
I'm trying to run a jar file named plovr as part of my node application, although at the moment publish keeps failing on the line I've added to my build with exit code 1. This is the code I'm trying at the end of my build file within the <Project></Projet> tags.
<Target Name="Build">
<Exec Command="java -jar $(Plovr) build $(PlovrConfig)" />
</Target>
I've got these properties setup earlier in the file
<Plovr>dependencies\plovr.jar</Plovr>
<PlovrConfig>dependencies\plovr-config.js</PlovrConfig>
How can I get msbuild to run the plovr.jar?
If you put in the full path to java.exe.....the EXEC command should work.
It just does a command line call....at the end of the day.
<Target Name="Build">
<Exec Command=""C:\Program Files (x86)\Java\jre7\bin\java.exe" -jar $(Plovr) build $(PlovrConfig)" />
</Target>
Also note the use of " .. to delimit a quote...
You can also put in some Message's to make sure you have what you think you have:
<Message Text="Plovr: $(Plovr)"/>
<Message Text="PlovrConfig: $(PlovrConfig)"/>

ResolveComReference Invalid argument. Parameter "ItemSpec" cannot be null

I am in the process of upgrading a project to .NET 4.0 and I get this error when I try and build the solution: Invalid argument. Parameter "ItemSpec" cannot be null. c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets 1558 9
Is there a way to find out what is being passed as null to the ResolveComReference task?
Try this; temporarily add the following to the project file that is failing:
<Target Name="DiagnoseNullItems"
BeforeTargets="ResolveComReferences"
AfterTargets="ResolveAssemblyReferences">
<Message Importance="High" Text="COMReference is '#(COMReference)'" />
<Message Importance="High" Text="COMFileReference is '#(COMFileReference)'" />
<Message Importance="High" Text="ReferencePath is '#(ReferencePath)'" />
<Message Importance="High" Text="_ResolveComReferenceCache is '#(_ResolveComReferenceCache)'" />
</Target>
I think that is all of them, unless some of the other $() arguments to that task are also of type ITaskItem. If that doesn't reveal an empty item, do the same for the properties passed to the ResolveComReference task.

MSBuild echo task?

Is there a task in MSBuild that's synonymous with NAnt's <echo> task?
I don't want anything fancy, just a simple message output to stdout.
MsBuild has the Message task built in which will output a string to the console:
<Target ...>
<Message Text="text to output" />
</Target>
By default, MSBuild logs at minimal verbosity which will prevent these messages from being seen. Either increase the verbosity, or set the Message's Importance parameter to high:
<Target ...>
<Message Text="text to output ALWAYS" Importance="high" />
</Target>

How do you stop MSBuild execution without raising an error?

With MSBuild, as soon as an error occurs, the execution of the project is stopped unless ContinueOnError=true.
Is there a way to stop the execution of the project without raising an error?
I'd like to have this possibility because I have an existing set of msbuild project files and in some circumstances, I would need to stop processing the projects without raising an error because it is a normal exit point for the process and I don't want the person using the script to think something is wrong.
I know I could just set some property and put all remaining tasks conditional on this but I would like to avoid that.
As you explain it, you want to stop your build under special circumstance without raising an error because it is a normal exit point. Why not create a target doing nothing that will serve as your exit point. Under your special conditions you will call this target.
<target Name="BuildProcess">
<Message Text="Build starts"/>
...
<CallTarget Targets="Exit"
Condition="Special Condition"/>
<CallTarget Targets="Continue"
Condition="!(Special Condition)"/>
...
</target>
<target Name="Continue">
<Message Text="Build continue"/>
</target>
<target Name="Exit">
<!-- This target could be removed -->
<!-- Only used for logging here -->
<Message Text="Build ended because special condition occured"/>
</target>
The way to do this is the create another target to wrap the target you're interested in conditioning.
So if you have a scenario with a target like this:
<Target Name="MainTarget">
command - run under a certain condition
command - run under a certain condition
command - run under a certain condition
command - run under a certain condition
command - run under a certain condition
</Target>
The point is that you want to save having to use the condition statement a whole bunch of times, right?
To address this, you can do this:
<Target Name="MainWrapper" DependsOnTargets="EstablishCondition;MainTarget" />
<Target Name="EstablishCondition">
<SomeCustomTask Input="blah">
<Output PropertyName="TestProperty" TaskParameter="value" />
</SomeCustomTask>
</Target>
<Target Name="MainTarget" Condition="$(TestProperty)='true'">
command
command
command
command
command
</Target>
Eventually found an elegant solution for a similar issue. I just needed to rephrase my concern from "Break/interrupt MSBuild execution" to "Skip the next targets".
<PropertyGroup>
<LastInfoFileName>LastInfo.xml</LastInfoFileName>
<NewInfoFileName>NewInfo.xml</NewInfoFileName>
</PropertyGroup>
<Target Name="CheckSomethingFirst" BeforeTargets="DoSomething">
<Message Condition="ConditionForContinue"
Text="Let's carry on with next target" />
<WriteLinesToFile Condition="ConditionForContinue"
File="$(NewInfoFileName)"
Lines="#(SomeText)"
Overwrite="true" />
<Message Condition="!ConditionForContinue"
Text="Let's discard next target" />
<Copy Condition="!ConditionForContinue"
SourceFiles="$(LastInfoFileName)"
DestinationFiles="$(NewInfoFileName)" />
</Target>
<Target Name="DoSomething" Inputs="$(NewInfoFileName)"
Outputs="$(LastInfoFileName)">
<Message Text="DoSomethingMore" />
<Copy SourceFiles="$(NewInfoFileName)"
DestinationFiles="$(LastInfoFileName)" />
</Target>
This works ok with a command like:
msbuild.exe Do.targets /t:DoSomething
where target DoSomething Inputs/Outputs are correctly checked after the CheckSomethingFirst target was executed.