A few minutes ago I posted a small Visual Basic 6 class module that could be used to register an applications objects in something called the “Running Object Table” Or ROT. Rather then go on a long monologue in that post I’ve decided that this is an excellent topic for a blog entry, with pictures and whatnot. The forum thread I created is here, and provides the source to a useful class module that can be used to expose your objects on the ROT.
In order to fully understand what the ROT is and it’s usefulness, it’s important to have a basic understanding of COM. At the moment COM is really a “legacy” technology, and Microsoft much prefers that people develop .NET assemblies instead. Of course, what MS fails to mention is that it’s unlikely that COM support will be withdrawn from any foreseeable version of windows, simply because it is so deeply rooted and so necessary for applications, including Microsoft’s. In any case, having a solid knowledge of COM is not something that is going to become useless or even irrelevant anytime soon, so it cannot hurt even a non-programmer to understand some of the basic semantics involved.
Originally, COM wasn’t really released with any fanfare; in fact, it was simply the “bed” upon which the more prevalent technology at the time, OLE (Object Linking and Embedding) was based. OLE really is an awesome technology, but the problem is nobody really knows how to use it. Anyway, the main idea was that each application knew how to deal with it’s own files; for example, excel knew spreadsheets, word-perfect knew word processing, etc, and the idea was that instead of trying to get applications to implement the various different application “powers” (such as having built-in word processors and the like), they could simply call on another application to do it. For example, if you made a useful chart in Excel 5.0:
Now, of course you could make a chart with the spreadsheet, but let’s say you wanted to embed the spreadsheet into your word document. In pre-OLE versions of word, you could copy-paste a picture of the spreadsheet, but if you ever needed to change it you’d need to go right back to excel, find the file you originally used, make the changes, copy it, paste it, reformat the bloody document again because pasting it has totally screwed up your pagination, etc. Basically it translates to a huge pain in the ol’ keester.
So Microsoft decided, hey, you know what, let’s make it so you can actually place the spreadsheet document itself into the word document, and you can edit the spreadsheet and have it update in the word document automatically. One of the development team leaders for excel at the time said, “that might be a bit difficult” at which point they fired him and hired somebody else. I’m making this up, obviously. the quip was more along the lines of him trying to discuss his previous extra-marital relations with the project managers mother. Or maybe it was their wife, in either case it’s generally not something you bring up around the water-cooler even in faint whispers, let alone in the middle of an important business meeting about important businessy things, like who keeps taking the bloody stapler.
Anyways, Microsoft eventually perfected the technology that they called OLE. (oh yeah, and just so everybody is aware, it’s apparently pronounced “olay”… so don’t try to embarass yourselves. I still personally pronounce it Ohh- Ell- eee, but hey, I’m a rebel. Also pronouncing it “olay” is just begging for jokes about “oil of OLE” or perhaps even matador references. It just feels like it was chosen for comedic reasons.)
using OLE, you could link your excel spreadsheet to your southern US based newspaper, by using the very popular “Copy” command from Excel, and then using “paste Special” in word, you could get the following dialog:
As you can see, there are a number of choices here. the relevant one to this discussion is to insert it as a “Excel 5.0 Worksheet”- the default for the two radio buttons on the side is to actually “paste” the item into the document; here I’ve chosen to paste a link. pasting the spreadsheet into the document directly (rather then linking it) still allows you to edit the spreadsheet, but the spreadsheet data itself is saved right in the word document when you save it. Because linking the object instead offers one extra point of failure and because I like living on the edge, I always opt to link the documents even if I have no good reason to.
In any case, the resulting newsletter is this:
beautiful! such magic is the very essence of OLE. In fact, one could even take advantage of OLE in their Visual Basic Applications, starting with Version 2.0, which included, among other useless “professional” controls, the OLE client control.
“But I thought this entry was about the ROT” you ask. to which I reply, shut the hell up, will you, I’ll get to that eventually, and the less you try to fictitiously interrupt me the quicker I can try to ease the topic back to the present day and the running object table. Don’t worry, I haven’t forgotten about it.
Anyways; as I was saying, COM was basically what this OLE magic is based on, and was in fact the “plumbing” that made OLE work. OLE was only the visual manifestation of COM; therefore it was the part that was oooh’d and ahhh’d, (although the actual response was more a hum and a haw, since nobody could really figure the bloody thing out). COM just sort of sat in the background. unnoticed, watching OLE take the spotlight, earn all the respect and get all the beautiful women and free cream soda. Microsoft created something called “OLE Controls” whereby various User Interface widgets could be created using a number of OLE Interfaces with confusing names and functions, like an IPersistFile that didn’t deal with files, IOLEActiveObject, and other weird esoteric interfaces.
Things started looking up with the creation of “ActiveX Controls” which are exactly the same as OLE Controls, but don’t require all the silly interfaces to be implemented (at least, not as many of them). Pretty much all you needed to implement were a few basic interfaces. With the release of Visual Basic 5.0, this task became even easier; soon enough ActiveX Controls were sprouting up out of basements everywhere with dubious security and hardly little effort or skill. Unfortunately this had the effect of backfiring on Microsoft as they had forgotten that IE3 sorta just allowed ActiveX Controls to do what they pleased; in the long run, Internet Explorer gave ActiveX a very bad name. The technology itself is sound; however, one consumer (Internet Explorer) has an awful track record when it comes to actually being intelligent with what is actually run. First MS decided, “ha! we’ll just make it so they have to sign the control as safe with this little tool” much to their surprise, the people who were doing illegal things already by creating spyware as ActiveX Controls gladly downloaded the tool and signed them, even though the EULA was quite clear that you couldn’t sign malicious files. “dear gawd! these people are MAD! mad I say! have they any idea the legal repercussions of agreeing to a shrink-wrap EULA implicitly in a completely non-legally binding way?” exclaimed… well, somebody at MS, to which the common reply was “Tom, we know you’ve been taking staplers home.”
In either case, ActiveX got noticed, and while IE was a massive failure when it came to using ActiveX, ActiveX was perfectly safe on the desktop itself; in fact, it’s still quite prevalent. Go ahead and look on your own windows machines- ActiveX Controls are found in “OCX” files. many are even installed by default. Because ActiveX was more a Programming technology then a silly little User Interface gimmick like OLE, programmers liked to pick apart it’s innards like a vulture likes to take it’s pick from the smorgasboard of delightful organs that are present on a freshly killed wildebeest. Programmers learned of the various COM component technologies that powered ActiveX and OLE before it.
It was around this time that COM itself became the “technology of choice” when it came to interoperating with the various components of windows. So much so that COM itself became deeply rooted in the Operating System; with the actual Shell interfaces that allow for such things as IE plugins and Browser helper objects and Shell Extensions being implemented as COM interfaces.
COM itself establishes a binary standard between modules; it essentially lays out how objects are to look in memory, so that other objects can use them. In a strange coincidence this layout was nearly identical to the way the Visual C++ compiler laid out it’s Class instances.
Unlike C++ itself, or java, or .NET, for example, however, COM does not really facilitate for most things that people seem to require in order for something to be “object oriented”. For example- there was no Implementation inheritance. There was interface inheritance, to be sure, but they didn’t add implementation inheritance because they believed that to replace parts of the functionality of a pre-existing class with your own while leaving parts of the original code intact requires a knowledge of what that code does beyond what you can see, and really there is no debating that fact on the level.
Now then, enter OLE automation, which was really just COM with a fancy name. OLE automation basically meant that you could “control” other applications from another application, completely cross-process. For example, nowadays you can write a VBScript that interfaces with Microsoft word to open a document, make changes to it, save it, and close it. This is possible through OLE automation, because the Word Program exposes itself to other applications, who, strangely enough, are not revolted by Word’s nether regions.
Visual Basic has allowed for the creation of ActiveX programs since Version 5; what Word would be equivalent to as a Visual basic project would be an “ActiveX EXE”. there are both ActiveX EXE and ActiveX DLL projects; they act quite similar to one another, in that the various methods of using their objects are the same in either case. the main difference between them is that an ActiveX EXE is, for obvious reasons, a completely separate process, while a ActiveX DLL is contained in the same process and every process that uses it. This means that all data passed back and forth to an ActiveX EXE needs to be marshalled across a process boundary. Very time consuming, but at the same time the EXE can perform operations asynchronously from the application itself, which, in the case of Visual Basic, really only has a single thread.
When a ActiveX Server program is running, the general idea is for it to add itself to something called the “Running Object Table”. This ia global table that stores all the various active COM objects that can be retrieved. For example, Word, Excel, Access, etc, all place their “Application” objects into this table.
Visual Basic ActiveX EXE programs, however, for whatever reason, do not. This despite Visual Basic having a function that can acquire objects from the running object table, the GetObject() Function.
GetObject
The GetObject Function is probably one of the strangest functions with the oddest behaviour and the quirkiest set of rules of all the functions in the Visual Basic Language. The syntax seems simple enough:
1 |
GetObject([Pathname],[class]) |
pathname, we can guess from our encounters with Excel and word with OLE, would probably accept a OLE enabled document. and lo and behold, passing a excel, word, or other OLE server application document returns that document object. the class parameter however requires some explanation regarding it’s background.
All COM objects have at least one thing associated with them; a CLSID, which I guess stands for “ClassID”, but could just as easily stand for “Chickens Like Seeds In Dung”. This CLSID is required when instantiating (creating an instance of) the object. Some objects have another, optional, more human readable representation, known as a “progid” (god knows what it stands for. I’m going to say “People Really Ought to Give It a few Days” or something. This is far easier to read then the CLSID. a ProgID might be “Excel.Application”, whereas it’s CLSID is {00024500-0000-0000-C000-000000000046} (although technically it fits in 8 bytes, this is the conventional “human readable” form of a CLSID.
Now, you can call me dull, dense, made of cheese or fond of yogurt, but I don’t think I’m too far off-base in saying that the progID, While having an utterly ridiculous acronym expansion that I just made up, is a lot easier to read then the CLSID.
In any case; the Class argument to GetObject() is actually a ProgID. So the question is; how does one call this function to get a running instance of the program? If you do:
1 |
Set X=GetObject("","Excel.Application") |
a new instance of Excel starts in the background and your given it’s application object. However, it turns out the first parameter is optional… you can in fact do this:
1 |
set X = GetObject( ,"Excel.Application") |
and your given a instance of Excel that is already running, if available. If not, you get an error. You can trap the error and perform either the former empty string version of the function call or use CreateObject() to create a new instance explicitly though, if necessary.
Now, given that GetObject() when used in that scenario acquires the object from the running object table, it becomes evident why it will not work for Visual Basic objects; as previously discussed, the visual basic Runtime never actually anything to the ROT. This means it’s necessary to do so yourself by explicitly adding it to the ROT using the COM API.
Now, although I wrote the class I describe in the forum post 5 years ago, I distinctly remember that from beginning to end only took about 30 minutes. Most of the COM code I have in there was ripped directly out of a module in my BASeEdit XP project I was working with at the time. One tool I found useful while I was working on it was a little Utility that came with Visual Studio 98 called “ROT Viewer”. Since IT doesn’t appear to be available online anywhere, I have taken the liberty of uploading it myself.
Even the non-programmer can get a few minutes of mild amusement out of the program. With Vista and 7, you need to start the program with Administrator rights, otherwise it doesn’t show anything. Try it out; start word, excel, (I wonder if MS works has a COM server…) and any number of other programs, and watch them get added to the table, close out the programs, watch them leave… OH THE EXCITEMENT!
Have something to say about this post? Comment!