How to specify different BootstrapperPackage-s for x86 and x64 platforms?

Viewed 623

In my WPF project I use some third-party platform-specific dlls, e.g. if Platform is x86 then x86-versions of that dlls are copied into Output folder, and if platform is x64 then x64 versions are.

These dlls also require Visual C++ Redistributable. So I need it to be a Prerequisite to be installed when ClickOnce setup runs. The problem is I need only x64 version of C++ redist for x64 platform, and x86 for x86 platform. But I cannot just write

<BootstrapperPackage Include="Microsoft.Visual.C++.14.0.x64" Condition="'$(Platform)' == 'x64'">
  <Visible>False</Visible>
  <ProductName>Visual C++ "14" Runtime Libraries %28x64%29</ProductName>
  <Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Visual.C++.14.0.x86" Condition="'$(Platform)' == 'x86'">
  <Visible>False</Visible>
  <ProductName>Visual C++ "14" Runtime Libraries %28x86%29</ProductName>
  <Install>true</Install>
</BootstrapperPackage>

because <BootstrapperPackage> tag doesn't support Condition attribute.

It is also impossible to write multiple <ItemGroup> tags with <BootstrapperPackage>s inside them because Visual Studio turns

<ItemGroup>
  <!--common BootstrapperPackages-->
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
  <!--BootstrapperPackages for x86-->
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x64'">
  <!--BootstrapperPackages for x64-->
</ItemGroup>

into

<ItemGroup />
<ItemGroup Condition="'$(Platform)' == 'x86'" />
<ItemGroup Condition="'$(Platform)' == 'x64'">
  <!--All BootstrapperPackages: common, for x86 and for x64-->
</ItemGroup>

I cannot include both packages, because on x86 systems the installer of x64 C++ will show an error, and on x64 systems x86 C++ will be installed but it won't be used.

How can I overcome these difficulties and specify different BootstrapperPackages for different platforms?

1 Answers

Even if the BootstrapperPackage element in the csproj file supported the Condition attribute, it would be applied only at compile time which is probably not what you want.

Unfortunately here you're going to have to modify the ClickOnce Bootstrapper package manifest on your machine (and on all machines deploying this code).

On my machine the manifests for Microsoft.Visual.C++.14.0.x86 and Microsoft.Visual.C++.14.0.x64 are located at C:\Program Files (x86)\Microsoft SDKs\ClickOnce Bootstrapper\Packages\vcredist_x86\product.xml and C:\Program Files (x86)\Microsoft SDKs\ClickOnce Bootstrapper\Packages\vcredist_x64\product.xml respectively. (They might also be in C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages or any other version of the Windows SDK depending on your OS. The build log when you publish your application probably mentions where its copying the prerequisite from.)

In these files you will find a section like this (taken from my vcredist_x64 manifest)

  <!-- These checks determine whether the package is to be installed -->
  <InstallConditions>
    <BypassIf Property="VCRedistInstalled" Compare="ValueGreaterThanOrEqualTo" Value="3"/>
    <!-- Block install if user does not have admin privileges -->
    <FailIf Property="AdminUser" Compare="ValueEqualTo" Value="false" String="AdminRequired"/>
    <!-- Block install on any platform other than x64 -->
    <FailIf Property="ProcessorArchitecture" Compare="ValueNotEqualTo" Value="AMD64" String="InvalidOS"/>
    <!-- Block install on Vista or below -->
    <FailIf Property="VersionNT" Compare="VersionLessThan" Value="6.00" String="InvalidPlatformWinNT"/>
  </InstallConditions>

This line causes the error:

    <FailIf Property="ProcessorArchitecture" Compare="ValueNotEqualTo" Value="AMD64" String="InvalidOS"/>

Modify it to

    <BypassIf Property="ProcessorArchitecture" Compare="ValueNotEqualTo" Value="AMD64"/>

to skip the prerequisite instead of failing. The vcredist_x86 is configured to be installed on both 32 and 64 bits OS, if you want to force it to be installed only on 32 bits systems add the following line in its InstallConditions

    <BypassIf Property="ProcessorArchitecture" Compare="ValueEqualTo" Value="AMD64"/>

Related reading:

Related