Roshan (http://pensieve.thinkingms.com/) posted a blog on ObjShell (http://medialab.di.unipi.it/Project/ObjShell/), an old project of mine. At the time I was impressed by COM and the fact that Windows was based on an integration philosophy different from Unix. The basic Unix model for composition are processes connected through pipes. In some sense you can consider programs as basic components with a single standard interface: stdin, stderr, and stdout. A unix "component" can be run only "out of process", in the sense that the model constraints you to have one component running in a process.
Of course the same compositional model is available on Windows, but isn't so popular as it is in Unix: on Windows you can rely on a more powerful composition system that, in a sense, is a superset of the Unix one. It's a pity that nobody says this!
You can think COM as an extension to the classic Unix model:
- components have multiple interfaces, not just one
- many components can run in a single process
- Windows Scripting Host plays the same role as the Unix shell: you combine components in a convenient environment
I was amazed by this powerful abstraction but I was also disappointed that it was also pretty hidden too! In Unix shells are the fundamental tools; in Windows WSH isn't that known, and you don't even get a top level to lively interact with components.
So I decided to build a top-level for JScript and WSH so that you could write statements interactively, in order to help script development. As a matter of fact I was thinking as a shell with an enhanced history module in order to script "by example" in the sense that statements were collected in a file with the user controlling log on that file.
Both on Unix and Windows, when you use a shell, you expect an help from command using some command line switch: nobody is able to remember all the options of the ever growing command community! Is there a similar mechanism on components?
In .NET the answer would be definitively yes: reflection can support you with information about component interfaces. Besides, in the COM world the answer is "yes and no": the reflection counterpart in COM are type libraries, not always available.
Nonetheless many compoents provides typelibs so I decided to provide some primitive to simply print component interfaces on console. ObjShell comes with a COM component called OConsole, which provides access to console features and compoents' typeinfos.
If you open the shell and type:
> w = CreateObject("Word.Application")
// Interface of Word here
you instantiate Word as an out of process component, and inspect its interface.
Although the shell is far from complete I often use it to prepare my WSH scripts!
After few days of shell programming I quickly realized that syntax is a problem. Shells on Unix are popular because they provide a concise and effective syntax for composition. On the other hand the dot notation isn't either concise or effective, at least if compared with shell languages! At first sight it may seem only a matter of producing a better (perhaps more obscure) syntax. But after some thinking I realized that the verbosity of the dot notation is striclty related to the fact that component interfaces are more complex than the simple Unix approach. You need to distinguish types (in shells all arguments are strings), methods, properties, etc. So the real question is: how can we retain the power of a full fledged component model with more convenient notations?
After some thinking I came up with a possible architecture to have the best of both worlds. As I said shells can provide simpler interfaces because of simplyfing assumptions such as type of arguments. How can we do the same in a component world? ObjShell provides the notion of reader to address this issue: a reader is a small script responsible for reading a language L and translating into JScript (that is evaluated afterwards). The language L has the role of providing a convenient language for a class of components. For instance, if you are interested in the MAPI library you may provide a shell like interface to the MAPI COM objects:
> cd Inbox
One may think: but this is crap! It would be a nightmare having to implement all these readers: they are in fact small compilers! Fortunately I observed that often readers are simple programs whose role is to add commas, quotes, semicolons and all the others syntactic elements required by JScript. Thus with few regexp it's easy to write a reader. With this extension I was able to provide a full extensible shell for combining COM components with convenient syntaxes.
Moreover you can always switch back and forth among the available readers. Try for instance:
Object: 0> setMode("Command")
Command: 1> dir
Command: 2> setMode Object
In this example you are using the Command reader: a reader that makes the top level behaving like cmd (though it is totally handled in JScript). After running the required commands you can switch back to the Object reader (the one with the JScript syntax) and continue in that environment. A neat consequence is that data acquired in a reader may be reused in the others (if the reader provides some means to save and access variables in the JScript running environement).
In conclusion ObjShell is not incomplete as it may seems from the help file. Nonetheless I think that ObjShell.NET would be a more interesting project in a .NET world. I'm not sure to have the strength to do it, perhaps some day... Now I have BDB# (with a great PersistentHashtable) and CodeBricks to maintain!!!