ISWIX, LLC View Christopher Painter's profile on LinkedIn profile for Christopher Painter at Stack Overflow, Q&A for professional and enthusiast programmers

December 16, 2010

Thoughts on using C# in Build Automation

As I mentioned in my last blog post, Cary Roys has posted a blog article titled Getting Started with InstallShield Automation and C# over at InstallShield. It's a good read that raises a couple thoughts for me. I've already covered my first thought so this blog post will address my second thought.

Cary's sample starts with ( abbreviated ):


static void Main(string[] args)
{
    ISWiAuto17.ISWiProject m_ISWiProj = new ISWiAuto17.ISWiProject();
}

Now I'm sure that Cary wrote this to keep things quick and simple but I wanted to use it as an opportunity to share some thoughts on build automation using C#.

In case you've never used NAnt or MSBuild ( they are very similar so everything I write about MSBuild will mostly apply to NAnt ) I'll start by saying that just as MSI shuns imperative programming in favor of declarative programming for installs,  NAnt and MSBuild do the same for build automation.   And just as MSI provides a mechanism for calling custom actions, so does MSBuild.

So, IMO, it's kind of hard to talk about using C# to write build automation without also talking about either MSBuild or NAnt. That said, you typically won't call custom EXE's using the Exec Task  for many of the same reasons why you wouldn't call an EXE from an installer except for a low risk or last resort situation.   Instead you'll write a custom MSBuild Task.

Let's look at a simple example:


using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Example
{
    public class ExampleMSBuildTask : Task 
    {
        public string Configuration { protected get; set; }
        public override bool Execute()
        {
        }
    }
}

This will create a DLL that exports a task called ExampleMSBuildTask. Now let's see how we actually wire it into our MSBuild targets file. ( Think Binary, CustomAction and Sequence tables in MSI )



<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask AssemblyFile="Example.exe" TaskName="ExampleMSBuildTask"/>
  <Target Name="Build">
    <ExampleMSBuildTask Configuration="Debug|Release"/>
  </Target>
</Project>

In this example we have an MSBuild file that has a default target of Build which in turn calls our task. However, I've found that debugging the task isn't really straight forward. What I like to do is create a "test harness". This is just a fancy way of saying move my custom code into it's own class and consume it from both a Windows Application and an MSBuild task.

First I create a simple base class to inherit from:


using System;

namespace Example
{
    class EngineBase
    {
        public delegate void LogHandler(string message);
        public event LogHandler Logger;

        virtual protected void Log(string message)
        {
            if (Logger != null)
                Logger(message);
        }

    }
}

Now let's create a class that inherits from this base class:


using System;

namespace Example
{
    class SampleEngine : EngineBase
    {

        public void Build(string Configuration)
        {
            Log(string.Format("Building {0}", Configuration));
        }


    }
}

The Build method can now easily call the logging message which will in turn call it's delegate it it exists. This basically allows the consuming class to be able to subscribe to logging messages and display it to the user in a way that's appropriate. Let's look at an example:


using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Example
{
    public class ExampleMSBuildTask : Task 
    {

        public string Configuration { protected get; set; }

        public override bool Execute()
        {
            SampleEngine engine = new SampleEngine();
            engine.Logger += Logger;
            engine.Build( Configuration );
            return true;
        }

        void Logger(string Message)
        {
            Console.WriteLine(Message);
        }

    }
}

The task now constructs the engine, assigns it's delegate and calls the Build member. Any messages get routed to the Console as StdOut.

Now let's look at another example:


using System;
using System.Windows.Forms;

namespace Example
{
    public partial class FormTestHarness : Form
    {
        public FormTestHarness()
        {
            InitializeComponent();
        }

        private void buttonExecute_Click(object sender, EventArgs e)
        {
            var engine = new SampleEngine();
            engine.Logger += Logger;
            engine.Build( textBoxInput1.Text );
        }

        void Logger(string Message)
        {
            richTextBox1.Text = richTextBox1.Text + Message + "\r\n";
        }

    }


}

Basically we have the same code only now it's adding it to a RichTextBox on a Windows Forms. Now we have a program that we can easily run, observe and step into with a debugger without jumping through a lot of hoops. This allows you to establish your contract ( inputs and outputs ) up front, get that wired into the build automation and then do most of your development on your own box then check it all in when you are done. It also allows you to convert your logic to an EXE or NAnt task if you need to.

All in all, it's a good way to roll IMO.

December 14, 2010

InstallShield Automation Interop with .NET / C#

Cary Roys has posted a blog article titled Getting Started with InstallShield Automation and C# over at InstallShield.  It's a good read that raises a couple thoughts for me.  This blog post will address the first issue.

When you add a COM reference to InstallShield, Visual Studio will generate interop libraries specific to the version that you added.  This allows you to call into the automation interface with code like:

ISWiAuto17.ISWiProject project =  new ISWiAuto17.ISWiProject();

The problem with that though is the ISWiProject class is now coupled (strongly  typed) to InstallShield 2011. If you need to reuse this code with other versions of InstallShield it simply isn't going to work.

There are several ways around this problem but none of them are pretty:

1) Use reflection for COM late binding.

//Untested Example
object projectType = Type.GetTypeFromProgID("ISWiAuto17.ISWiProject");
project = Activator.CreateInstance(projectType );


This gets ugly real fast with no type safety and a ton of line noise to invoke the members.  If a version of InstallShield doesn't support a member, you'll get a run time error.

2) Switch to C# 4.0 and use the dynamic type.   With this approach you create some initialization code that selects the correct version of InstallShield and assigns the project class to a dynamic class.  This cuts down greatly on the line noise needed to write the code but it's still not type safe and what could be a build time error will be a run time error. Also you might be working in a build automation environment that hasn't yet migrated over to .NET 4.0.

3) Write your own interfaces and then implement provider pass through wrappers for all of the automation calls you'll need to support.  This allows you to create a factory or use dependency injection.  This is a very clean approach that will be type safe but takes a lot of time to write all the tedious plumbing.

4) It's been suggested to me that the the generated runtime callable wrapper could be modified so that the type names are constant. ( Version Neutral / Neutered interop )  but it's above my skill to know how to do this.

5) Hack it!  Write your logic once, clone it to multiple class files and do a search and replace to update all the references.  Then write a factory around it to let you control which one gets used.  Any time you update your code you have to copy it over and search and replace again.   This is a horrible design but it takes a lot less time to implement then option 3 but could possibly take more time to maintain over the long run.   I've done this in the past and got lucky since the code base was pretty mature.

