Welcome to MSDN Blogs Sign in | Join | Help

Component Rules 101

I've been debating with myself for the last week wether I really wanted to write this blog entry about the Component Rules. The Windows Installer SDK has some decent documentation about what can go wrong when the rules are broken. But right when I had just about decided to write about something more pleasant, on the walk back from lunch yesterday, Robert suggested that I write this entry anyway to put a more emphasis on this topic that has easily sucked up months of my life. Then today there was yet another email thread at work that demonstrated people still don't understand the Component Rules. So, on the drive home tonight when I heard that C89.5 was going to play the entirety of Basement Jaxx's new album Kish Kash, I decided I would sit down and write the blog entry about the Component Rules. So here we are and here we go.

In a previous blog entry I talked about the basics of Windows Installer Components. If you haven't read that entry you should do so before continuing on here. Done? Great, let's continue.

At the end of that previous blog entry, I hinted at a flaw in the way the Windows Installer reference counted Components and the Resources contained in them. Rather than give the answer right away, I'll start building up an example then walk through the problem step by step and we'll see how quickly you can jump to the conclusion.

Note, I'm going to pretend to use a bit of set notation here but I can't find my discrete mathematics book right now so I apologize now if I butcher the syntax.

First, remember that every Component in the Windows Installer has a Globally Unique Identifier (GUID) that I called the ComponentId. Also remember that the Windows Installer tracks (reference counts) Components only by their ComponentIds. I like examples so let's say we have three Components with their ComponentIds like:

 C1 - ComponentId = "{0F794AC3-F266-4238-BC59-4AD641DD5F8F}"
C2 - ComponentId = "{5B2390D5-C8D0-43b0-980F-01A872E809C4}"
C3 - ComponentId = "{0F794AC3-F266-4238-BC59-4AD641DD5F8F}"

Now to us, it looks like there are three Components listed. However, the Windows Installer would only see two Components because C1 and C3 have the same ComponentId (trust me, I cut'n'pasted them). Okay, so now, let's say I also have three Resources:

 R1 is a Registry Key = "HKLM\Software\Microsoft\Wix\Data=example.wxs"
R2 is a Registry Key = "HKLM\Software\Microsoft\Wix\Version=2.0.0.0"
R3 is a File = "[ProgramFilesFolder]\Wix\candle.exe"

I probably only need two Resources for the example, but electrons are cheap. Anyway, the actual types of Resources listed above don't matter. I just wanted to make the example a little more concrete since I know I don't like it when people start hand waving at abstract concepts.

Now, that we have some Components and Resources, let's run through some simple logical statements. For the rest of this entry, the symbol "==" means "is equivalent to" and the symbol "!=" means "is not equivalent to". Okay? Okay.

 C1 == C1
C1 != C2
C1 == C3
C3 == C1
R1 == R1
R1 != R2
R1 != R3
C1 != R1 (and some people would argue this is a nonsensical thing to do anyway
since Resources aren't Components to begin with and discussing their
equivalency is pointless!)

All I'm trying to show is that the Components with the same ComponentId are identical and the Resources provided are all unique. Now that we have some building blocks for a setup, let's put them together for our first scenario

 C1 = { R1 }
C2 = { R2, R3 }
C3 = { R1 }

What I've tried to represent in set notation is that Component 1 contains Resource 1, Component 2 contains Resources 2 and 3, and Component 3 contains Resource 1. Nothing magical here. Again, if we do the equivalency tests on the contents Components the following should all still be true:

 C1 == C1
C1 != C2
C1 == C3
C3 == C1

But enough truth statements, I'm here to talk about installation. So let's pretend that we had the Windows Installer install each of those three Components on a "clean machine" (a machine that has never had these Components installed before). We're talking about reference counts a lot in this blog entry, so let's take a look at the reference counts on the ComponentIds and Resources after the installation is complete:

[ten after midnight and the DJ has started playing Basement Jaxx, sweet...]

 {0F794AC3-F266-4238-BC59-4AD641DD5F8F} - 2 (C1 and C3)
{5B2390D5-C8D0-43b0-980F-01A872E809C4} - 1 (C2)
R1 - 2
R2 - 1
R3 - 1

