multiple instances of a component - is it really legal??

30 views
Skip to first unread message

John Carver

unread,
Nov 19, 2002, 6:48:22 PM11/19/02
to
I'd like to see clarification of some points here.

1. R. Michael Sanford speaks of shared components. I take that to mean
that multiple products can use the same component and that each
product should use the same instance of the component. But is any
component in a merge module necessarily a shared component? How is
that different from shared files? And what about side-by-side sharing?

2. Mika Kärkkäinen quotes the MSI specs as referring to any component.
"Only a single instance of any component is installed on a user's
computer". This can be shown to be untrue. Two products can be created
that install the same component to two different locations. Installing
and uninstalling these appears to be handled OK by MSI. What
complications can arise? Assume each product uses its own copy of the
component.

3. How does MSI track these things anyway?

On Fri, 9 Aug 2002 13:00:05 -0400, "R. Michael Sanford"
<msanfor...@activeinstall.com> wrote:

>Hi,
>
>This is an Invalid Merge Module. A properly authored Merge Module with a
>Shared Component will not allow the component to be installed to just any
>location. The Merge Module author is responsible for ensuring that their
>shared component cannot be installed to more than one location. In other
>words, the Merge Module MUST be authored in such a way that the component
>ALWAYS installs to the same location.
>
>"Mika Kärkkäinen" <mika.j.k...@fi.abb.com> wrote in message
>news:111701c23fa9$b985c5d0$9ae62ecf@tkmsftngxa02...
>> Hi,
>>
>> Does the MSI allow to install a component into two or more
>> locations on a computer. According to the MSI 2.0 specs,
>> this should not succeed, see the following excerpt:
>>
>> "The installer service installs or removes a component as
>> a single coherent piece. It tracks every component by the
>> respective component ID GUID specified in the ComponentId
>> column of the Component table. Two components that share
>> the same component ID are treated as multiple instances of
>> the same component regardless of their actual content.
>> ***Only a single instance of any component is installed on
>> a user's computer***. Several features or application may
>> therefore share some components."
>>
>> Anyhow, we tested this by means of two individual MSI
>> installs, both including the same MSM which only installs
>> a single file. Opposed to what we expected, both products
>> succeeded in installing the MSM's file into a product
>> specific target directory. We were expecting the second
>> product's install to fail to install and/or complain about
>> the already installed instance of the MSM's file.
>>
>> So, all in all, are we facing some bug(s) in MSI or is the
>> MSI spec incorrect or are we missing something?? Any help
>> GREATLY appreciated ...
>>
>> Rgds,
>> Mika
>>
>
>

R. Michael Sanford

unread,
Nov 19, 2002, 9:03:12 PM11/19/02
to
John --

I'm hoping Carolyn or Chris will respond (they are so much more eloquent and
verbose...), but I wanted to offer this:

Some confusion may be caused by the use of the term "component". The term
component is sometimes used when referring to a shared .dll, and also used
when speaking of Windows Installer components.

A Windows Installer Component can be installed only once and to one location
only. If the Windows Installer Component in question is already installed,
no action is taken by the Windows Installer engine (except to increment the
usage count if it was marked as shared).

A Windows Component (a shared library) can be installed to multiple
locations by multiple applications. The conditions under which this can
happen depend greatly on how (or what tool is being used) to install the
component. In short, this topic segways directly into .dll hell and some of
the core reasons why we need Windows Installer. For example, if two apps
from two separate companies both use a shared library (MyLib.dll), and each
app installs a copy of the .dll to their application directory, then
self-registers it, the last one installed wins. If that app is then
uninstalled, the .dll is either removed, leaving the other app broken, or is
left in place (due to the refcount in the registry) but is installed to a
(now) defunct location. There's many scenarios and versioning/backwards
compatability issues that can come into play here. It's a touchy area that
needs to be managed delicately and really requires some serious thought,
primarily by the author of the shared library.

Authors of shared components have the ability to take control of the
behavior of their component when installed by providing Merge Modules to
consumers of their component. This doesn't mean that ALL apps using the
shared library will work properly, but it does mean that all apps installed
by WI will use your shared component exactly as you intended.

> 1. R. Michael Sanford speaks of shared components. I take that to mean
> that multiple products can use the same component

Yes, for example, all apps the include the ATL Merge Module are using the
same ATL Component provided by that module.

and that each
> product should use the same instance of the component.

Yes, apps that rely on atl.dll should use the ATL Merge Module.

But is any
> component in a merge module necessarily a shared component?

