Running InstallUtil twice damages InstallState file?

  • Thread starter Thread starter dhbayne
  • Start date Start date
D

dhbayne

Hi,

I have a .NET assembly, written in C#, which has the RunInstaller(true)
attribute, and inherits from one of our utility classes called
BaseInstaller, which in turn inherits from the Installer class.

This assembly is contained in an InstallShield 10.5 generated MSI.
InstallShield uses InstallUtilLib to install and uninstall Installer
assemblies like this one.

Normally, this works fine; the assembly is installed during
installation, and uninstalled during uninstallation.

The problem is when I patch or upgrade the MSI. When this happens, the
assembly is installed a second time, which appears to corrupt the data
in the InstallState file.

Prior to the patch, the InstallState file contains Dictionary data:

<a1:Hashtable id="ref-15"
xmlns:a1="http://schemas.microsoft.com/clr/ns/System.Collections">
<LoadFactor>0.72</LoadFactor>
<Version>3</Version>
...
</SOAP-ENC:Array>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

However, after the patch or upgrade (and the second call of
InstallUtilLib against the assembly), all of this information is
missing from the InstallState file, and uninstallation fails with the
following exception:

Exception Type: System.ArgumentException
Message: The savedState dictionary contains inconsistent data and
might have been corrupted.
ParamName: NULL
HelpLink: NULL
Source: System.Configuration.Install

at System.Configuration.Install.Installer.Uninstall(IDictionary
savedState)
at MyLibrary.BaseInstaller.Uninstall(IDictionary savedState)

There is obviously something I'm missing here. Has anyone any idea
what it could be? TIA for any help.

Yours,
Duncan Bayne
 
Just to be precise about what's going on here, the InstallUtil stuff isn't
installing your assembly, its a jacket for calling an Installer class custom
action in your assembly. Your custom action is being installed during
updates (it will be called during a repair too). So the basic question here
is whether you really want your install custom action to be called again in
these circumstances. If you don't, add a condition of Not Installed to it.
Typically you don't want to call it again if it's (say) installing a Service
or just patching files and not changing anything else.

If you're doing a major upgrade, that's an uninstall followed by an install,
so it should mostly work.

Installer classes can be rather tricky. There's nothing they do that can't
be done using less complex methods. I'm wondering what your Installer class
does.
 
[Please do not mail me a copy of your followup]

(e-mail address removed) spake the secret code
I have a .NET assembly, written in C#, which has the RunInstaller(true)
attribute, and inherits from one of our utility classes called
BaseInstaller, which in turn inherits from the Installer class.
[...]

After having used this method (VS.NET has a similar way for
using Installer classes with custom actions), I can't say that I would
recommend doing this ever.

As you say there is this secondary installutil state file that can
introduce problems and you also don't have any real way to interact
with Windows Installer through these classes.

What is it you are trying to do in your installer class? There is
almost always a better way to do things like install services and
register COM objects. For some reason everyone in .NET thinks they
need to write Installer classes and most of the time they don't.
 
It turns out the reason had to do with the way my ProjectInstaller
worked. If it was doing an upgrade, it removed the
System.Message.MessageQueueInstaller from its own Installers
collection, so as not to purge the existing queue.

This resulted in the info about the MessageQueueInstaller not being
serialized into the InstallState file, which resulted in an exception
during uninstallation.

We now use our own MessageQueueInstaller, which doesn't do a purge of
the queue if it already exists, so it's safe to run this one multiple
times (e.g. once during an installation, then again during an upgrade).
 
Back
Top