October 06, 2010

VSTO 4 ( 2010 ) Lessons Learned

Two and a half years ago, I posted the blog VSTO Lessons Learned. Since then Microsoft has released .NET 4.0, Visual Studio 2010, Office 2010, VSTO 2010 Runtime.   Recently, Stefan Krueger  posted a link to an article over at MSDN called Deploying a Visual Studio 2010 Tools for Office Solution Using Windows Installer.   This was of interest to me since I've recently been working on a project for a client that needed to deploy an Outlook AddIn developed in .NET 4.0 / VSTO 4 targeting Office 2007 / 2010 (x86/x64) on Windows XP ( x86), Vista (x86/x64) and Windows 7  (x86/x64).  As a result of this project I've become intimately familiar with the deployment requirements of such an application and I can say with confidence that the MSDN article has missed the mark.

First, the article teaches the use of Visual Studio Deployment Projects and Installer Class custom actions despite Microsoft announcing that VDPROJ is retired and every MSI expert at Microsoft declaring Managed InstallUtil Custom actions evil.  In case you aren't aware, not only are Installer class custom actions fragile, but VDPROJ will schedule the custom actions with impersonation.  That's a horrible combination if you want to support UAC / Elevated Installs. (Which you should.)

Then they suggest building X86 and X64 MSI's to support Office 2010 x86 / x64 when in reality the only difference is which registry hive you register the AddIn. ( See: Office 2010 Bitness Pain )  This seems to me Microsoft's answer to bitness but many people, including myself, are concerned about the environment.

Not to overlook a single detail, I noticed that their LaunchCondition exampes fail to include "or Installed" to prevent problems during repairs and uninstalls. 

But let's get to what I consider the really import lessons learned:

Office 2007 Beware

There are two problems lurking in Office 2007 GA:

1) It only supports registering Per-User AddIns.

2)  It doesn't load VSTO AddIns unless .NET CLR 2.0 installed.  This is even true if your VSTO is authored using .NET CLR 4.0

There's a hotfix and registry value  that fixes this however the hotfix is not redistributable and requires Office 2007 SP2 already be installed anyways.  ( See: Deploying your VSTO add-ins to All Users, KB976811 and KB976477 )

Frankly, if you come across a machine in this state, there isn't much you can do legally.  You can't redist SP2 and KB976477.  You can pretty much do one of a few things:

1) Add .NET 2.0 to your bootstrapper and use the unsupported/ not recommended HKLM - > HKCU registry propogation pattern described at Deploying your VSTO add-ins to All Users.

2) Add .NET 2.0 to your bootstrapper and use a mutually exclusive registry component to register the AddIn in the user profile and rely on Advertisement to fix it for other users.  ( "Please wait while Windows Installer Repairs [ProductName]...."  badness. )

2) Author a System Search / Launch Condition to block the install.  For this I author one search to look for [CommonFilesFolder]Microsoft Shared\Office12\mso.dll  ( MSO12DLLFOUND) and another one to look for it as  min version 12.0.6520.4999 ( MSO12DLLGOODFOUND )  The LaunchCondition is then

Installed or Not MSO12DLLFOUND or (MSO12DLLFOUND and GOODMSO12DLLFOUND)

[ProductName] Setup has detected a problem with your installation of Office 2007 that must be fixed before installing [ProductName].  Please visit Windows Update or read Microsoft Knowledge Base Article KB976477.

Perquisites

The preqs for this type of application seem simple at first:

.NET 4.0
VSTOR 4

However,  VSTOR4 is really two packages:  x86 and x64.   Also .NET 4.0 also has a requirement for Windows Installer 3.1 and Windows Imagine Component.   See, Microsoft figures that most people will already have these so they didn't include it in the .NET 4.0 bootstrapper.   That won't save your hide though when your customer doesn't have it so along for the ride they must come.

Oh, and did I mention that I have observed that you may have to reboot after installing .NET 4.0 or otherwise VSTOR4 won't install properly?

Finally my client got cute and wrote some C++ code so I had to add the x86 and x64 C++ 2010 Redist packages.  

Here's the final list:



Let's look at our supported configurations and the packages / special notes:

Windows XP SP2 ( x86 )


This is clearly the worst case scenario.  In fact, to support all of this our prereqs folder grows to 92MB. Adding in the Setup.exe and my clients actual MSI and we are at 95MB.    Fortunatly InstallShield can build multiple releases per Product Configuration so I get to give my client choices of CDROM (95MB), Offline EXE (95MB) and Online EXE ( 3MB ).

Windows XP SP3 ( x86 )

MSI 3.1 and WIC can be skipped as these are included in the service pack.

Windows Vista / 7 ( x86 )


MSI 3.1 and WIC can be skipped as can .NET 2.0 as these (or newer)  are all included in Vista / 7 .

Windows Vista/7 (x64)



Now it gets interesting.  Up until now InstallShield 2010 provided all the Setup Prereqs that I needed.  However I couldn't find a VSTO 2010 ( 4 ) x64 prereq so I had to roll one.  Also  the C++ 2010 x86/x64 prereqs only installed on x86/x64 windows respectively.   That doesn't seem correct to me.  The x86 redist will install on either x86 or x64 windows and it seems logical to me that an x86 process on an x64 machine could have a dependency on the x86  C++ runtime.  Also a .NET AnyCPU could go either way and God only knows how an AddIn loaded into Office 2010 x86 might behave differently then an AddIn loaded into Office x64.   So to play it safe I tweaked the InstallShield provided prereq and gave it a condition to install on either platform.

Whew, that was a lot to write for one night and I hope I covered it all.   It seems like to me that Microsoft treats VSTO as this easy ClickOnce deployment story but in reality the deployment story is quite complicated.   The test surface on this one is quite massive (even with the blessing called Hyper-V) but I do have an idea that makes sense to me:

Create an InstallShield 2010LE  Template

The bootstrapper in InstallShield is quite capable of doing all this work. Also it's free with Visual Studio 2010.  This gives it a HUGE leg up on Windows Installer XML.   Also IS 2010 LE is capable of calling EXE CustomActions which is exactly the hack I used to solve my Office 2010 x64 edge case.  I just created an AnyCPU .NET EXE that checks to see if it's running in a 64bit process space and if so, register the AddIn in the 64bit hive.  Same for uninstall.   Evil, I know, but it works.

The other thought that I have is to wrap this all up into a "prereqs only" setup.exe that goes through this process and then quits when it gets to the MSI.    From there you really could do this as a simple and easy ClickOnce installer on a per-user basis with autoupdating from a website of the AddIn.  Unless of course your AddIn was part of a much bigger product.

I'll try to revise this post from time to time. Until then, please leave a comment if you need any clarification or corrections.

4 comments:

plewi-blogsberg said...

Hi

thank you for this great article. I run into the same problems and for me it's really difficult to generate a generic installer for 32/64 bit systems and office 2007/2010 solutions. Can you provide some demo project to your article?

greetings Stefan

Anonymous said...

Why You create so complicated condition like "MSO12DLLFOUND or (MSO12DLLFOUND and GOODMSO12DLLFOUND)"?

You can check if file exist and at the same time version of this file using "Add File Lunch condition" where you can select minVersion. Or I miss something?

Christopher Painter said...

I needed to be able to detect if a DLL within a certain version number range was installed.

Сергей said...

Thanks for the great article! I am fighting with VSTO add-in installation problems for a long time...
How you tweaked InstallShield VSTO prereq to install on any platform? You mean this exe custom action?
Does click once installation have same issues?