In MSBuild 4.0+, there's a $(MSBuildProgramFiles32)
property for it, which you can confidently employ directly (especially if you're prepared to put a ToolsVersion="4.0"
at the top of the file to guarantee it's going to be available and Fail Fast if it's not).
If you're not and need something that can Do The Right Thing even when executed in an MSBuild 2.0 or later environment (i.e., back to VS 2005 environments), the complete solution is:
<PropertyGroup>
<!--MSBuild 4.0 property-->
<ProgramFiles32>$(MSBuildProgramFiles32)</ProgramFiles32>
<!--Use OS env var as a fallback:- 32 bit MSBuild 2.0/3.5 on x64 will use this-->
<ProgramFiles32 Condition=" '' == '$(ProgramFiles32)'">$(ProgramFiles%28x86%29)</ProgramFiles32>
<!-- Handle MSBuild 2.0/3.5 running in 64 bit mode - neither of the above env vars are available. http://stackoverflow.com/questions/336633
NB this trick (Adding a literal " (x86)" to the 64 bit Program Files path) may or may not work on all versions/locales of Windows -->
<ProgramFiles32 Condition ="'$(ProgramFiles32)'=='' AND 'AMD64' == '$(PROCESSOR_ARCHITECTURE)'">$(ProgramFiles) (x86)</ProgramFiles32>
<!--Catch-all - handles .NET 2.0/3.5 non-AMD64 and .NET 2.0 on x86 -->
<ProgramFiles32 Condition=" '' == '$(ProgramFiles32)' ">$(ProgramFiles)</ProgramFiles32>
</PropertyGroup>
Unfortunately Progressive enhancement / polyfill overriding of the MSBuild reserved property name MSBuildProgramFiles32
via either a <PropertyGroup>
or <CreateProperty>
is rejected by MSBuild 4.0+ so it can't be made tidier and still support .NET 2.0.