Sort of. I mean the whole idea of a Merge Module is to share some data
between two or more installer packages. The specific requirements of an
application are what dictate if a specific Component should be marked as
'shared'.

How is
> that different from shared files?

The Windows 2000 web site has a white-paper that really dives into the .dll
hell issues and does a great job of explaining how WI mitigates many of thos
issues. Reading it will give you a better understanding of this issue. If
you can't find it let me know and I'll find a link to it for you.

And what about side-by-side sharing?

Some components are not fully backwards compatable or have functionality
that was obsoleted by a newer version. Isolated Components (aka
side-by-side sharing) allow an application to use a private version of a
shared library that is not affected if the shared (or public) version of
that library is upgraded to a newer version.

HTH

BTW, I'm pretty sure I've got this right, but I welcome any corrections...

--
R. Michael Sanford
ActiveInstall Corp.
http://www.activeinstall.com


"John Carver" <john....@pwrm.com> wrote in message
news:3ddaba47...@msnews.microsoft.com...

Chris Gouge [MS]

unread,
Nov 21, 2002, 6:17:03 PM11/21/02
to
Well, since you asked....

Having multiple instance of a component on a machine can be a very useful
thing to do in some scenarios (sometimes having multiple instances of an
entire product on a machine can be useful) but like many things with
software installation, understanding the nuances of what it means for
functionality and management requires a bit of research into the various
scenarios where multi-instance support may be encountered.

I'll start off by ignoring completely any definition of "component" other
than the type of component managed by Windows Installer. While there are
obvious functionality issues related to installing multiple instances of
generic software "components" on the machine (what if they both want to
share a data file?, or CLSID registration?, or configuration data?, or both
try to claim ownership of a resource or connection?) this is more a product
design issue than a Windows Installer issue.

Instead, I'll talk only about "Component" in the Windows Installer sense.
From the installer's point of view, it is very easy to have multiple
instances of the same component installed on the machine, and the Windows
Installer provides quite a bit of support for this case in its data model
(especially in MSI 2.0). In general, there are two easy ways to have
multiple instances of a component on a machine: components installed by
multiple products and components installed by multiple users.

Examining first the case of components shared by multiple products, the key
thing to remember is that there is nothing in MSI that forces two products
using a component to use the same instance of a component. This is why the
MsiGetComponentPath API takes a product code as its first argument. If only
one instance of a component could exist for a user, this argument would be
superfluous. But in fact, if a product allows the configuration of some
target directories it may ask MSI to install the same component to multiple
locations, and MSI is OK with this.

In fact, you can easily see this in action. If you look in the MSI SDK at
the installatin packages for the tools, you'll see that both Orca and
MsiVal2 install the same CUB files with the same component codes. By
default, these CUB files are authored to install to the same location, but
Orca allows you to specify a CUB file directory by specifying a path for the
CUBDIR property on the command line (if you are an Administrator - although
it is a public property, it isn't listed as a secure property.)

So if you take a clean machine and run the following commands:
msiexec /i msival2.msi /qb
msiexec /i orca.msi /qb CUBDIR=c:\testdir
you will see that the CUB files are installed in both "...\Program
Files\msival2" AND in "c:\testdir". If you call MsiEnumClients, two products
will be listed as clients of the component code, and if you call
MsiGetComponentPath, each ProductCode will return the path which is
appropriate for that product.

Of course, not everything is so smooth, because some APIs explicitly are
designed to not take a ProductCode (such as MsiProvideQualifiedComponent),
and the behavior of these APIs can be a bit interesting in these cases. MSI
will simply pick a product to provide the qualified component in an attempt
to satisfy the request. Somtimes this behavior is desired, sometimes its
not. This is why most such APIs have a corresponding API which DOES take a
product code (in this case, MsiProvideQualifiedComponentEx). Unfortunately,
there are some cases where you simply can't provide a ProductCode (in the
case of a fault-in from a CoCreateInstance call via advertised CLSID) and in
these cases you simply have to trust that a valid instance of the CLSID
implementor is returned.

Given the length of this post, understanding how multiple instances of a
component affect component install states, repair operations, registry keys
that are part of the components, advertisement, and reference counting is
(for now) left as an exercise for the reader. The behavior is generally
logical, but feel free to ask specific questions in the future if something
is unclear.

(Note on the above, the SDK installers for Orca and MsiVal2 have changed a
wee bit over time. If the above steps don't work for your SDK version, you
should be able to cook up a similar example).