I'd love to see a better solution ( believe me, I've asked ), especially if it came built into InstallShield out of the box.  Anyone have any suggestions?

November 23, 2010

Look, No Hands! Really??

I was just reading an interesting blog post over at InstallShield titled Look, No Hands: InstallShield’s Automation Tools. It's an interesting read so go check it out and come on back.

Ok, now I'd like to share my experience with InstallShield automation.  This no doubt get's me in trouble since people don't like being called out but here goes anyways:


I've done extensive ( e.g. C# Linq to XML NAnt tasks that parse WiX fragments and build up InstallShield projects and working as part of a build team that does over 100,000 automated builds per year) work in this area and the main problems I find are:

1)  The Automation interface is based on COM and isn't very easy to use with C#.  It doesn't feel like the .NET base class libraries, it's clearly something from a decade ago. 

2) The way it's set up, there is no easy way ( short of reflection ) to write code that will work with multiple versions of the automation interface.  You can't just call into a factory and ask for the implementation for any given version of InstallShield.  They show examples in VBScript where you just change the ProgID but any build engineer writing automation in VBScript should be summarily fired.

3) If you spend any amount of time using the automation interface you'll find that it has feature gaps galore.  At this point you are stuck manipulating the XML directly or saving it in Binary format and using an MSI interop to directly update the tables.

4) Another annoyance is that Product Configurations and Release names are case sensitive and that if you pass in an invalid PC/Rel it won't throw an error, it'll just instantiate it for you and then build with incorrect results.

5) I've never been able to get the TFS SCC integration to work correctly.  I always get a C++ ChatterAbstractionLayer error ( or something like that. )  Also, as of the last time I tried, InstallShield doesn't handle more then a handful of ISM/ISPROJ's in a single solution.  In order to have dozens of merge modules build in a single solution I had to author the SLN file by hand and pass it off to msbuild.  Opening it in VS would fail with an error.    This isn't a huge deal to me as I've never really liked the new Visual Studio style UI over the old DevStudio style UI but I think it's worth noting.

Finally, I'd like to say if you read this far you should give yourself a pat on the back for caring about build automation.   My observations from over the years lead me to believe that far to many IS developers users follow very poor practices including the use of magical build machines / desktop builds.   I believe that this is supported by the decision some years ago to remove the SAB from IS Pro and I have hope that since one license of SAB was recently added back into Pro is evidence of a maturing of the user base in adopting formalized processes/automation for building their installer.

November 14, 2010

InstallAware Questionable Announcement

I just received the following email from InstallAware:


----- Original Message ----

From: Erika Lehman <elehman@installaware.com>
To: chrpai@yahoo.com
Sent: Sun, November 14, 2010 3:11:46 PM
Subject: InstallAware 10 First Ship Special - The Only Hybrid Installer

Together with the release of InstallAware 10, we're celebrating Visual Studio Magazine's Reader's Choice Award for InstallAware in the "Installation, Setup, & Deployment Tools" category! Thank you very much for helping make us the number one installer.

...  rest of message snipped ...

Kind regards,
Erika Lehman
Marketing Communications Manager
InstallAware Marketing Corporation
1888 Kalakaua Avenue, Suite C312
Honolulu, HI 96815
808 447 5817
What I find interesting is that they are claiming that they won the "Reader's Choice Award" and that they are the number one installer.

Really? InstallShield is claiming the same thing in a recent press release:

Flexera Software's InstallShield Wins Visual Studio Readers Choice 2010 Award
For Sixth Year in a Row, Gold Standard Installation Development Solution Takes Top Honors in Installation, Setup and Deployment Tools Category
SCHAUMBURG, IL--(Marketwire - November 11, 2010) - Flexera Software, the leading provider of strategic solutions for Application Usage Management for application producers and their customers, today announced that the readers of Visual Studio Magazine have once again selected Flexera Software's InstallShield®, the leading installation authoring solution for the Microsoft® Windows® platform, as the winner of the Visual Studio Readers Choice 2010 Award in the Installation, Setup and Deployment Tools category. This is the sixth year in a row that InstallShield has won this prestigious award, reflecting Flexera Software's ability to sustain the highest levels of functionality, ease of use, and customer satisfaction with the software.

... rest of message snipped ...
So I decided to go to the source to try to understand how two companies could possibly be claiming to win the same award.  Since I don't feel like stepping in the brown stuff today and have someone claim that I am misrepresenting the facts,  I'll just show you what I found and let you draw your own conclusions.



Let's just say that somebody is either not telling the truth or needs to get better at applying the creative use of weasel words. Of course the cynic in me notes that pretty much all of the award categories have 2 "merit award" winners and is aware there are only a few players in this sector in the first place. ( I've also read that VS Mag doesn't include MSFT tools because they want to encourage third party tools development so that explains why WiX won't be on the list. )

November 07, 2010

InstallShield Setup Prereqs Gotcha (BugBug)

I've recently discovered a weird InstallShield 2010 setup.exe behavior while doing some extensive testing for a client's installer.  Basically on a Windows 7 (x64) machine that I knew should need several redists, only one of the redists would show as needing to be installed.  When I ran the setup.exe again all three would show up as needing to be installed.

I did some googling and found out that setup.exe has a /debuglog option that allows you to diagnosis setup.exe problems.  I decided to do this and compare the bad then good logs.  Doing so revealed the following:

Skipping prerequisite 'Microsoft Visual C++ 2010 Redistributable Package (x86).prq' because it was installed before the reboot


Funny, I've never installed this prereq.   I did some googling and found a thread over on InstallShield Community where another user was seeing a similar behavior.

Now the machine I was testing on was a VM snapshot.  And it was only this one snapshot that I could reproduce the problem on.  I started thinking about how this could be and I think I've figured out the scenario that surfaces this design defect.    I had created a build for my customer that had several prereqs and used that to create the snapshot.  My customer then added additional dependencies to the application so I created a new build that added a couple more prereqs and I scheduled them to be run before some of the prexisting prereqs.  In doing so I think I stumbled into a situation where InstallShield keeps some information around and incorrectly figures it's installed something before that it hasn't.

So just be aware, if your doing setup prereq work and using snapshots for performance / productivity purposes while testing edge cases  with setup prereqs that you might come across this problem.   To  be extra safe, always author AppSearch / LaunchConditions to make sure the problem isn't swallowed and resurfaced when you try to run the application.

If anyone would like to help me confirm this bug, please consider trying to do the following:


1) Build setup.exe v1 with prereq A

2) Build setup.exe v2 with prereq A and prereq B.  Sequence prereq B to run before A.

3) Create a VM and create snapshot 1.

