打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Automation

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.

Late Binding

Script-based automation is based on a protocol of runtime discovery andexecution of methods of an interface. The protocol works like this:

  1. A scripting-client wants to call a method X of an interface. The client asks the server "Do you have a method named X?" If the object responds "No, I don't have a method named X", the client knows that it cannot call that method. If the object responds "Yes, I have a method named X", the client knows that it can call that method.
     
  2. If a server says yes, it also gives the client a numeric identifier that corresponds to that method (similar, but not identical, in concept to a method's position index in a vtable). This numeric identifier is semantically unique for each method within the interface that contains the method. The client then goes back to the server and says "Execute the method that corresponds to this ID", passing in the numeric identifier earlier obtained from the server.

Quite a simple protocol isn't it? Let's look at some advantages of thisprotocol:

  1. This protocol is very simple and can be implemented by any server. On the client side, since the protocol is well-defined, the script interpreter/engine should be able to implement the protocol on behalf of the script. As the script engine runs/interprets the client script, it simply translates object method calls using this protocol.
     
  2. This protocol is not bound by restrictions found in vtable binding. For instance, although it is fatal to rearrange methods in a vtable, it is not in this protocol. Why? Because this protocol works in such a way that the client first asks if a method is supported and gets an ID back if the server says yes. The client then sends back this ID to server when it wants to call that method. Based on the ID, the server determines which method to execute. Notice that the client has no concept nor view of the ordering of the interface methods; all it cares about is runtime discovery of 1) obtaining an ID for a given method and 2) executing the method using the ID. Although this protocol is not strict with method ordering, it is however heavily dependent on method names - the client passes the method name into server when asking for the method's ID.

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.

IDispatch

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:

  1. The script engine talks to the server through IDispatch and only through IDispatch. This allows the script engine to talk to any server (past, present, and future) as long as the server exposes an IDispatch interface. Furthermore, the script itself is not concerned with interfaces nor vtables nor IDispatch; it's the script engine that takes care of all of that. For instance, the script can say Foo.ExecuteMethodThatDoesntExist and the script engine would be more than happy to call IDispatch.GetIDsOfNames ("ExecuteMethodThatDoesntExist") which, of course, would get back an result indicating that that method doesn't exist. In this case, the script engine won't call IDispatch.Invoke but will instead raise an error indicating an erroneous script statement.
     
  2. A server object that wishes to support script-based clients must support IDispatch (at the least, GetIDsOfNames and Invoke). If the server is not going to be used by script-based clients, there is no need for the server to support IDispatch - this is important, a lot of COM newbies think that objects must support IDispatch to be usable by clients. However, there is no harm in supporting IDispatch even if you won't have any script-based clients.

Where Are We?

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.

Further Reading

  • Inside COM by Dale Rogerson
  • Inside DCOM by the Eddons
  • Automation Programmer's Reference
  • Inside OLE by Kraig Brockshmidt
  • Essence of COM by David Platt
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Basics of an IDL file
What is LDAP?
TrackBack Technical Specification
java SE静态代理和动态代理
XtreemFS
Simplified Arabidopsis Transformation Protocol
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服