Moving on now to multiple users installing the same product, you basically
have the same result through a different installation technique. Isolation
of component data between users before MSI 2.0 was spotty at best, so the
discussion here relates to MSI 2.0 and later. If User A installs a product
and User B installs a product, there is nothing that forces User B to
install the component to the same location as User A. In fact, if this were
the case it could be exploited by malicious users. The behavior you'll see
from the APIs in the multi-user scenario is generally the same as if no
other users on the machine had installed the product -- that is that there
will be a single client ProductCode with a single path and the only path
returned to the user will be that user's version of the path. In cases where
the install is per-machine and per-user on the same box, the per-user
install will normally shadow the per-machine install to ensure that the
per-user path is returned. Things can get a little complicated when you
throw in advertised products or features, but the behavior usually makes
sense if you think about it. Again, feel free to ask specific questions in
the future.

Just to be complete, there is a third way to get multiple instances of the
component on a machine in different paths, and thats if you have a product
which installs multiple instances of itself. This basically maps to the
first case above (multiple products in the same context) but I thought I
would mention it for completeness.

And of course, you can mix and match all three cases to get a really
confusing set of products and machine. Multiple users installing multiple
productcodes with multiple instances, some of them going to the same path
and some going to different paths. Trust in the MSI APIs and you will
normally get the appropriate path for the data you provide and your
installation context. (Of course, this doesn't mean that from time to time
you won't disagree with us about what "appropriate" actually is, it just
means that we have a security and isolation model and we generally stick
with it.)

-Chris Gouge
Microsoft Windows Installer Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

MSI FAQ:
http://www.microsoft.com/windows2000/community/centers/management/msi_faq.as
p


"R. Michael Sanford" <msan...@activeinstall.com> wrote in message
news:uZxouiDkCHA.1280@tkmsftngp12...

R. Michael Sanford

unread,
Nov 22, 2002, 2:25:48 AM11/22/02
to
Thanks for the info Chris! (I think...) ;-)

I would like to make a point or two in response:

1.)
What you say and what the docs tell us are in conflict. Consider this
quote:
--BEGIN QUOTE--


"The installer service installs or removes a component as a single coherent
piece. It tracks every component by the respective component ID GUID
specified in the ComponentId column of the Component table. Two components
that share the same component ID are treated as multiple instances of the

same component regardless of their actual content. Only a single instance of
any component is installed on a user's computer. Several features or


application may therefore share some components."

--END QUOTE--

As you can see, this clearly contradicts the point you correctly made. It
also makes me wonder why? You say it can be useful, but I don't see how.
In the case of .cub files, there is no advantage to having them use the same
ComponentId. The same could have been achieved by simply putting them in
separate components in both applications.

What's the point of having isolated components if I can install copies of a
component anywhere my little heart desires?
Why give a Component a GUID if it does not ensure only a single copy can
exist?
Upgrading a product allows you update files in an existing component, right?
Are you then obligated to upgrade all copies of that component? Failing to
do so means you have very different versions of something that is supposed
to be identical, right?
Two products can install the same component to different locations, but one
product cannot install the same component twice. Why?
If I do an AppSearch for that ComponentId, what do I get? Both values?
What if the second value was the one I wanted? How would I get it out of
the results property?
Can you honestly consider Orca a client of MsiVal's .cub files?
MsiEnumClients would indicate that is the case, right?

2.)
With respect to MsiGetComponentPath, one would think that this function
would be used to determine if a component was installed as a client of a
given product. What I mean is that it seems that it would be answering the
question: "Was Component123 installed and registered as a component of
Productxyz and if so, where?" This is similar to the case of
MsiProvideComponent where the product code is used to tell WI what to
reinstall/repair. I now understand the real intent, but the docs lead you to
believe something else.

3.)
Gaining a complete mastery of WI is no small task. In fact, it is a
monumental task that I fear borders on a real cost/value issue. At times
I've wondered if the problems with legacy installers are in fact a less
complicated issue to deal with than the intracacies of WI. When the
technology becomes so powerful that people cannot harness it, it stops being
powerful and starts becoming unweildy. If you took a sampling of 100 random
.msi files from random authors off the internet, how many would prove to be
error free? And how many actually use some of these sooper-dooper complex
features? My point is two-fold; 1.) the complexity of WI makes it extremely
difficult to create authoring tools capable of producing error-free
installations. 2.) The "Features" you've built into WI for 0.05% of the
developer community are killing the other 99.5%.

I completely understand what you said about trusting the API, but when
developers get into those types of situations where launching their app
kicks off a repair of office or some other app, it makes their users ask
questions that they can't (usually) answer.