4) Run setup.exe v1 on the VM against snapshot 1 to install prereq A.

5) Create snapshot 2

6) Run setup.exe v2 on the vm . You'll see prereq b ommitted from the list and /debuglog shows it's being skipped

7) Run setup.exe v2 again on the vm. You'll see prereq b in the list and skipping emitted from the log.

8) Apply snapshot 1 and run setup.exe v2. You'll see prereq a and b in the list.

9) Apply v2 and repeat steps 6 and 7.  It should be very predictable.

November 05, 2010

InstallShield Media Table Gotcha (BugBug)

It should stand without saying that you should always test your installer using the various ways your customer will install it.   For example, if you are building a CDROM / DVD release don't just mount the network share and navigate to DISK1,  actually burn the folder to media ( or ISO's and mount them ) and use this to test your install.   Doing so would expose the following InstallShield bug that I found using InstallShield 2010.  Perhaps this is fixed in 2011 but I wouldn't know since I don't have it available to me at the moment.

  1. Create a feature called A1.1 and give it some components / files.
  2. Create a Product Configuration / Release of type CDROM, Compressed and tell it to create 1 CAB per feature.
  3. Build and examine the Disk1 folder with windows explorer and ORCA.
What you'll find is a Media table with a DiskId 1 row that has a Cabinet name of A11~1.cab.  That is correct as the Media table only understands short names. ( Yes, I know... this is 2010 AD right? )

Take a look at the Disk1 folder and you'll see a CAB named A1.1.cab.  This is incorrect.

If you drop to a DOS prompt and CD to the Disk1 folder you can do a DIR /X (display short names ) and you'll see   A11~1.CAB for short and A1.1.cab for Long.    However if you burn DISK1 to a CDROM you'll see something different for a short name.  What you see will depend on what type of file system you use but generally it won't be what you expect.  A detailed explanation of all this would take a long time and frankly it doesn't matter to me.    The point is if the media table only understands short names then the cabinet files should match it as short names so you don't have to worry about all of this.

As an aside, another gotcha to watch out for is when you burn a release that has more then 1 disk.  Windows Installer cares about the VolumeLabel in the Media table matching the VolumeLabel on the media.  It doesn't matter that your disk has the right cabinet file name with the right hash,  MSI will keep prompting for the next disk unless this VolumeLabel matches up.   This probably goes back to the 1990's when a 'high speed' CD-ROM was capable of only 300KB/sec.  The problem of course is that in many organizations the group responsible for building installers isn't always the group responsible for media control.   So again, make sure you get a copy of what's actually going to go to the customer and test it before signing off on a release.

November 03, 2010

InstallTalk: Windows 7 Application Compatibility

It looks like after 7 years InstallShield is finally joining the blogosphere.  Maureen Polte kicks off a new blog series called "InstallTalk" with an article dealing with Windows 7 application compatibility. It's an interesting article that addresses "what a software installation developer can do to help".  
Here's a quick list of the pain areas she lists:

  1. Legacy Help Files
  2. Windows Resource File and Registry Issues
  3. UAC File Header Issues
  4. Custom Action Security Issues
  5. Legacy Control Panel Applet Security Issues
 What I find interesting is that 3 of the 5 issues aren't really installer problems, they are development problems.  Over the last 15 years I've served in a variety of roles including Tier-4 Enterprise Engineering, Application Development, Build Engineering and Installation Engineering.   I've seen the industry from a variety of angles with a number of companies and in general I'd say that Maureen is correct in pointing out that operations folks often encounter pain caused by ISV's.   But I don't point the finger at install developers.  The problem comes when development organizations do a poor job of understanding the platform they are developing for and fail to take integration concerns into account from the moment they create their designs.  Of course the highly complex nature of the Windows platform and related technology stacks doesn't help any of this.

One of these days this message will get back to developers.  Until then I'll keep making the best possible installs and offering practical integration tips wherever I can.

October 28, 2010

Fact Check: Microsoft Office 2007 (setup) was developed entirely with WiX

I recently noticed the following tweet:

The quote comes from the WiX Tutorial at Tramontana:

You might wonder if WiX is already mature enough for the installation of large, complex applications with a large number of files to be deployed. Well, Microsoft itself is switching to WiX with all its major software packages. Just as an example, the setup of Microsoft Office 2007 was developed entirely with WiX.

That is a great testimonial to the maturity of WiX.  The only problem is that it isn't true.   Consider the following dialog:


This dialog is not created by WiX.  It's created by an internally developed bootstrapper that provides a multilingual external user interface.   Sure, the installers are mostly WiX underneath the covers ( I see some custom actions in there ) but the majority of the user experience has nothing to do with WiX.  Additionally the Office 2007 consists of many smaller MSI's that are chained together.   WiX simply does not yet support this story.

Sure, the WiX team is currently been working on Burn but it isn't done and the claim isn't true.   Why is this important?   Because I want everyone to remember, Don't Believe Everything You Read.   I like WiX but let's keep it real and not get blinded by enthusiasm.

October 18, 2010

New Book/eBook Available: WiX: A Developer's Guide to Windows Installer XML

Nick Ramirez announced today the availability of a new book focusing on Windows Installer XML authoring.  I can't say I've read it yet ( other then skimming the first chapter that's available online for free. ) but I'm going to go out on a limb and say everyone should go ahead and buy it.  To put my money where my mouth is, I just ordered it myself.

I don't know if I'm doing Nick any favors or not but here's the way I see it.   Let's be honest, how often do we see a new book on installers?   Once every 5 - 10 years is my guess.    Leslie Easter and Phil Wilson's books were fine but they are very, very old.   So just on that alone I give Nick's new book a buy rating.

Seriously, apx $50 ($10 if you are into eBooks ) is chump change when it comes to investing in training.  So either break out your credit card right now or go on down to your boss and ask him to sign off on it and let's show Nick that his work is appreciated.

Then feel free to come back here and post your reviews of the book as comments.

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.

October 05, 2010

Changing Course

I received some news today that came a bit quicker then I was expecting.   Effective tomorrow, I'm going to to ( mostly ) take a break from install lead responsibilities and go work as a .NET developer in one of my company's business areas.  I'm really anxious to attack this new challenge and grow application development skills.  As such,  I'm going to be taking a break from the installer community. I'll continue to work on IsWiX and I owe at least one more blog post on deploying VSTO AddIns.

Wish me luck!

September 30, 2010

Troubleshooting IIS Problems on Vista SP1

Rod Maupin recently  blogged 'Installations for IIS on Vista Require SP2' :

If you are developing an installation that will install to Internet Information Services 6.0 on Windows Vista, be aware that you must have Service Pack 2. If you don’t, the installation will probably fail in the middle, and roll back any changes that have been made.
Rod's post is light on details and didn't really say why it would (probably) fail so I thought I'd post my observations and experiences on this subject.  I have successfully created Web Installers for Vista SP1 but there are certainly a few gotchas to watch out for:

1)  Make sure you are using an authoring tool with properly behaving IIS Custom Actions.  I highly recommend InstallShield 2010 SP1.  I'm currently withholding judgement on InstallShield 2011 until it's been in the wild for awhile and has it's own SP1.   You need custom actions that can properly handle the various versions of IIS without requiring backwards metabase compatibility shims.  ( Yup, I'm looking at you WiX. )

