Opened 4 years ago

Last modified 4 years ago

#681 new change

Clean up BHO registration mess

Reported by: trev Assignee:
Priority: P4 Milestone:
Module: Adblock-Plus-for-Internet-Explorer Keywords:
Cc: oleksandr, eric@… Blocked By:
Blocking: Platform: Internet Explorer
Ready: yes Confidential: no
Tester: Verified working: no
Review URL(s):

Description

Background

The way our BHO is currently registered is far from optimal:

  1. The registration code is duplicated between installer and DLL self-registration.
  2. DLL self-registration uses hardcoded paths (!).
  3. There is no documentation on setting up a development environment, nor is there an easy way to do that.

What to change

There are essentially two options:

  1. Remove self-registration code in the DLL. This will mean however that the installer needs to be used for development which is far from great.
  2. Fix and extend self-registration code in the DLL and make the installer use it. This will require more effort but it will simplify creating a development environment a lot.

From what I remember, the last state was Eric favoring the first solution and me the second. Eric, could you maybe sum up your reasoning again?

Change History (4)

comment:1 Changed 4 years ago by oleksandr

It is considered a bad practice to do self-registration of dlls from the installer, as it may cause leftovers should the rollback occur (http://msdn.microsoft.com/en-us/library/aa243943(v=vs.60).aspx#veconinstallerassociationsanchor4). Microsoft strongly recommends to do all the registration from within the installer, so that uninstall would remove everything.

I would actually not agree that we need to have only 1 way of registration. It's nice to have both, since one expects a BHO dll to be self-registerable and yet for end user the installer should do that. I don't think the registration stuff will change that much that we will have any problems syncing both ways.

I suggest we just fix the .rgs file and describe the duality in readme.md

comment:2 Changed 4 years ago by philll

spamblocked post by eric:
Before I get into my recommendations, let me first go over some more background on this. Oleksandr is completely right that it's a Very Bad Idea to use self-registration within an installation, exactly because it's not reliably reversible. Many (including me) also consider using self-registration during development a Merely Bad Idea (a downgrade in Badness from 'Very') for essentially the same reasons, largely involving the same kinds of issues. Self-registration was an absolute necessity when in the era of Visual Basic (6 and earlier, that is, pre-.NET) when Microsoft was heavily promoting component software distribution, what ended up as ActiveX. VB6 required that a component be registered on the system as a whole to be used at all; there was no facility for local access to the type library (for compiling) or to the entry points (for linking). It wasn't much of a problem when a component used the registry (and other system resources) exactly the same from version to version, which of course did not happen all the time. If you lost the old DLL (for example by overwriting an old version with a new one because they had the same file name), you'd have no ability to remove its cruft from your system. Regardless of this history, self-registration is a legacy of this period of software development. It's not that big of a deal if you know exactly how your DLL uses the registry, if you know how to manually correct problems, etc. Right now that characterizes (I think) just two people, me and Oleksandr. It does not scale particularly well to other developers.

I also agree with Oleksandr that having two different mechanisms for registration is pretty much a necessity. Using MSI (or at least Windows installer library mechanisms, which is tantamount to the same thing) is a necessity for end users, but it's inappropriate for developers since it's seriously overweight for that task and makes a big negative impact. (I'm speaking from experience. I tried with with a cut-down MSI once, and it didn't last the day.) The real question is how we provide registration to developers. Using self-registration within the DLL is not the only way.

I am in favor of option 1, to remove self-registration from the DLL. There are other good reasons for doing this, most notably that it's that an exposed entry point and end-users will invoke it if it's there. That would not be problematic if the DLL were capable of working in isolation, but that's not the case. The DLL needs a number of other files (dictionary, settings, first-run, etc.) at known locations, so registering the DLL in isolation causes non-function. We don't have a report of that yet, but ...

Self-registration, however, is only one way of getting the plugin registered with the system. The code to write registry entries can be in the self-registration entry point in the DLL, within an installer, or in an external program; they all work. So to be more specific, I am in favor of option 1, eliminating self-registration, and then providing an external tool (of some sort) to provide development-time registration.

I wrote such a tool last year. It was something of a quick hack, built with batch files and MS-specific system tools; it was admittedly ugly but it worked OK as a preliminary version. If I were building a clean and permanent solution for this, at this point I'd just write a separate developer-installation tool in C++ so it would compile up with the plugin itself. It wouldn't be much code, it would behave more cleanly, it would be easier to read (proper comments!), easier to use (documented command line), and wouldn't require as much special Windows knowledge to maintain as batch files.

For the record, I found I needed three basic functions from such a tool:
(1) Install the plugin, given arguments about where its files were. This is for invoking post-build within Visual Studio.
(2) Completely scrub all the registry entries relevant to installation. This is for recovering from mistakes.
(3) Enumerate all the registry entries relevant to installing the plugin (in whatever way), whether they were there correctly or not. This is for auditing what was actually happening. I saved more time using it this way, avoiding manual hunting through REGEDIT, than it took to write the scripts.

Of these functions, (1) is much the same as self-registration, but it's parametric, taking into account other files. (2) is more than self-unregistration, because it took out not just its own way of doing things, but all the others that might be there. (3) had no analogue in the old component world

comment:3 Changed 4 years ago by eric@…

Thank you for recovering that text, @philll.

comment:4 Changed 4 years ago by oleksandr

  • Platform set to Internet Explorer
  • Ready set
Note: See TracTickets for help on using tickets.