What does this mean? Let me try to represent the lines above in English. "The ComponentId {0F794AC3-F266-4238-BC59-4AD641DD5F8F} has been installed on the machine twice, once by Component 1 and again by Component 3. The Component 2 with its GUID has been installed on the machine once. The Windows Installer only reference counts Components but if we were to apply the reference counts from the Components to their contained Resources we'd notice that Resource 1 has a reference count of two while all the other Resources have a single reference count."

Now let's say we were to uninstall Component 1 and Component 2. The resulting reference counts would look like this:

 {0F794AC3-F266-4238-BC59-4AD641DD5F8F} - 1 (C3)
R1 - 1

Notice that Component 2 and its Resources are gone. That's because their reference count reached zero and were thus removed from the machine. Component 1 was emoved so the count on the ComponentId it shared with Component 3 was reduced by one but did not hit zero so the Component is still there. If we remove Component 3 now then all of our Resources would be removed from the machine.

So far so good, so let's move on and introduce a new scenario with just Components 1 and 2 like thus:

 C1 = { R1 }
C2 = { R1 }

Now, Resource 1 is installed by two different Components.So if we go back to our clean machine and install each of these Components the resulting reference count on the Components and Resources would look like this:

 {0F794AC3-F266-4238-BC59-4AD641DD5F8F} - 1 (C1)
{5B2390D5-C8D0-43b0-980F-01A872E809C4} - 1 (C2)
R1 - 1

See the problem? No, that's not a typo. Let's try it in English, "The ComponentId {0F794AC3-F266-4238-BC59-4AD641DD5F8F} has been installed once by Component 1 and the ComponentId {5B2390D5-C8D0-43b0-980F-01A872E809C4} has been installed once by Component 2. The Windows Installer only reference counts Components but if we were to apply the reference counts from the Components to their contained Resources we'd notice that Resource 1 gets a count of one from two different Components. Unfortunately, that isn't additive so the Resource 1 ends up with a reference count of one."

So what happens when you uninstall Component 1 (or Component 2, it doesn't matter)? Yep, you guessed it:

 {5B2390D5-C8D0-43b0-980F-01A872E809C4} - 1 (C2) 

Resource 1 has been removed prematurely from the machine. Yes, this is wrong. Yes, this is the way the Windows Installer really works. Yes, there are variations on the scenario that result in Resources being "orphaned" (left behind) after uninstall and Resources not being installed on the machine when a Component tries to install them.

The thing I find interesting is that if you take the first logical statement about the Windows Installer's view of equivalency between Component 1 and Component 2 and compare that to the mathematical equivalency of the sets that represent Component 1 and Component 2 in the last scenario you get this:

 C1 != C2 where "{0F794AC3-F266-4238-BC59-4AD641DD5F8F}" != "{5B2390D5-C8D0-43b0-980F-01A872E809C4}"
C1 == C2 where { R1 } == { R1 }

While not quite as profound as Russell's Paradox, if you're using the Windows Installer this design flaw is something you should definitely be aware of when putting Resources in Components. Hopefully, it also demonstrates that you should never put someone else's Resources in one of your Components.

C89.5 has finished playing the new Basement Jaxx CD and I have a flag football game in 8 hours (we have the early game this weekend) so I'm going to wrap this blog entry up here. If people want, I can drill into more detail about the Component Rules in future blog entries. However, I think we have enough information here to understand the problem and provide justification for Merge Modules thus unlocking new branches in my thought tree.

Until next time.

Published Saturday, October 18, 2003 4:28 AM by robmen
Filed under:

Comments

# RE: Component Rules 101

Tuesday, November 04, 2003 11:59 PM by Robert
Many man month have been lost to the figuring out a) an app did or did not need to break the component rules and b) there is no easy way to message the consequences. Darwin's guidance in the SDK is better than it was however in the majority of cases its so easy to break the rules and ship before the rule violations are recognized. After shipping, the best you can do is yes we sure shot the user on that one, let's try not to do that again. The problem boils down to the rigidity of a darwin component is inversly proportional to the transparancy of what should be in a component. Should a component contain a single file and it's registration? that's naieve (please pardon the spelling) best case but it does not allow for the evolution of the file and it's registration. Version to version files sets morph into different file sets as the engineering evolves. As a component fragments or grows, how does one continue to share appropriately? There are other complexities to picking a component composition. For instance, what if none of the files in a component have a version and there is no registration? This is a messy one because there is no single behavior that works perfectly for all cases. Another case is the tiny files of content things like MSDN and data centers proliferate. For these scenarios, you'd really like to strip the majority of the integrity systems out of Darwin as integrity checking ends up surpassing the value it provides (in the aggrigate). Another fun case is where there are dependent references between components. (ready for a juicy new thread Rob?) one of the things Darwin failed to get was adequate representation of dependencies. Knowing ones dependencies so that ont can articulate them and validate they are fulfilled is an essential part of engineering. Darwin missed this entirely but to their defense no one else in the Darwin era really groc-ed the importance of articulating and validating dependencies either. The problems with componets are vast and deep as well as subtile and sophisticated. Rob groc this uniquely, in my experiance. It sure is fun to watch Rob come in to a room of 20 people utterly confused about the state of their world and have Rob summarize their mistakes and the available solutions in less time than it took to complete the introductions. Good thing for Microsoft that Rob is generous in spirit and committed to making all of Microsoft a better place.

