You correctly noticed, that you can achieve behavior you want with unconditional assignment of property. The following project when built without /p: override on command line will produce Default Value
. And when built using command msbuild myproj.proj /t:DefaultsTest /p:MyProperty=NewValue
will produce NewValue
.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MyProperty>Default Value</MyProperty>
</PropertyGroup>
<Target Name="DefaultsTest">
<Message Text="MyProperty=$(MyProperty)"></Message>
</Target>
</Project>
This is because any properties specified on MSBuild command line or provided as a parameter of task will be treated as Global Properties. For global properties, any assignment or modifications, either conditional or unconditional, are simply ignored -- global properties will remain constant throughout lifetime of the project execution.
The only difference in behavior between conditional assignment and unconditional will be if you use TreatAsLocalProperty attribute.
For example, consider the following project:
<Project TreatAsLocalProperty="Prop1;Prop2" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Prop1>Prop1 Default Value</Prop1>
<Prop2 Condition="$(Prop2) == ''">Prop2 Default Value</Prop2>
</PropertyGroup>
<Target Name="DefaultsTest">
<Message Text="Prop1=$(Prop1)"></Message>
<Message Text="Prop2=$(Prop2)"></Message>
</Target>
</Project>
Two properties -- Prop1 and Prop2 are both declared as local in the Project element. Prop1 is assigned unconditionally, while Prop2 is assigned using non-empty condition. Executing build command:
msbuild b.proj /t:DefaultsTest /p:Prop1=NewValue1 /p:Prop2=NewValue2
will produce output:
Prop1=Prop1 Default Value
Prop2=NewValue2
This means that in general case (if you are not absoluterly sure if property will be global or local), it is safer to use conditional assignment of the default value, because it works always.