In 64 bit versions of windows, 32 bit software is installed in "c:\program files (x86)". This means you cannot use $(programfiles) to get the path to (32 bit) software. So I need a $(ProgramFiles32) to overcome this in my MSBuild project. I don't want to change the project depending on the os it is running on.
I have a solution that I will post, but maybe there is a easier/better way.
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.
My solution is to look whether "c:\program files (x86)" exists, if it exists, asume this is a 64 bit os. Otherwise use the normal program files directory:
<PropertyGroup>
<ProgramFiles32 Condition="Exists('$(PROGRAMFILES) (x86)')">$(PROGRAMFILES) (x86)</ProgramFiles32>
<ProgramFiles32 Condition="$(ProgramFiles32) == ''">$(PROGRAMFILES)</ProgramFiles32>
</PropertyGroup>
I can use it like this
<Exec WorkingDirectory="src\app1" Command='"$(ProgramFiles32)\doxygen\bin\doxygen" Doxyfile' />
In MSBuild 4.0, $(MSBuildProgramFiles32)
will give you the 32-bit Program Files directory.
Try "$(MSBuildExtensionsPath32)\.."
I think a slighly more reliable way is to grab the Environment variable "ProgramFiles(x86)". In a 64 bit process on Windows this will point to the 32 bit program files directory. It will be empty on a 32 bit version of windows and I believe on a wow64 process
I ran into virtually same problem recently with some PowerShell scripts. I wrote a blog entry on how a worked around the program files directory issue. Different language obviously but it may help you out.
http://blogs.msdn.com/jaredpar/archive/2008/10/21/program-files-i-just-want-the-32-bit-version.aspx
I stumbled across this question trying to find a generic way in MSbuild to see if it was a 32- or 64-bit os. In case someone else also find this, I used the following:
<PropertyGroup>
<OSBits Condition="$(ProgramW6432) != ''">x64</OSBits>
<OSBits Condition="$(OSBits) == ''">x32</OSBits>
</PropertyGroup>
Apparently %ProgramW6432%
is only set on 64-bit systems.
If you run the 32-bit version of the Visual Studio tools (especially in VS2012, there are like 3 different command prompts you can choose from), $(ProgramFiles) points to "Program Files (x86)"