Lastly, it would be really, really nice if your team opened up an informal
channel of communication with developers of WI authoring tools. Newsgroups
are helpful and your commitment to answering requests for help is
commedable, but discussion surrounding the implmentation of authoring tools
is something I for one would prefer to discuss offline due to the
confidential nature of planned features, design, implementation techniques,
etc...

--
R. Michael Sanford
ActiveInstall Corp.
http://www.activeinstall.com


"Chris Gouge [MS]" <cgo...@online.microsoft.com> wrote in message
news:u1$lZQbkCHA.3808@tkmsftngp08...

Chris Gouge [MS]

unread,
Nov 25, 2002, 6:42:10 PM11/25/02
to
You have raised a lot of issues here, I'll try not to miss anything
requiring a reply...

"R. Michael Sanford" <msan...@activeinstall.com> wrote in message

news:Oy5MRgfkCHA.1864@tkmsftngp10...

> 1.)
> What you say and what the docs tell us are in conflict. Consider this
> quote:
> --BEGIN QUOTE--
> "The installer service installs or removes a component as a single
coherent
> piece. It tracks every component by the respective component ID GUID
> specified in the ComponentId column of the Component table. Two components
> that share the same component ID are treated as multiple instances of the
> same component regardless of their actual content. Only a single instance
of
> any component is installed on a user's computer. Several features or
> application may therefore share some components."
> --END QUOTE--
>
> As you can see, this clearly contradicts the point you correctly made.

The only statement in the doc that is flat-out false in the statement "Only


a single instance of any component is installed on a user's computer".

Everything else in that paragraph is true. I will try to get the doc team to
look at this.

> It
> also makes me wonder why? You say it can be useful, but I don't see how.
> In the case of .cub files, there is no advantage to having them use the
same
> ComponentId. The same could have been achieved by simply putting them in
> separate components in both applications.

Sometimes, yes. At other times, no. Fundamentally, a component is "a set of
related resources usually managed as a unit" and adding a GUID makes it "a
globally named set of related resources usually managed as a unit". If you
change the GUID, you're changing the name. Sometimes this is OK, at other
times its not because the name is important. For example, I'm aware of a
component DLL shared between multiple products (unfortunately both component
and products must remain nameless for confidentiality reasons) and the
component DLL has several resource DLLs which it locates by passing the
known Component GUID of the resource DLLs to various MSI APIs. If each
product used a different component GUID for the resource DLLs, the DLL would
have to be recompiled for each product so that it knew what Component GUID
to ask for.

> What's the point of having isolated components if I can install copies of
a
> component anywhere my little heart desires?

The IsolatedComponent table and action are the MSI interface to the core OS
isolation functionality. This type of OS-integrated isolation provides much
more functionality than simply installing a copy of your files in a
particular directory. To start with, it actually changes the binding order
when loading DLLs and OCXs. You can find more information on this in the
MSDN topic "Implementing Side-by-Side Component Sharing in Applications".

> Why give a Component a GUID if it does not ensure only a single copy can
> exist?

Having a GUID makes the component globally identifiable, auditable,
ref-countable, etc. It is also what MSI uses internally to register and
track components and their resources, as well as to manage sharing in the
cases where multiple products do share the same instance. The ComponentId
column of the Component table is nullable, so you don't have to provide a
GUID if you don't want to. However the component then falls out of MSI's
management and cannot be repaired, uninstalled, queried, etc.

> Upgrading a product allows you update files in an existing component,
right?

Yes.

> Are you then obligated to upgrade all copies of that component?

No. Only one copy belongs to you. But see below.

> Failing to
> do so means you have very different versions of something that is supposed
> to be identical, right?

This is where things get interesting and scenario specific. In the case of
multiple instance support, ISVs often want isolation such that individual
instances can be upgraded indpendently of others. In essence, they want to
be in control of when and which patches are applied to files because each
instance may have different patching requirements. As an example of multiple
instance, consider the MSDE desktop version of SQL - each app can isolate
its own instance and control the patch level of those components themselves.
In other cases you may be talking about content-based components (html
files, data files, etc) which may need to be isolated to the application but
still have a constant GUID for programmatic and management reasons.

A key thing to remember is that having multiple instances of a component is
NOT the norm. Normally when a component is shared across multiple products
it is coming from a merge module or some other sharing system and the target
directory is not configurable because its based off a standard directory
(such as ProgramFilesFolder) and none of the Directory table entries are
public properties. Thus the products end up sharing. I do not have hard
numbers, but I have seen very few components that can install multiple
instances of themselves.

A big reason why is that until recently the OS lacked the isolation
functionality to allow you isolate the non-file data. Items such as COM
registration, registry keys, INI files, and so forth are inherently not
isolatable (except for a few cases such as per-user COM registration) which
prevents developers from supporting instances of their components.