2) Make sure your web.config is not marked as read-only when you build your installer.  MSI will deploy the file with the read-only attribute set and IIS really, really doesn't like this.

3) Make sure your web.config doesn't have xml namespaces declared.  The IIS API will throw and exception which will bubble back up as a Custom Action error.  In my case it was a namespace declaration added to the web.config when the developer added an Nlog reference.  Once we removed the namespace the installer started working.

Also there's a good read over at the InstallShield community forum:

Vista Enterprise Service Pack 1 IIS 7.0 install problems using Installshield 2010

 If you still have problems or have seen another edge case, please feel free to document it with a comment below.

September 29, 2010

The Worst Installer I've Ever Seen

I'm going to have to pass on naming the guilty party but recently I received an installer that I needed to add as a prereq to my bootstrapper / chainer.  I started to look at it and here's what I found

1) It's 300+ MB InstallAnywhere installer that presents itself on Windows as a command line installer.  You have to press enter 26 times to page through the EULA and then  type Y to accept it.  Press enter to accept the default installation directory and then watch a progress bar that looks something like:

===============================
Installing...
-----------
[=========|=========|==========|==========|===========]
[-------------|--------------|------------  <- the part that moves

Oh my God, and I though WiX was bad.   This one tops it for me.   Hello!  The 1980's called and they want their INSTALL.EXE back.

Here's where it gets worse though.  This InstallAnywhere is just a wrapper for an MSI installer that it extracts out, calls to and then deletes when it's done.  (  Certainly hiding the installer source is far more important then making it available for repair operations ).

I did some googling ( I have to admit, I haven't ever written an InstallAnywhere package.  The few tarballs I wrote in the 1990's were enough for me. ) and I found the command line switches for UI, Console and Silent.  Guess what?   Yup.  UI and Silent were both intentionally disabled in this installer. 

Finally, the documentation that comes with this installer specifically states "Do Not Use Add/Remove Programs" to uninstall the application.

Wow.  I didn't know to laugh or cry.

September 24, 2010

InstallSite: Microsoft will retire Visual Studio Installer

According to Windows Installer MVP Stefan Krueger of InstallSite:

Retirement of Visual Studio Installer Projects from future versions of Visual Studio



Candy Chiang MSFT Thursday, July 15, 2010 8:07 PM

In Visual Studio 2010, we have partnered with Flexera, makers of InstallShield, to create InstallShield Limited Edition 2010 just for Visual Studio 2010 customers. The InstallShield Limited Edition 2010 offers comparable functionality to the Visual Studio Installer projects. In addition, you can build your deployment projects using Team Foundation Server and MSBuild. For more information, see http://blogs.msdn.com/b/deployment_technologies/archive/2010/04/20/installshield-limited-edition-is-available-for-download-in-visual-studio-2010.aspx.

With InstallShield available, the Visual Studio Installer project types will not be available in future versions of Visual Studio. To preserve existing customer investments in Visual Studio Installer projects, Microsoft will continue to support the Visual Studio Installer projects feature that shipped with Visual Studio 2010 and below as per our product life-cycle strategy. For more information, see Expanded Microsoft Support Lifecycle Policy for Business & Development Products.

All I can say is:  About Time!

Visual Studio Deployment Projects were horrible and contributed to a great many anti patterns including the extensive and inappropriate use of fragile Installer class custom actions.  I can only hope that InstallUtil is next on the chopping block.

That said, InstallShield 2010LE alone will not fill the void 100% so I hope Microsoft also makes good on getting WiX into a future version of Visual Studio.  Until then, if one is clever, there are ways of making WiX merge modules and merging them into InstallShield 2010LE projects to get IS to do things it wasn't designed to do while following MSI best practices at the same time.

September 18, 2010

Office 2010 Bitness Pain

Recently I've been doing some work for a customer who needs an installer for a Office 2007/2010 VSTO 2010 AddIn.  While authoring the actual installer isn't that difficult thanks to the awesome bootstrapper in InstallShield 20xx, the real fun has been on the integration and testing side. 

Making sure this your product and installer will work on Windows XP SP2/SP3 x86 / x64,  Vista x86 / x64 and Windows 7 x86 / x64 in conjunction with Office 2007 and Office 2010 can really take quite a bit of time even with the help of Hyper-V snapshots to make sure that you aren't missing any edge cases.   You have prereqs with prereqs such as VSTO -> .NET 4.0 -> Windows Imaging Components -> MSI 3.1 in the case of Windows XP SP2.  Microsoft doesn't keep it simple but thankfully InstallShield does a good job trying to keep up.

 Somethings have improved as Office 2010 once again behaves like Office 2003 in allowing you to register AddIns in HKEY_LOCAL_MACHINE  (  the hell that is Office 2007 is fodder for another blog post ) but Office 2010 adds a whole new wrinkle that makes me want to pull my hair out:  Bitness Pain

Let's start with the easy bitness pain:   VSTOR40_x86.exe vs VSTOR40_x64.exe.   The VSTO AddIn has a run time dependency that's tied to the platform of Windows that you are running on.   Still, since the setup.exe bootstrapper is handling VSTOR for me, this is a pretty easy problem to solve.

Now for the harder pain:   Your AnyCPU VSTO AddIn has to be registered in HKEY_LOCAL_MACHINE but which hive?    The 64bit or the 32bit?

If you picked 64bit  you are probably wrong.  If you said "use registry reflection you re probably wrong also since this was removed from Windows 7 and considering how much of a flop Vista was your user is probably running Windows 7.

See, it doesn't matter that you are running 64bit Windows, it matters if you are running 64bit Office!  Now for the kicker,   Microsoft has a complicated work flow for recommending if a user should install the x86 Office or the x64 Office.     It basically boils down to  Developers and Hard Core Excel Junkies with spreadsheets larger then 2GB should run x64 and the rest of the world should run x86. In fact, if you stick the disk in and run the setup.exe from the root you are very likely to get x86 Office 2010.



So now you have this AnyCPU AddIn packaged up in MSI which doesn't officially support hybrid installs which means you have to have 2 downloads and hope your user is smart enough to know which one to download.  Or you have to make 2 MSI's and wrap it with a bootstrapper .... something that InstallShield can't do at the moment.

Hmmm... what to do, what to do?  I guess I could just punt and only support x86 Office.  After all the vast vast majority of users will be using it.  But Microsoft really wants to move the community forward and I really don't want to leave my customer taking even 1 support call trying to get their AddIn to work.

So I think I'm going to vote for a Hybrid install on this one.  It's only 4 registry values that I need to write so I'm going to put my nose up in the air at Windows Installer and roll a custom action which fires only on 64 machines to write the values and remove them on uninstall.

If anyone at Microsoft is reading, and I know you are from my http logs,  please, please try to do something to fix this.    This single bitness limitation in MSI is just going to become more and more painful in my opinion.

PS-  I'll probably never get back to the Office 2007 comment so here goes.   2007 only supported registering AddIns in HKEY_CURRENT_USER.  There is a HotFix available along with a registry value to fix this and Microsoft blog articles say 'we fixed it' but here's the catch.   We aren't allowed to redistribute it with our installers.  We have to hope that end users have patched their machines via Microsoft Update.   Well I didnt want my customer to have to get that support call either so I wrote an AppSearch that checks if Office12 MSO.DLL is present that it's atleast a certain version otherwise gate with a LaunchCondition.

September 17, 2010

.NET 4.0 has 2 Global Assembly Cache (GAC)

Please be sure to read the following article and then come back.   I'll pull up a chair and wait for you.

.NET 4.0 has 2 Global Assembly Cache (GAC)

Wow,  I only recently noticed that .NET 4.0 has a "new GAC" ( BTW, wtf? I guess Global doesn't really mean Global? )


But I'm wondering, what does this mean to me as a Setup guy? Does the MSI support this?   To find out I created a CLR 4 Class Library in Visual Studio 2010 and signed it with an SNK.   I dropped it into an InstallShield Basic MSI targetting the GAC like normal and sure enough the file deployed to [WindowsFolder]Microsoft.NET\assembly\GAC_MSIL\ClassLibrary1\v4.0_1.0.0.0_token.

But, is there anything else I need to know here? My head is just spinning from this design decision ( although I seem to be in good company ) and I really want to make sure I understand all of the implications.

September 15, 2010

Read the Windows Installer SDK

I have a story that I'd like to share and I ask everyone to please not take it too seriously / literally.   With that out of the way, here goes.

I was at church the other day and they were doing a presentation of Bibles to third graders.  It was really exciting to see these little kids up there unwrapping their new found treasure. 

At some point there was an oath where the children and later the adults promised to read their Bibles. During this a comment was made by the that you won't always understand what you are reading but that you should keep reading it until one day you do.

One of my responsibilities at work is team professional growth.  I do all kinds of activities to keep everyone plugged in and learning but just like anything if life if you only listen for an hour a week you are never really going to get it.

So at the risk of sacrilege, I want to state:

Read your Windows Installer Bible!

Yes, it's a tough read that doesn't always make sense but read it every day anyways.  Apply it to what you do every day and one day soon those obscure notes sprinkled throughout will make sense.

Whenever I get a really hard problem, I am usually able to solve it really quickly because I took the time to read it over and over.  People sometimes look at me with amazement on how fast I fixed a problem but the truth is anyone who takes the time to learn it inside and out should be able to do it.  It just goes to show me that they haven't been reading their MSI SDK.

Try to make a commitment to yourself.  30 minutes a day for the next month.  You might be surprised what you learn.

September 11, 2010

In Defense of Merge Modules

Neil Sleightholm recently commented:
"Personally I never use merge modules unless I am forced to!"
It's an interesting perspective and I invite Neil to tell more ( as an aside, I'm always interested in guest bloggers on the Deployment Engineering team.  Diversity in Opinion is always a good thing ).  Until then, I wanted to give a few of my thoughts.   

Let's begin by reviewing Windows Installer Tao Rule # 43

Rule 43: Think carefully about Merge Module Patching

Merge modules provide a standard method for delivering Windows Installer components and setup logic just like any redistributable software. For all practical purposes any MSI package can consume a merge module and start using the functionality exposed by the merge module. However, the servicing story of such an MSI package has a huge flaw. Since the setup author who owns the MSI doesn’t own the merge module, they have no way to deliver fixes to issues that are found in the merge module, unless the merge module owner makes them available. On the other hand, the owner of the merge module has no way of delivering the fixes directly to the clients who installed the MSI built after consuming his/her merge module. The bottom-line of the story here is:

•Do not consume merge modules of vendors who do not promise to fix their merge modules promptly when bugs arrive

•Be prepared to handle the heat when bugs are found in your merge module causing issues for others’ products that have consumed your merge module and you get to put out the flame

Merge modules are great to use for distributing authoring and building of your setup. However, if you intend to redistribute an MSM externally, you should review the servicing implications. If you can tightly control the MSM consumers and identify the relevant products, then it’s possible to service them with a single MSP (multi-product targeting). Otherwise the recommendation is to provide your technology as an MSI that must be chained into the setup
Let's begin with a little history lesson. Microsoft used to use Concurrent / Nested Installs and Merge Modules as a deployment option for Microsoft SQL Server Desktop Engine. Then along came some really nasty security vulnerabilities that exposed a glaring problem in servicing these products that were embedded in other products. Network / Systems Administrators simply couldn't patch there production systems easily to eliminate these worms. Then Microsoft started telling developers to not use these technologies and instead use Micro-Packages to deliver them. After awhile, the message mutated into something along the lines of "merge modules are evil".   Then there was the little problem that MSI doesn't actually provide a decent bootstrapper / chainer to put all these packages together and the proliferation of packages has made Add/Remove Programs look like total chaos.  

Now let's go back and re-read Rule #43 with a little emphasis on the parts that I find interesting:

Rule 43: Think carefully about Merge Module Patching

Merge modules provide a standard method for delivering Windows Installer components and setup logic just like any redistributable software. For all practical purposes any MSI package can consume a merge module and start using the functionality exposed by the merge module. However, the servicing story of such an MSI package has a huge flaw. Since the setup author who owns the MSI doesn’t own the merge module, they have no way to deliver fixes to issues that are found in the merge module, unless the merge module owner makes them available. On the other hand, the owner of the merge module has no way of delivering the fixes directly to the clients who installed the MSI built after consuming his/her merge module. The bottom-line of the story here is:

Do not consume merge modules of vendors who do not promise to fix their merge modules promptly when bugs arrive

•Be prepared to handle the heat when bugs are found in your merge module causing issues for others’ products that have consumed your merge module and you get to put out the flame

Merge modules are great to use for distributing authoring and building of your setup. However, if you intend to redistribute an MSM externally, you should review the servicing implications. If you can tightly control the MSM consumers and identify the relevant products, then it’s possible to service them with a single MSP (multi-product targeting). Otherwise the recommendation is to provide your technology as an MSI that must be chained into the setup
OK, so what am I getting at?   Yes, it's true that when I put merge modules in my installs from third parties ( typically Microsoft .. how ironic )  that the quality of my installs go down.   And it's true that Microsoft doesn't promise to provide fixes and updates to these modules and in many instances they don't provide MicroPackages to redistribute either.    So what's my alternative?  Break the component rules and author my own components for another companies  resources?   Yup, this is an ugly problem that's never solved except by not taking dependencies on those components and moving to newer technologies that get more love from third party vendors.  Still, I'm writing the install not the application so I don't typically get to make that call.

However,  I am certain that using merge modules internally  to distribute setup development is a good thing.   Comparable and even better in some situations then using  WiX Fragments / Libraries /  Binary Libraries or InstallShield Developer Installation Manifests.

First, Merge Modules are STANDARD and can be consumed by installers ranging from InstallShield to WiX.   Try consuming an InstallShield DIM in WiX or a WiX Fragment in InstallShield. 

Second, merge modules are atomic collections of components and setup logic.  This is actually fairly similar to WiX Fragments which according to their own documentation are also atomic and immutable.  WiX Binary Libraries and MSI Merge Modules both aim to solve similar problems.

Sure, using Fragments can speed up your build and give you a bit more flexibility ( like including two components in a fragment but Referencing them into two different features ).    However, you can do the same thing with merge modules by creating multiple merge modules with module dependencies to describe component / feature relationships.  With a little bit of creativity, Merge Modules can even be used to encapsulate AppSearches, CustomActions, Dialogs and more.

Over the last five years I've developed an architecture where I use an InstallShield Basic MSI project to describe a feature tree and product configurations to describe which features to consume.  This serves as a fishbone that I then flesh out with dozens to hundreds of merge modules and create dozens of product installers with.   I use Major Upgrades as my servicing strategy and the result is I've never had any problems that were caused by the use of Merge Modules.

In summary, you don't have to have a monolithic InstallShield project for each of the installs you own.  You can split it out and reuse components and logic through merge modules and not increase the fragility of your install.   In fact, you can realize considerable savings by eliminating wasted effort and decreasing the frequency of bugs in your baseline.

Yes, I will admit it:   I use Merge Modules and I'm OK with that.   Still,  I will be working on Fragment support for IsWiX.

September 10, 2010

InstallShield KB Q207265 Critique

I was browsing InstallSite today when I noticed a link to InstallShield KB Q207265:

HOWTO: Implement an InstallScript Custom Action to Detect and Display Message About Whether a Directory Exists

I'm a little suprised by this article for several reasons.  The first reason is that it suggests writing InstallScript custom actions for functionality that already exists in the Windows Installer.   The AppSearch pattern ( InstallShield calls it System Search ) is more then capable of resolving if a directory exists by using the DrLocator table.  Also you can easily create a modal dialog with a text control that displays exists / not exists messages based on the results of the first search.

Finally the article suggests scheduling the custom action in the execute sequence with a condition of  REMOVE <> "ALL" to prevent execution during an uninstall.    However, this means that the message will be displayed during a silent install since the CA is in the execute sequence and there is nothing that takes UILevel into consideration.

Overall I'm really surprised by the lack of quality in this article.  I know InstallShield has some extremely talented and experienced experts such as Robert Dickau  so I'm not sure where this article came from.

August 27, 2010

WiX-Users: Exceeding Version Limits

Sohail Somani recently asked on the WiX-Users List:

I'm currently in the middle (or nearing the end, I hope) of porting an installer from the evil that shall not be named to WiX.


Mostly, it's been pretty easy. However, one thing which is sticking out is the version number. The products being ported use the current year as the major version number and this means strings like "2011.foo.bar".


...Is there a  simpler way to exceed the limits...? 

The tool ( let me guess: InstallShield ) Sohail used to use isn't the evil, it's how it was used that is incorrect. Over my many years of writing installs I've seen this situation happen over and over:

(I'll use one real world example to illustrate how absurd this really can get when you let functionals try to drive the decision without consulting technical resources. Seriously.... don't ask )

Release Manager:  I need the product version to be  DMLSS_V3.00.01.A.01.10
Setup Developer: I am sorry, I can only do x.x.x.x with certain upper and lower bounds for each field.
Release Manager:  That's crazy, the install shouldn't dictate what I choose.  You must make it what I say.

However, certain the release manager is about how things must be done to meet his 'special' business needs ( aren't they always? ), the MSI SDK is quite clear on the definition of the ProductVersion property:

The format of the string is as follows:

major.minor.build
The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255. The third field is called the build version or the update version and has a maximum value of 65,535.
The old tool allowed this violation ( usually without much real life harm, perhaps some problems doing Major Upgrades ) but WiX simply doesn't allow it.  I think that's a good thing because it helps the install developer when he needs to tell management:

Setup Developer: I'm sorry, I can display your custom version scheme on the dialog but I cannot possibly assign it to the ProductVersion.

Instead it looks like Sohail is just looking for a way around MSI to make the release manager happy.  I understand that pressure but personally I never tolerate it.  I suppose that's partly why I change jobs so often.    Still, it can get better as evidenced by the fact that I've been at my current employer for nearly two years now when the last time I worked for them I barely made it past a year.    Push back hard enough and provide sound reasoning and eventually it will improve.

August 24, 2010

IsWiX Stretch Goals

Wilbert van Dolleweerd left a comment on the blog entry IsWiX - Three Great Tastes asking:

We are in the process of migrating away from Installshield to Wix. It is a good tool if you don't mind a bit of commandline work (for the record: I'm a VIM user ;-) 
Would love to see your ideas for IsWix and how you're willing to enhance it. I might even consider contributing to it.

IsWiX is already a very usable tool at my day job as it was designed for our specific needs.  However,  I'd love to grow it into general purpose tool.  With that in mind, here is a short list of stretch goals I have for IsWiX.  I am also very open minded to feedback to see where people would like to see this project go.



User Documentation

I had written a user manual for IsWiX but it used a company confidential template so I left it behind.

Presentation

I'd like to develop a one hour overview of Windows Installer / WiX technologies targeted at traditional developers for use at CodeCamp and DotNet User Group type events. I am somewhat concerned that there might not be much interest in this from developers.

Robust Automation Interface

SDK Documentation and Visual Studio Project Templates to help people write designers and domain objects for Fireworks / IsWiX.

Support for Sharp Develop

Matt Ward was very helpful in coaching me in the use of their XmlEditor control and I know they are WiX fans so I'd like to try to give something back.   Combining SharpDevelop, WiX and IsWiX seems like a no brainer for small companies and developing markets who can't afford Visual Studio / InstallShield.

Improvements to the XML Editor

IsWiX is meant to be used with Votive which already has a decent XML editor.  The XML editor in IsWiX was initially implemented primarily as a  way to preview the changes to the in memory document but it would be nice to mature it to a point of being similar in capabilities of Visual Studio but a lot lighter weight.

VIM Text Editor
OK, this is somewhat a gag feature ( but I'm actually serious here ) but it would be interesting to somehow host VIM in a Winforms control.  Imagine switching from designer mode to editor mode and using all the VIM tricks you are used to and then switching back to designer mode.
Refactor Files and Folders

I need to clean this up to use proper domain objects and allow it to exist in Product's, Fragments or Modules.  It currently only supports Modules since that was the easiest path to supporting our use case.

COM Extraction

Add the ability for the Files and Folders designer to interact with Heat to perform COM harvesting and authoring.  Currently I use a utility that serves as a front end to heat to author the COM snippets and then manually integrate them using the text editor.

Additional Designers

Finish work on Custom Tables Schema Editor and implement Services, Registry and ShortCuts Designers

August 22, 2010

IsWiX - Three Great Tastes

WiX vs InstallShield has long been a Red vs Blue debate. Some people believe that setup source is code and should be edited as such while others are in the camp that it's just a document that should have visual designers to automate the workflow.  Finally there are others who need to also be able to programatically update source files from time to time.
Each of these approaches have pros and cons so with IsWiX I decided to support them all.    After all what's garbage to one developer might be a treasure to another. Let's look at these three great tastes:

Graphical Designers














Many of us live in the land of  Windows and use tools like Visual Studio. We like to be able to point, click, drag and drop and cleanly visualize the results of our labor.  Drag a tree of files from the Source view to the Destination view and let someone else do the work of writing the XML for us.  As they say in Jamaica- No Problem Mon!   You can create really nice UI's with rich client side validation such  a constraint for Module@Platform that provides a list list of  types or maybe preventing a user from adding the same file twice.  Properly designed UI's and Domain Objects can generate code as clean as hand written code only you didn't have to spend all day slaving over the computer to write it.  Detractors will claim that it's a crutch that prevents you from learning what is really happening behind the scenes but the same argument could be made of copy and paste and assuming all is well when it seemed to work.  At the end of the day it's up to the developer to turn on the curiosity gene and really understand the entire technology stack.

Text Editors













Some developers just hate reaching for the mouse.  Give them a command line interface and VI and that's all they need or want.  Interestingly, many of these people work on Windows and DevDiv / Visual Studio @ Microsoft and that in itself is a life mystery that I will never quiet grok.  Personally I think it's some form of super-geek 'I'm smarter then you.' cult philosophy but that's just a theory with no hard evidence. While I'm no stranger to the command line, ( My resume includes CPM, AmigaDOS, MS-DOS and various flavors of Unix ) I just don't enjoy typing large amounts of XML. Still, it's nice to be able to look behind the scenes and read what the visual designer actually did.  It's nice to get the XSD validation ( although not as protecting as client side validation ) and it's nice to be able to make hand tweaks to generated code.  After all, there's always an edge case out there and graphical designers and code generators should never stand in your way of getting the job done.  At the end of the day, you are smarter then the computer.

Automation Interfaces















Finally, there are times ( for whatever reason ) when you just need to be able to inject a little magic into the process.  You shouldn't have to use raw XML DOM's to manipulate the source nor should can you possibly use a graphical designer.  Therefore, anything a graphical designer can do must also be possible programtically through an automation interface.   Additionally, a well thought out automation interface can help create an ecosystem of tools that are currently unimagined.

Summary and Invitation

So that basically sums up the three great tastes of IsWiX.  In thinking this over, it's now clear to me that a best in breed solution should borrow ideas from both WiX ( XSD is wonderful ) and InstallShield ( Designers and Automation Interfaces Rock ).   InstallShield is a wonderful product but I have several major concerns:

1) InstallShield's use of DTD in it's project format is dead to me.  It's barely readable/editable and is a nightmare once you get into branching and merging situations.

2) InstallShield needs to be rewritten.  I can only imagine the hell it must be maintaining 10+ year old C++ code.  It's time for a reboot.  Just as InstallShield embraced Windows Installer over a decade ago, it's time for them to embrace the .NET framework and some form of XSD based document format.  I vote for WiX.

