By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,127 Members | 1,338 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,127 IT Pros & Developers. It's quick & easy.

installer woes (MSI generated by VS.NET 2003)

P: n/a
I'm having some inconsistency problems with my deployment project ("Setup")
and its custom actions ("Installer"). I'm using Visual Studio .NET 2003
(.NET 1.1, no service pack) on Windows XPSP1.

My main project is a band object (Explorer Bar) in an assembly (.DLL) that
needs to be registered on installation and unregisted on uninstallation. In
addition, during installation, Setup creates registry subkeys, sets registry
values, installs some application files, and adds a new file-type. On
uninstallation, Setup is supposed to undo all of that. More specifically, I
have custom actions for Setup that are run within the Installer class. The
Installer class is within the main assembly, and perhaps surprisingly, that
seems to work, some of the time. I have also tried putting the Installer
class in its own assembly, both as a class library and as a console
application, and that doesn't seem to work any better than having the
Installer class in the main assembly. Sometimes the registration or
unregistration of the main assembly fails. The workaround we tell our users
(a small userbase so far, fortunately) is to "repair" after installation, or
to uninstall completely before installing a new version. Neither are as
ideal as being able to simply install over the previous version. I think
there are two subproblems.

1) The Uninstall custom action in the Installer class isn't always called.
This is especially inconsistent. My Installer class overrides
OnBeforeUninstall() [so that the main assembly is unregistered before the
files are removed] and Uninstall() [so that savedState is empty, in order
for the installState to be removed]. Lacking better debugging tools for
MSIs, I added code in these methods to set registry entries containing the
timestamp at the beginning and end of each of these methods. I verified
that usually the Uninstall custom action is (but not always) called when the
user explicitly asks to remove the package (via "Add/Remove Programs"), but
when the user is installing over a previous version, sometimes (but not
always) the Uninstall custom action is called. As a side note, I change the
installer version, PackageCode, and ProductCode whenever I build a new
installer. I don't understand why these inconsistencies occur. For a while
I thought VS.NET might randomly corrupt the Setup.vdproj file and that I'd
have to remove and add the custom actions again, in order to be sure that
the Uninstall custom action was registered, and once or twice I built the
Setup.vdproj file from scratch, fearing general corruption in the file. This
seemed to help (especially the latter), but not for too long, and it's not a
sustainable solution, even if it's not a placebo. In addition, which may or
may not be related, the Setup.MSI doesn't seem to always uninstall all
registry entries, and because of that, I've had to add a few lines to my
Uninstall custom action. It doesn't seem right to me that the MSI would
sometimes not uninstall registry entries that it added in the first place.

2) The second subproblem is more specific to my project, and this occurs
sometimes when I'm registering the main assembly. The main assembly is
registered in the overridden OnCommitted() method of the Installer class,
presumably after the previous version's main assembly was unregistered in
the OnBeforeUninstall() method. In the case where the previous version and
the new version were installed in the same "Program Files" folder, the
assembly containing the Installer class will have the same exact CodeBase,
but they'll of course have a different FullName because the assembly version
has been automatically incremented. It seems that sometimes the Commit
custom action will re-register the old assembly instead of registering the
new assembly. My registration code looks like this:
RegistrationServices rs = new RegistrationServices();
rs.RegisterAssembly(MyAssembly, AssemblyRegistrationFlags.SetCodeBase);
and my unregistration code looks like this:
RegistrationServices rs = new RegistrationServices();
rs.UnregisterAssembly(MyAssembly);
MyAssembly is defined as a property:
Assembly MyAssembly
{
get
{
return Assembly.LoadFile(InstallDirectory + "assembly.dll");
}
}
I used to use Assembly.Load(path) instead, but it seemed that
Assembly.LoadFile(path) worked better. My concern is that either the
Uninstall and Commit custom actions share an AppDomain, so sometimes
MyAssembly might return the previous assembly during the Commit phase if the
previous assembly wasn't somehow still in Commit's AppDomain after Uninstall
finished. I tried creating a temporary AppDomain and then loading the
assemblies within that, but it threw a deserialization exception. I suppose
the overall issue of this subproblem is that I'm trying to register and
unregister assemblies without knowing the FullName of either assembly, as
I'm trying to semi-automate the build process and stay within VS.NET as much
as possible (for now).

I know these are complex and possibly peculiar problems! While I'd love for
someone to post a solution for either (or both!) subproblems, at the very
least, I'd appreciate hearing tips regarding debugging deployment projects
and custom installation classes, similar stories of installer woes and
solutions, and recommendations for possibly better installation/deployment
tools than VS.NET's deployment projects. Something like InstallShield seems
like overkill, but maybe it's what I need to have dependable installations.

Thanks for reading this far!
Arun
Jul 21 '05 #1
Share this question for a faster answer!
Share on Google+

This discussion thread is closed

Replies have been disabled for this discussion.