How to Break Delphi's Object Repository


I'm a long time Delphi user and have taken advantage of the Object Repository quite a bit. It's really handy to take a unit or project that might be useful somewhere else but in a slightly different form and add it to the repository. Later, when you need to use that bit of code, you can select it from the repository right from within Delphi and it will make a copy of that code in your new project.

If you're wondering why not use a library or even the popular Delphi IDE plug-in, GExperts, with its "librarian" feature, I do. A code library is static and GExperts is best for small code snippets. But sometimes you just need to copy and modify a large chunk of code. For this, I have found Delphi's Object Repository to be a great tool. And actually, anyone who creates projects in Delphi's IDE uses the standard repository objects that come with Delphi, namely the "New Project," perhaps without realizing it.

I write a lot of plug-in modules for a point-of-sale software called Retail Pro. Its plug-in API requires building COM servers that adhere to a set of interfaces. There's a lot of structure to be setup for each plug-in and several properties that interact to accomplish a retailer's goal. Each interface is typically implemented as a single Delphi unit and while it has the same basic structure (since it implements an interface) it will have different method implementations and property values. It's hard to remember all the different nuances that each API call can have and how they can be used inside Retail Pro. So what I've done is create a repository unit for each interface and copied all the documentation for that interface into the unit using XML Documentation. Then I've added it to the Delphi Object Repository.

When I need to build a new plug-in for Retail Pro, I create a new plug-in project and then add the interface units I need to implement from the repository. This jump-starts my project with all the code in place, complete with documentation and even TODO items that I can just fill in and compile. Of course, the end solution involves quite a bit more than that, but a lot of work has been saved.

So, now that you're convinced this is a cool tool to add to your collection, it should come with a little warning: it's fairly easy to break and there's not much documentation. There are a couple of references here and there that talk about Delphi's repository setup when it's installed, but it took some searching to find out where additional items added by the user are stored.

The folder for Delphi's built-in repository (that doesn't change) is in its installation folder under Program Files (x86), or if you're still on a 32-bit system, just Program Files. Since Windows Vista came out with it's increase protection of the Program Files folders, the editable copy of the repository is located in a user directory, probably under either %APPDATA%\CodeGear\BDS\<version> or %APPDATA%\Embarcadero\BDS\<version>, depending on your version of Delphi, and is named RADStudioRepository.xml. (Really old versions of Delphi stored these settings in delphi32.dro under Delphi's bin folder.)

The structure of the RADStudioRepository.xml file can, of course, be changed with your favorite text or XML editor. That in itself could break the object repository, but it can actually be done using Delphi itself. (Dislaimer: I've only tested this with Delphi 2010, not anything newer. It's possible the following has been prevented in newer versions of the IDE.) When you're adding an item, you can optionally specify an icon. The help for this screen says that you can use a bitmap of any size but it will be cropped to 60 x 40 pixels. I happened to choose 24x24 bit icons for several items added one day. I noticed immediately the New Item... menu option no longer showed the category of repository items I had just added. Restarting Delphi, I got an "invalid image size" error every time I selected File | New | Other... which rendered all my user entries in the repository inaccessible.

I looked at Delphi's own repository settings and saw that many of them were 32x32 bit. So I manually edited the XML file for the entries I had entered and changed them to point to 32x32 bit icons, restarted Delphi, and it worked. (You can also simply leave the icon path empty in the XML or not add one in the first place--the icon is optional.)

Surprisingly, an invalid path or filename to the icon does not break the repository, it's just when it tries to actually load an icon with a resolution it's not expecting (or one that's evidently not supported) that causes it to throw up an error.

Add new comment