3) In the area of Agile Software Development, InstallShield's build automation story is really good but it falls really short in the area of Distributed Development.  The Collaboration piece simply isn't powerful enough and the pricing model and learning curve of the main IDE just doesn't make it a good tool choice.
3) InstallShield's Automation Interface is lacking in terms of API coverage.  You have to resort to raw manipulation of the underlying tables every time you hit a wall. Additionally using it from .NET is a horrible excercise in COM Interop with no factory pattern or interfaces to allow you to easily switch your code from one version of the API to another.  This beast was made for VBScript ( see #2 ).

4) I was reading about Paternerships vs Dependencies the other day and it made me realize: When pay up to $9500 per seat for InstallShield with maintenance and then do the activation dance, you are dealing with the latter.  You are at their mercy to even use the software with no promises that they will actually fix their bugs or release features that are important to you.   That's probably fine for a lot of shops but I've been increasingly concerned by it.  That's saying a lot since I used to think of this as a parnoia argument.

WiX on the other hand has some clear technology advantages but continues to suffer from severe underfunding and narrow user stories.  I'm convinced they are some very smart people and that most of choices that they have made that I've disagreed with in the past are really just a result of the realities of the available resources.

It's with this in mind that I've decided to set out on creating IsWiX.

I'm throwing the gauntlet down: 