# RE: Component Rules 101

Friday, November 07, 2003 9:51 AM by David
One component topic I would be interested in is validation. There is an issue in the repackaging industry at the moment with ICE 33 errors. What is your view and experience of ICE 33. Is it possible to solve all ICE 33 errors?

# RE: Component Rules 101

Saturday, November 08, 2003 3:01 AM by robert
Office does not run ICE33... I'd call that a vote of no confidence... ...and generally repackagers are bad news... Repacagers can't know enough about a product to make the right componetization calls.

# Inside the MSI file format, again.

Tuesday, February 10, 2004 4:01 AM by when setup isn't just xcopy
Another tour of the MSI file format.

# re: Windows Installer XML (WiX) toolset has released as Open Source on SourceForge.net

Tuesday, April 06, 2004 8:27 PM by when setup isn't just xcopy

# re: Registering an Assembly for COM Interop in a MSI file with the Windows Installer XML toolset.

Friday, April 30, 2004 1:29 AM by when setup isn't just xcopy

# re: Component Rules 101

Monday, May 03, 2004 8:37 PM by Naren

Component management pitfalls pointed out here have dogged our company's installer efforts from the start. We even believe MSMs were the way to share "components" (non-msi definition).

But we have learnt our lesson, we don't let MSI manage our shared pieces. We make separate MSIs for each and we manage the dependencies ourselves. WE can now make MSIs with gleeful abandon of component rules. Mind you we don't, but if we break a component rule here or there, we don't end up in a soup.

# Excellent MSI component tutorial

Saturday, May 08, 2004 1:16 AM by Aaron Stebner's WebLog

# Welcome, Aaron!

Saturday, May 08, 2004 2:03 AM by the1's WebLog

# O'Reilly Net on Getting Started with WiX.

Friday, May 14, 2004 2:57 AM by when setup isn't just xcopy
Imagine a blog entry where I discuss a couple issues in an introduction article to the WiX toolset I found online.

# re: My philsophical musings about building setup for software.

Monday, May 17, 2004 12:22 PM by when setup isn't just xcopy

# Excellent MSI component tutorial

Wednesday, May 19, 2004 12:13 PM by Aaron Stebner's WebLog

# re: Component Rules 101

Wednesday, May 26, 2004 10:36 PM by Dan
Um, maybe everyobody else knows the answer, but I've got what seems to me like an obvious question:

Why doesn't Microsoft fix this design flaw?

# re: Component Rules 101

Thursday, May 27, 2004 6:56 AM by Rob Mensching
Dan,

How do you "fix" something that is fundamental to the architecture of the system that hundreds to thousands of applications have come to depend on for their installation? You can't just completely change the rules and expect those applications to keep installing. And you certainly can't just break all those applications.

Instead, you find yourself in a very difficult situation. Trust me, if it was easy, they would have fixed this a long time ago.

# Well, not 'fix', but 'extend'

Saturday, May 29, 2004 12:17 AM by Dan
Well, you're right--can't just go ripping the carpet out from under everybody.