> Two products can install the same component to different locations, but
one
> product cannot install the same component twice. Why?

This was a design decision made by the MSI team.

> If I do an AppSearch for that ComponentId, what do I get? Both values?
> What if the second value was the one I wanted? How would I get it out of
> the results property?

I don't like the answer a whole lot, but you get "a" path from the set of
paths visible to the user. The functionality is equivalent to
MsiLocateComponent(). If you need a specific path for a specific product,
you can use a simple custom action to call one of the APIs which accepts a
product code. I'm not really an expert on AppSearch, so I can't comment on
the design rationale behind this.

> Can you honestly consider Orca a client of MsiVal's .cub files?
> MsiEnumClients would indicate that is the case, right?

There are several possible answers to this question. Conceptually, as the
author of Orca and MsiVal2, I absolutely consider Orca a client of the .cub
files installed by MsiVal2. Try it! Install MsiVal2, then install Orca and
after you're done go manually delete the CUB files. Orca will see the CUB
files installed by MsiVal2 because it uses the QualifiedComponent method to
enumerate a set of component codes and then takes a path from those
component codes. Orca doesn't care who installed the CUB files, nor where
they are installed, it just knows that its a CUB file.

As a side note, you can actually have your own CUB files appear in the Orca
UI by publishing them from your own install(s).

> 2.)
> With respect to MsiGetComponentPath, one would think that this function
> would be used to determine if a component was installed as a client of a
> given product. What I mean is that it seems that it would be answering the
> question: "Was Component123 installed and registered as a component of
> Productxyz and if so, where?" This is similar to the case of
> MsiProvideComponent where the product code is used to tell WI what to
> reinstall/repair. I now understand the real intent, but the docs lead you
to
> believe something else.

You aren't wrong, they're different forms of the same question.
Fundamentally, you're saying to MSI "I've got ProductCode X and
ComponentCode Y. Tell me what, if anything, you know."

> 3.)
> Gaining a complete mastery of WI is no small task. In fact, it is a
> monumental task that I fear borders on a real cost/value issue. At times
> I've wondered if the problems with legacy installers are in fact a less
> complicated issue to deal with than the intracacies of WI. When the
> technology becomes so powerful that people cannot harness it, it stops
being
> powerful and starts becoming unweildy. If you took a sampling of 100
random
> .msi files from random authors off the internet, how many would prove to
be
> error free? And how many actually use some of these sooper-dooper complex
> features? My point is two-fold; 1.) the complexity of WI makes it
extremely
> difficult to create authoring tools capable of producing error-free
> installations. 2.) The "Features" you've built into WI for 0.05% of the
> developer community are killing the other 99.5%.

I understand your concerns. The development team for MSI is constantly
walking a fine line between making a product which is so complex that it
isn't used and making a product which is so limiting that it isn't used. For
every person that tells us that MSI is so powerful that its too hard to do
simple things, we hear from another customer who is complaining that they
have to write a custom action to do something because MSI doesn't have the
ability to do things the way they want. Both opinions are valid, and we're
aware that we need to try to make both groups happy. This feedback is
valuable.

> I completely understand what you said about trusting the API, but when
> developers get into those types of situations where launching their app
> kicks off a repair of office or some other app, it makes their users ask
> questions that they can't (usually) answer.

Yes, there certainly have been areas of MSI where the behavior can be
complex and we have not always done a satisfactory job of explaining things.
We are working to address these areas, and feedback on which areas are
confusing is helpful.

> Lastly, it would be really, really nice if your team opened up an informal
> channel of communication with developers of WI authoring tools.
Newsgroups
> are helpful and your commitment to answering requests for help is
> commedable, but discussion surrounding the implmentation of authoring
tools
> is something I for one would prefer to discuss offline due to the
> confidential nature of planned features, design, implementation
techniques,
> etc...

I've passed this suggestion on to the person who thinks about such things.
If\When I get an answer back, I'll let you know.

R. Michael Sanford

unread,
Nov 25, 2002, 9:42:17 PM11/25/02
to
Thanks for taking the time to answer my questions and concerns so
thoroughly. You've definitely enlightened me in an area of WI that I was
previously ignorant of.

--
R. Michael Sanford
ActiveInstall Corp.
http://www.activeinstall.com


"Chris Gouge [MS]" <cgo...@online.microsoft.com> wrote in message

news:OSKX$wNlCHA.1824@tkmsftngp04...

Reply all
Reply to author
Forward
0 new messages