Who will help me?

PS-  IsWiX is intentionally released under the MS-PL license to enable anyone to take the ball and run with it.  I'm under no illusions of grandeur or wealth - I just hope that my little contribution can somehow spark thought and improve this little domain we call deployment engineering / setup authoring.  Regardless of what happens,  it's been a wonderful opportunity to develop my .NET skills while working in a domain that made sense to me.  No doubt this will help prepare me for the inevitable day that I retire from writing installs.

August 19, 2010

InstallShield Stand Alone Build Error -1131

I was just reading this InstallShield KB article and it really makes me scratch my head.   Basically what it is saying is that the SAB has a dependency on the MS C++ 2005 SP1 Redist but that the SAB installer doesn't actually install it and hence an installer failure becomes a runtime/  failure.

Are you serious?  InstallShield has the best setup bootstrapper / chainer on the market.   Did no one notice they needed to add a C++ redist prereq?   Did they know but just not want to add the 2.3MB to the package?  Did they not know to use an AppSearch/LaunchCondition to gate the install?

But the part that really gets me is:

This unlikely situation is apt to appear on clean Windows/XP or Windows 2003 Server images.

Isn't the point of the SAB to enable *CLEAN* build machines?  If customers are following proper CM practices there should be alot of people with build machines that don't resemble the magical build machine antipattern.  I run my build machines lean and mean and I just looked - no C++ runtime on them.   No Visual Studio either.

