ClickOnce 4.0 package for the C++ 2008 SP1 Redist ATL Security Update

ClickOnce is a great technology that simplifies the setup and install process for the end user. I ended up in a project where there was a need to install the latest SQL Server Compact Edition 4.0 in private distribution mode in a .NET v4 solution. In theory, that’s just the case of distributing the SQL CE runtime DLL’s to the destination folder. But wait, there’s a catch. The latest SQL CE v4.0 is dependent on the Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package ATL Security Update. (msvcr90.dll version 9.0.30729.4148) Well, that shouldn’t be a problem, just open up the prerequisites dialog in VS 2010 and put a check mark into….. oh darn. There is no bootstrapper package for the 2008 VC++ Redist in Visual Studio 2010, just the newest 2010 VC++ redist package.

So what to do?

Well, just create you own bootstrapper package, and here I will guide you through the steps.

First, create a new folder in the package install location for the bootstrapper. The default location is C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages. Create a folder named vcredist_2008SP1_x86. Download the Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package ATL Security Update and save the vcredist_x86.exe  into this new folder.

image

Create a product.xml file in the new location and enter the following:

<?xml version="1.0" encoding="utf-8" ?> 

<Product
  xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper"
  ProductCode="Microsoft.Visual.C++.9.0.x86"
>

  <!-- Defines list of files to be copied on build -->
  <PackageFiles>
    <PackageFile Name="vcredist_x86.exe" HomeSite="VCRedistExe"/>
  </PackageFiles>
  <InstallChecks>
    <MsiProductCheck Property="VCRedistInstalled" Product="{1F1C2DFC-2D24-3E06-BCB8-725134ADF989}"/>
  </InstallChecks>
  
  <!-- Defines how to invoke the setup for the Visual C++ 10.0 redist -->
  <!-- TODO: Needs EstrimatedTempSpace, LogFile, and an update of EstimatedDiskSpace -->
  <Commands Reboot="Defer">
    <Command PackageFile="vcredist_x86.exe" 
         Arguments=' /q:a ' 
         >

      <!-- 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 Win95 -->
        <FailIf Property="Version9X" Compare="VersionLessThan" Value="4.10" String="InvalidPlatformWin9x"/>

        <!-- Block install on NT 4 or less -->
        <FailIf Property="VersionNT" Compare="VersionLessThan" Value="5.00" String="InvalidPlatformWinNT"/>

      </InstallConditions>
      
      <ExitCodes>
        <ExitCode Value="0" Result="Success"/>
        <ExitCode Value="3010" Result="SuccessReboot"/>
        <DefaultExitCode Result="Fail" FormatMessageFromSystem="true" String="GeneralFailure" />
      </ExitCodes>
      
    </Command>
  </Commands>
</Product>

 

Create a new folder inside vcredist_2008SP1_x86 and name it en. In the en folder, create a package.xml, and copy paste the following:

<?xml version="1.0" encoding="utf-8" ?>

<Package
  xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper"
  Name="DisplayName"
  Culture="Culture"
>

    <!-- Defines a localizable string table for error messages-->
    <Strings>
        <String Name="DisplayName">Visual C++ 2008 SP1 Runtime Libraries (x86)</String>
        <String Name="Culture">en</String>
        <String Name="AdminRequired">You do not have the permissions required to install Visual C++ 2008 SP1 Runtime Libraries (x86). Please contact your administrator.</String>
        <String Name="InvalidPlatformWin9x">Installation of Visual C++ 2008 SP1 Runtime Libraries (x86) is not supported on Windows 95. Contact your application vendor.</String>
        <String Name="InvalidPlatformWinNT">Installation of Visual C++ 2008 SP1 Runtime Libraries (x86) is not supported on Windows NT 4.0. Contact your application vendor.</String>
        <String Name="GeneralFailure">A failure occurred attempting to install Visual C++ 2008 SP1 Runtime Libraries (x86).</String>
        <String Name="VCRedistExe">http://download.microsoft.com/download/9/7/7/977B481A-7BA6-4E30-AC40-ED51EB2028F2/vcredist_x86.exe</String>
    </Strings>
    
</Package>

 

Now, when you restart Visual Studio 2010, you should have a new package for the Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package ATL Security Update:

image

And when the end user runs the ClickOnce setup, it will automatically install the VC++ redist if it’s not installed already.

Getting started with WTL on Visual Studio 2010

WTL on Visual Studio 2010

Now that you have downloaded the latest WTL release (v8.1 at the time of this writing), you will find out that it doesn’t have any project wizards for Visual Studio 2010. That’s a relatively easily fix. Just go ahead and download the latest build from the repository at AppWiz.tar.gz-view=tar. Extract the .tar file and you will find the JavaScript install scripts for VS 2010:

image

I recommend you to extract the files to the same location were you installed the WTL files. In my case this would be c:\WTL.  Double click the setup100.js file (or setp100x.js for Visual Studio 2010 Express) to install the WTL Project Wizard.

Add the WTL include path to the default include directories

One thing you may have noticed in VS2010 (compared to earlier versions) is that there is no way to set the global paths of VC++ directories in Tools->Options:

image

Bummer. How to solve that? You really don’t want to have to include the WTL include path in every VC++ project. Here’s how to set the global paths and include the WTL include path. It’s really not that intuitive, if I would say.

First you will need to have a project open in VS 2010. Then go to View->Other Windows->Property Manager. In the Property Manager, expand the project and the platforms nodes. Multi-select the two Microsoft.Cpp.Win32.user items. (By holding down the Ctrl key and select them each by the mouse).

image

Right click and select properties

image

Now you finally can set the global default search paths for the VC++ include directories. In my case I have added the C:\WTL\Include path. Save the properties settings restart Visual Studio.

If you open one of the samples in the WTL folders, you may stumble upon a peculiar error that says: error CVT1100: duplicate resource.  type:MANIFEST, name:1, language:0x0409

image

This is because the way manifest files are handled in VS 2010 has changed. What you can do is to open the resource file (.rc), edit it by selecting “View Code” and remark out the line

//CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "res\\BmpView.exe.manifest"

Now, happy WTL’ing in Visual Studio 2010.