However, they _could_ come up with something new, something very similar to the original (probably forked off v1) (not like win32 and .NET), but that had the correct mechanism. It uses a separate database or registry or whatever so you can use the two versions side by side (SxS!). They maintain both versions (like win32 and .NET); v1 is frozen, and left around for whoever wants/needs to use it, and everybody doing new work uses v2.

Perhaps the problem isn't causing people enough headaches for them to justify the cost (monetary and otherwise) to do this, but I think it's reasonably possible to do. (Although, why do you think people roll their own install? They must think that what's available isn't cutting it...) Just my $0.02.

# What I would do if I didn't continue to

Saturday, June 26, 2004 2:11 AM by when setup isn't just xcopy
Imagine a blog entry where I ramble along after having my wisdom teeth pulled and come up with something of a vision statement.

# Creating localized MSI files using WiX toolset and .wxl files.

Tuesday, November 30, 2004 3:31 AM by when setup isn't just xcopy
Imagine a blog entry where I discuss the WiX toolset localization features and .wxl files in detail.

# Learning WiX: Part One

Wednesday, February 09, 2005 3:29 PM by Ryan Lowe's Blog
Learning WiX is not just about learning the WiX toolset. It appears that in order to use the toolset properly you need to know quite a bit of background of setup on Microsoft Windows in general including the structure of...

# Learning WiX: Part Two

Friday, February 11, 2005 12:33 PM by Ryan Lowe's Blog
After more learning I think I need to backtrack even further with the WiX toolset and Windows Installer SDK. There are some fundamental decisions my team needs to make about how the product installation will work and it's something that...

# Component rules vs. file versions

Saturday, April 09, 2005 3:38 PM by Hackward and Foreword

# Using MsiInv to gather information about what is installed on a computer

Friday, July 01, 2005 9:11 PM by Aaron Stebner's WebLog
As I was reading one of the posts on Quan To's new blog, I noticed that someone posted a link to a tool...

# Creating localized MSI files using WiX toolset and .wxl files.

Tuesday, July 12, 2005 1:51 PM by when setup isn't just xcopy
Imagine a blog entry where I discuss the WiX toolset localization features and .wxl files in detail.

# How Windows Installer handles file replacement logic for versioned and unversioned files

Wednesday, August 31, 2005 12:29 AM by Aaron Stebner's WebLog
I ran into an interesting problem yesterday where a team had built an MSI-based setup package, and they...

# How Windows Installer handles file replacement logic for versioned and unversioned files

Wednesday, September 07, 2005 1:20 AM by Aaron Stebner's WebLog
I ran into an interesting problem yesterday where a team had built an MSI-based setup package, and they...

# re: Component Rules 101

Wednesday, March 22, 2006 11:38 AM by Christopher Painter
How does this effect merge module retargeting? If you have a MM that has a component which allows retargeting, aren't you effectively doing the same thing of having 2 components with different resources ( dir1\f1 and dir2\f1 ) associated to the same c1 guid?

# re: Component Rules 101

Friday, September 08, 2006 3:09 PM by Blog Police
Christopher Painter is a blog hog

# Building setup packages for Visual Studio project templates and starter kits

Sunday, October 01, 2006 9:00 PM by Aaron Stebner's WebLog
This article describes how to create an MSI-based setup package to install project templates, item...

# Using MsiInv to gather information about what is installed on a computer

Tuesday, December 05, 2006 4:22 PM by Aaron Stebner's WebLog

As I was reading one of the posts on Quan To's new blog , I noticed that someone posted a link to a tool

# Building an MSI using WiX v3.0 that includes the VC 8.0 runtime merge modules

Tuesday, February 13, 2007 8:54 PM by Aaron Stebner's WebLog

I was recently asked a question by a customer who was building an MSI using WiX v3.0 and the Votive add-in

# Example WiX-based setup that adds a custom strip to the Windows Vista Media Center start menu

Wednesday, July 25, 2007 5:59 PM by Aaron Stebner's WebLog

In the past, I've posted examples (such as this and this ) demonstrating how to create installers for

# WiX: The Pain of WiX (Part 2 of 3)

Friday, October 19, 2007 6:15 PM by John Robbins' Blog

In the first part of this series I gave an introduction to WiX . In this second installment of this three

# foxpro.catalyst ?? » Blog Archive » NF . random quickie blobs

New Comments to this post are disabled
 
Page view tracker