Handling Different Versions of Design Packages inside the IDE
A standard Delphi installation contains three different versions of Microsoft Office Automation Server Wrapper Components packages: XP, 2000 and 2010. Only one of those packages can be loaded at a time because each tries to register the same named classes for design time.
Assume we want to create three new projects, each using a different version of these Automation Server components.
The current IDE implementation makes this task hard to solve at least, if possible at all.
Let’s take a vanilla Delphi installation, no project loaded. Go to Components – Install Packages and make sure all three packages are registered (i.e. listed under the Known Packages registry key) and disabled. Here comes the first problem:
If you disable one of those packages in this dialog, close the dialog and restart the IDE, one expects that a disabled package stays disabled. It does not! When you restart the IDE that package is enabled again.
The only way to disable that package permanently is to add it to the Disabled Packages registry key. This can only be done by manually adding that entry into the registry.
We now have all of three packages listed in the Disabled Packages registry key. When we launch the IDE and check in Component – Install Packages all three are unchecked. Fine!
Now we create the first VCL Forms project and directly save it under the name ProjectXP. Then we go to Project – Options – Packages and enable that Office XP package. Save and close the project and restart the IDE. Here comes the second problem:
My expectation when enabling that package inside one project is, that this doesn’t influence the global settings for this package. Guess what: it actually does. It doesn’t make any difference if you enable a package in the global options (via Component – Install Packages) or inside the project options – the result is that the package is globally enabled again and you have to manually edit the registry to make it disappear again.
Mind: Even if you have set this straight again, simply opening ProjectXP will bring this package back into the enabled list and you later have to start again getting rid of it.
The current behavior of the IDE doesn’t let us just use a package on a per project base. The lack of a tool to permanently disable a package and the stubbornness of the IDE to keep a package enabled makes the whole process of project enabled packages a nightmare. Note that we didn’t even get to create the second or third project as the encountered barriers already acquired are simply too high.
IMHO, to get the basics right for project specific design time packages two things are mandatory:
- When no project is loaded and I disable a package in Component – Install Packages this setting should be saved (i.e. that package should be added to Disabled Packages).
- When I enable a package in project options this should yet load that package, but should not change the list in Disabled Packages. This setting must of course be reflected in the Excluded Packages entry of the project configuration (which means it should not appear there).
- When I close the project the IDE should revert to the default situation, where all packages in Known Packages are loaded except those listed in Disabled Packages.
- When I open a project the IDE should load all packages that are listed in Disabled Packages but not listed in the Excluded Packages configuration option.
- In addition when opening a project, any package that is listed in the Excluded Packages option should not be loaded either.
Point 4 will mostly lead to problems which have to be addressed. Assume I have two mutually exclusive versions of my custom package registered in my IDE of which one or both are permanently disabled. Now we load a project from another co-worker that knows nothing of our packages. Obviously the project configuration has not listed our disabled packages in the Excluded Packages section. According to point 4 all versions of my custom package should be loaded which is going to fail.
How to solve this?
Let’s categorize a package in regard to a project as either required, forbidden or don’t care. Although one might be tempted to take the packages listed in the Excluded Packages option as forbidden, I suggest introducing two new options: Required Packages and Forbidden Packages. (I tend to name things after what they mean and not what should be done with them.) Given these new options the IDE should behave as follows.
- When no project is loaded, the packages should be loaded as if the IDE were just started (i.e. load all packages in Known Packages except those listed in Disabled Packages).
- When a project is opened the IDE should unload all packages from Forbidden Packages and load all packages from Required Packages.
- When switching projects the IDE should act accordingly.
- Any required package of the old project that is not forbidden in the new project stays loaded.
- Any forbidden package of the old project that is not required in the new one stays unloaded.
This reduces package unload/load overhead during project switching.
- When closing a project the IDE should do either of the following:
- Restore the state from (1).
- Keep the current state as is and wait for the next project to load and act according to a project switch as in (3). (preferred)
What not to solve?
Be it a standalone project or a project group, nothing can hinder us to load a form, frame or data module from another project containing a component that requires a different version of any package or simply requires a package that is just forbidden in the current project. We can display a package selection dialog to load the missing packages (at least if this is allowed), but that won’t cover all possible collisions.
I have no idea how this could be overcome within the current limitations. To minimize impact we can put the affected files into read-only mode, so any changes caused by the wrong or missing package won’t ruin the file when saved accidentally.
That said, this behavior (allow to load packages when loading a form fails and retry or switch to read-only if this cannot be solved) might be a good thing anyway.