Automation
by Binh Ly
A script-based client is a client application that is not compiled and, hence, requires a scripting engine in order to run.An example of a script-based client is Microsoft's ActiveServer Pages (ASP) technology. If you're unfamiliar with ASP, it provides ascripting language used to dynamically serve web pages. ASP provides constructs thatallow scripts to access and manipulate COM server objects.
If you've been following me so far, we all know that COM server objects andinterfaces are accessed using vtable binding from clients in a compiled state.Scripts aren't compiled. More specifically, ASP scripts are interpreted by ascript engine that's part of Microsoft InternetInformation Server (IIS). Because scripts are non-compiled and cannot do vtablebinding, COM introduces another protocol to enablescript-based clients to tap into the power of COM servers.
Script-based automation is based on a protocol of runtime discovery andexecution of methods of an interface. The protocol works like this:
Quite a simple protocol isn't it? Let's look at some advantages of thisprotocol:
In COM terminology, this protocol is calledlate binding. The term "late" is used to denote that the client has noknowledge of how to call interface methods until (late at) runtime. Contrast that withvtable binding which requires that a client "know" the exact interface and theexact method position within that interface to call - and that"knowledge" is compiled into the client, not discovered at runtime.
Late-binding is made possible using a well known COM interface calledIDispatch. Based on the late binding protocol, we expect IDispatch to provide atleast 2 methods: one to determine if a given method exists (and return an ID ifit does) and another to execute a given method given its ID. IDispatch hasexactly those 2 methods:
IDispatch = interface
procedure GetIDsOfNames;
procedure Invoke;
...
end;
GetIDsOfNames is used to retrieve a method's ID given its name and Invoke isused to execute a method given its ID. In order to get the entire late bindingpicture, let's look at a sample ASP script:
Assume that our script is trying to create a Foo object contained in aFooServer server. IFoo implements a Bar method.
'declare Foo variable
dim Foo
'create Foo object
set Foo = Server.CreateObject ("FooServer.Foo")
'call Foo.Bar
Foo.Bar
Remember, this is a script and is non-compiled. A script engine/interpreterwill read this script line by line and manually execute statements within thescript. This is roughly how a script engine would execute the above script:
Statement 1: dim Foo
Script engine allocates space for variable named Foo
Statement 2: set Foo = Server.CreateObject ("FooServer.Foo")
Script engine contacts COM to create the object whose PROGID is "FooServer.Foo".We've previously discussed how this mechanism works. COM then contacts FooServerfor Foo asking for Foo's IDispatch interface. Foo hands out its IDispatchpointer to COM and then COM hands it back to the script engine.
Statement 3: Foo.Bar
Script engine then calls IDispatch.GetIDsOfNames ("Bar") to get Bar'sID. Upon receipt of Bar's ID, script engine then calls IDispatch.Invoke (BarsID) toexecute Bar.
Here's some important observations from the above process:
We've just seen a basic overview and rationale for enabling script-basedclients to "connect" with COM servers. Using the IDispatch interface,it's clearly possible to devise a generic mechanism of creating script enginesthat hide the complexity of interfaces from non-compiled clients. Knowledge ofthis technique can also be used to create your own "genericinterface-based" communication mechanisms.
联系客服