Researcher: Code-execution bug affects 200 Windows apps

I just got back from my annual week at the the beach and came across this news:

About 200 Windows applications are vulnerable to remote code-execution attacks that exploit a bug in the way the programs load binary files for the Microsoft operating system, a security researcher said Thursday.
The critical vulnerability, which has already been patched in Apple's iTunes media player for Windows and VMware Tools, will be especially challenging to fix, because each application will ultimately need to receive its own patch, Mitja Kolesk, CEO of application security consultancy Acros Security, told The Register.
This remind me of problems in the past such as the GDI+ problems from years past and other situations where maybe you deployed a DLL privately, via a Merge Module ( that you must service but who knows if the vendor will provide an update ) or perhaps even a statically linked C++ library that has a problem.

Anyways, does anyone know which library is the problem here? I haven't actually found any public disclosure at this level yet but I'll be sure to update this blog if I do.

August 18, 2010

InstallShield 2011 Released

I'm on vacation so I only have enough time for a few quick observations.  InstallShield 2011 has been released and I noticed the following in the press release:

InstallShield 2011: Microsoft’s Installation Solution of Choice for Visual Studio 2010 Applications

It’s no surprise that Microsoft recommends their Visual Studio customers standardize on InstallShield 2011.
Hmmm, now I know that InstallShield 2010LE was introduced as a free download, but has anyone ever read or heard Microsoft formally recommend VS customers standardize on InstallShield 2011?  Maybe I'm not hitting the trade show circuit enough but it sure would be a surprise to me since Microsoft is all over the road in terms of their use of build and install/deployment tools.

