Use 32bit “Program Files” directory in msbuild

2019-01-17 05:49发布

问题:

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.

回答1:

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.



回答2:

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' />


回答3:

In MSBuild 4.0, $(MSBuildProgramFiles32) will give you the 32-bit Program Files directory.



回答4:

Try "$(MSBuildExtensionsPath32)\.."



回答5:

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



回答6:

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.



回答7:

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)"