Assuming it's true, I wonder how the WiX guys must be feeling considering they were dumped from Rosario and now this.

In other news, I see InstallShield has given a little bit of ground in the Stand Alone Build war.   They are once again including 1 license with Professional which pretty much gets us back to where we were with InstallShield 12. It's about time and I can only say that they *FINALLY* heard their customers.  Additionally, they are also now selling the SAB individually for $500 per seat.   Well, I actually hoped it would be free like MSBuild is but this is progress.   Now here's hoping that they haven't gone off the deep end and introduced DRM activation as that would be a huge ( as in Godzilla ) problem where I work.

I didn't participate in the beta nor have I see the detailed release notes yet so I'm pretty much just skimming the high level notes that can be found here.  There's some interesting things in their but not much that jumps out as 'must have's'  for my particular set of needs.  I'll be back in the office soon and I'll be sure to follow up if I find anything more interesting.

August 16, 2010

WiX Needs an Automation Interface

When I first started writing IsWiX, I intentionally decided to keep it simple and keep the bar low for would be contributors. I decided to expose the in memory document as a raw XDocument to the designer (UI).  This has worked out well but now I'm starting to realize what is really needed.

I've been getting irritated with InstallShield lately because I keep finding gaps in their automation interface.  Now that I'm getting really serious with WiX, I've come to realize that WiX is practically lacking an automation interface. ( The .NET 1.1 CodeDomReader isn't very helpful.) WiX is a pretty decent schema and compiler but the fetish for NotePad++ has left some pretty big holes up the stack.  While I understand my UI designers for WiX aren't for everyone, I'm pretty sure more people would be interested in a decent automation interface.

So I'm going to pause my development on IsWiX until I can come up with a good design that allows me to expose an automation interface for WiX separate from IsWiX and also work with Fireworks through some form of dependency injecting.

I have some technical debt to work off here. I'll get working on the automation interface so that the UI can follow.  Course it would be really cool if the WiX team would write one themselves that way they could influence the authoring decisions made by third party tools.

August 12, 2010

Using Linq to XML to Clean up ISString Tables

I was recently doing some cleanup work on an install that was getting a little long in the tooth and I noticed that it had a lot of pesky orphaned InstallShield String Table entries. Now if you are like me you always want to clean these up but first you need to be able to answer the question: Is this entry being used?

Fortunately with the help of .NET 3.5, C# and LINQ to XML it's a piece of cake to find out. I was recently able to whip up this small little utility in less time then it'll take me to blog about it.



Basically it's a simple layout of all entries, used entries and orphaned entries. Let's look at how easy .NET makes it to figure out which is which:



   1:  private void Process( string documentPath )
   2:  {
   3:    var document = XDocument.Load(documentPath);
   4:    var entries = from row in document.Descendants("row")
   5:                  where row.Parent.Attribute("name").Value == "ISString"
   6:                  select row.Elements().First().Value;
   7:   
   8:    List<string> stringEntries = entries.ToList();
   9:    document.Descendants("table").Where(w => w.Attribute("name").Value == "ISString").Remove();
  10:    string documentText = document.ToString();
  11:   
  12:    foreach (var entry in stringEntries)
  13:    {
  14:      listBoxAll.Items.Add( entry );
  15:      if( documentText.Contains( entry ))
  16:        listBoxUsed.Items.Add( entry );
  17:      else
  18:        listBoxOrphaned.Items.Add(entry);
  19:    }
  20:  }

The process is fairly straight forward. Load the ISM into the DOM; Query a list of ISString entry names; remove the ISString table from the DOM and then finally iterate through the list of names to see if the document contains a reference. It wouldn't take but a few additional lines of code to let you select the entries to remove and automate the rest.

It takes a little time getting used to LINQ to XML but it really rocks once you get the hang of it.

Note: The above example doesn't take into consideration entries that might be used by InstallScript as I don't use InstallScript anymore.