Program Files Microsoft Office Office10 Startup For Microsoft Word 2000: Program Files Microsoft Office Office Startup. Move any files that are located in that folder to your desktop. Open the following folder: Documents and Settings username Application Data Microsoft Word Startup. Move any files that are located in that folder to your desktop. This icon appears alongside links to resources that are not developed or maintained by Thomson Reuters. We provide access to these resources for your convenience, but we are not responsible for their accuracy. 2nd Opinion Do not Close) cannot load the OLE 2.0 or Docfile libraries. This keeps showng up whenever I try to - Answered by a verified Mac Support Specialist We use cookies to give you the best possible experience on our website.
- Cannot Load The Ole 2.0 Or Doc File Libraries App
- Cannot Load The Ole 2.0 Or Doc File Libraries Free
- Microsoft Word Cannot Load The Ole 2.0 Or Doc File Libraries Mac
| Allegro CL version 9.0 Unrevised from 8.2 to 9.0. 8.2 version |
This document contains the following sections:
1.0 Introduction to OLE support2.0 Introduction to high-level OLE/OCX interface
2.1 OCX objects and Allegro CL
2.2 Type Libraries
2.3 Typelib entity: CoClass
2.4 Typelib entity: Enum
2.5 Typelib entity: Interface
2.6 OLE/OCX low-level internals discussion
2.7 Reference guide to interface operators
2.8 Index to high-level interface operators
3.0 Introduction to the low-level OLE interface
3.1 Sample Programs
3.2 System Structure
3.2.1 Basic Concepts
3.2.2 Important CLOS Issues for an Allegro CL OLE Application
3.2.3 Special OLE Data Types
3.2.4 Language and Locale
3.2.5 Interfaces and Objects
3.2.6 The Registry
3.3 Writing an Automation Client
3.3.1 Dynamic naming
3.3.2 Unique ids
3.3.3 Classes
3.3.4 The Lisp remote-autotool Class
3.3.5 Set-up
3.4 Writing a Server
3.5 Defining Interfaces
3.6 Low Level View
3.6.1 Class Hierarchies
3.6.2 Control Flow
1.0 Introduction to OLE support
The high-level OLE/OCXinterface, introduced in 2005, is described inSection 2.0 Introduction to high-level OLE/OCX interface.
For some time, Allegro CL has supported a low-level OLEinterface. This is still supported and described inSection 3.0 Introduction to the low-level OLE interface.
2.0 Introduction to high-level OLE/OCX interface
This documentation for the OLE/OCX interface is preliminary. It willbe updated from time to time.
The high-level OLE/OCX interface is implemented in a number ofmodules. The primary module is the :ole-dev module. The remainingmodules are loaded automatically at the first call to the macroole:def-ole-linkage.
This document describes the interface. The relateddocument, ole_reference.htm, lists all theoperators.
To start using the interface, then, evaluate the following require form:
And then make a call to ole:def-ole-linkage.
You might need ole/client/autotool.fasl. This form in a filewill load that file:
Symbols naming OLE functionality are in the :ole
package.
2.1 OCX objects and Allegro CL
OCX objects are entities that provide services through OLE interfaces.They may be implemented in any language, and may be instantiated inthe address space of the client, via loaded DLL's, or in separateaddress spaces as local or remote processes. A Lisp program canrequest the services of any number of OCX objects. A Lisp program canalso implement OCX objects, but this document only addresses the useof externally implemented OCX objects. A forthcoming separate documentdiscusses OCX controls used as widgets on an IDE form.
To use an OCX object, the Lisp application must request its creationand receive one or more interfaces to the object. The application canthen invoke the object's methods, inspect and change its properties,and eventually release the object so that it can be destroyed. Inorder to code the method calls and property references, the programmermust know what methods and properties the object supports. To performthe actual invocations, Allegro CL must know the interface and objectdefinitions. The programmer may be able to get the information he orshe needs by reading documentation; Allegro CL gets the definitionsfrom a type library supplied with the object.
2.2 Type Libraries
Type libraries, also called typelibs, are compiledrepresentations of IDL files. IDL stands for InterfaceDefinition Language; it is the C-like language Microsoft uses todescribe the collections of interfaces supported by an OCX object. Atypelib is sometimes provided directly in file format, often in a filewith a .tlb extension; type libraries may or may not berecorded in the registry.
To have Allegro CL learn the definitions in a type library, we need tosupply a pathname to the typelib file or else provide a registry keyleading to the typelib. The basic function to read a type library isdescibed below (see ole:load-typelib). The ole:load-typelib functiondoes not itself define the foreign function linkage needed to activateand control the objects from Lisp. The ole:def-ole-linkage macro, also describedbelow, invokes ole:load-typelib and then processes theresulting information to define Lisp classes, constants, and methods,giving the programmer convenient access to the objects.
The type library provides Allegro CL with definitions of structures(structs), symbolic constants (enums), interfaces, and objects(CoClasses). The ole:def-ole-linkage macro expands into aform that defines corresponding foreign structures, Lisp constants,classes, functions, and methods. These different components of thelisp-to-object linkage are named by symbols, and this introduces aproblem. A name that appears as a constant or method in a type librarymay duplicate the name of some other entity in a different library, orthe name of some existing common Lisp function. ole:def-ole-linkage resolvesthis by interning all names for typelib entities in a special package,a package that is normally specific to that type library or to OLEinterfaces, and which normally uses no other packages. As a result, amethod named delete would be associated with adelete
symbol that was different from the CommonLisp symbol of the same name. SectionSection 2.3 Typelib entity: CoClass will describe thevarious pieces of Lisp linkage machinery constructed to correspond toeach item in the typelib. The following examples are taken fromMicrosoft's Internet Explorer, and assume the following form was used:
The meaning of each argument in this macro form is described below(see ole:def-ole-linkage).
The ole:def-ole-linkage macro expands into aform that defines the Lisp connection to the OCX object. As a result,the compile-time support for ole:def-ole-linkage, which reads andanalyzes the type library, is only needed when the form is compiled orinterpreted. Once a file containing ole:def-ole-linkage forms has beencompiled, the resulting fasl file can be loaded later into a Lispimage that doesn't include the machinery for analyzing typelibs orcompiling interface definitions.
2.3 Typelib entity: CoClass
The objects an application will manipulate are named and defined bythe CoClass entries in the typelib; a typelib may define severalCoClasses or just one. For our example we'll look at this CoClassdefinition:
This object supports two control interfaces and two source (or event)interfaces. The control interfaces are IWebBrowser2 andIWebBrowserApp; the event interfaces are DWebBrowserEvents andDWebBrowserEvents2. The ole:def-ole-linkage form defines a classmsx:InternetExplorer
which inherits from aninternal ole::access-to-ole-control
class, andwhose instances will be the Lisp objects corresponding to the CoClassobjects. An instance can be created like this:
All Lisp classes corresponding to OLE coclasses support theseinitialization arguments to make-instance:
:interface
: can be a symbol naming any controlinterface the CoClass supports (default is the symbol naming thedefault interface for the CoClass) This is the interface that will beacquired when the OCX connection is established.:event-interface
: can be a symbol naming any eventinterface the CoClass supports (default is the symbol naming thedefault source interface for the CoClass) This is the interface thatwill be used when establishing the event channel.:server-context
: can be one of:inproc
or:local
(default is totry:inproc
, then:local
if:inproc
fails) Specifies the type of service torequest from OLE.
Making an instance of a coclass class does not automatically get theOCX object created. That's done by ole:connect-to-server.
Cannot Load The Ole 2.0 Or Doc File Libraries App
The next form will make the connection, once the ocx object has beencreated as above:
This will start a browser running, but it won't be visible becausethis particular browser starts up in hidden mode. It can be madevisible by setting the appropriate property, as described below.
The ole:def-ole-linkage macro creates Lispmethods corresponding to the methods and property functions definedfor the CoClass's interfaces. For each method mmmm orproperty-getter gggg or property-setter ssss ofinterface IIII, ole:def-ole-linkage defines acorresponding method for msx:mmmm, msx:gggg or (setfmsx:ssss). In our example, InternetExplorer objects support bydefault the interface IWebBrowser2, which inherits fromIWebBrowserApp. Whichever interface is used for a particularInternetExplorer instance, all the IWebBrowserApp methods will beavailable. For example, consider these methods from the idl forIWebBrowserApp:
ole:def-ole-linkage generates methods thatlook something like this:
and
that invoke the appropriate OLE methods on obj's IWebBrowserAppinterface.
The defined methods call internal functionsole.control::IWebBrowserApp.Visible, and (setfole.control::IWebBrowserApp.Visible), also defined by the ole:def-ole-linkage form. Theselower-level interface-specific functions use theole.control:IWebBrowserApp function to get the appropriateclient interface. Examples appear below in the section on interfaces.
For each control interface IIII the CoClass supports, ole:def-ole-linkage defines a methodole.control:IIII to return the IIII-client interface for thatobject. If x is an instance of msx:InternetExplorer,(ole.control:IWebBrowserApp x)
will return anIWebBrowserApp-client interface on which low-level method calls can bemade. Since IWebBrowser2 inherits from IWebBrowserApp, the interfacereturned by ole.control:IWebBrowserApp might actually be a morespecific IWebBrowser2 interface, but either works for theIWebBrowserApp methods.
The application code doesn't normally need to use either theole.control:IWebBrowserApp function or the low-level methodcalls because the higher-level functions in the msx package are moreconvenient.
In our example, after connecting the browser object to an external webbrowser, nothing was seen because this particular control starts uphidden. Evaluating (msx:Visible browser)
returnsnil
, and evaluating (setf(msx:Visible browser) t)
makes the browser window visible.(msx:Navigate2 browser 'franz.com')
makes thebrowser object display the Franz home page.
When the typelib defines a method that returns a coclass's controlinterface, the generated Lisp method returns an instance of the Lispobject class whose control interface is the returned value and whoseinterface-type is the corresponding type. This object does not have anevent channel opened automatically. If the application wishes toreceive events for any such object, it needs to explicitly call thefunction ole:connect-event-channel, passing the newobject as the argument.
A technical note important in multiprocessing applications: Thecontrol methods defined in Lisp perform heap-dropping calls. There ismore overhead in a heap-dropping call, but since a method call to avisible control object might result in messages being dispatched towindows owned by other Lisp threads, we have to allow them a chance torun or risk hanging our application.
Besides the interface-specific methods defined formsx:InternetExplorer objects, there are some methods applicable to allinstances of access-to-ole-control subclasses. These include ole:connect-to-server, ole:disconnect, and thesetf-able ole:event-tracing.
If x is an instance of msx:InternetExplorer,(ole:connect-to-server x :inplace nil)
will ask OLEto create a new running instance of an InternetExplorer object. Ifthe attempt is successful then the current dumplisp tick (a value thatrecords how many time an image has been dumplisp'ed since first creation) is recordedin the Lisp object along with connection information. ole:connect-to-server will not try toestablish a new connection if x looks like it is connected and itsdumplisp tick matches the current Lisp dumplisp tick. A liveconnection doesn't survive a dumplisp restore, so this allows applicationinitialization code to call ole:connect-to-server on a set ofinstantiated Lisp objects either before or after a dumplisp.
Because the InternetExplorer CoClass defines an event channel, ole:connect-to-server also tries to createand initialize an event channel for the object. To see unhandledevents being generated by an object x,
This will make each event received on one of x's event channelsproduce a message.
will muffle the event messages for x.
Events can be handled by defining methods for them. Each event namedxxxx
is associated with a generic function named-xxxx (prefix a minus sign to the method name). This genericfunction takes as arguments the object, the channel, and the argumentsdefined in the typelib. For example, this definition in the typelibfor one of DWebBrowser2's events:
says we can define a method like this:
to get our own printout when the event is received.
2.4 Typelib entity: Enum
For each value in an enum, ole:def-ole-linkage generates a correspondingdefconstant form. ole:def-ole-linkage also generates a function toconvert the numeric values into the corresponding symbolic names. TheInternet Explorer type library contains this enum:
The def-ole-interface form produces the correspondingdefinitions:
2.5 Typelib entity: Interface
For each interface defined in a typelib, ole:def-ole-linkagegenerates a corresponding OLE def-ole-interface form and someadditional method definitions at a higher level. The generateddefinitions depend on whether the interface is used by the client tocall methods in the object or by the object to call methods in Lisp.The former we refer to as a control interface, the latter as an eventinterface. The exact definitions are not normally of interest to theapplication programmer, who uses the higher-level functions acting onthe CoClass object.
2.6 OLE/OCX low-level internals discussion
Interfaces
The IWebBrowser2 control interface in the InternetExplorer typeliblooks like this (many methods omitted to condense the example):
These are the corresponding forms generated by ole:def-ole-linkage:
One of the event interfaces in the typelib is this (again edited for aconcise example):
The corresponding definitions from ole:def-ole-linkage are:
2.7 Reference guide to interface operators
def-ole-linkage
Macro
Package: ole
Arguments: package-name &key guid major-version minor-version pathname application
The package-name, a string or symbol, provides the name of the packagein which library-specific symbols will be interned. The package willbe created when the macro is expanded if it does not already exist,and the expansion will include a defpackage form for it. The keywordarguments specify a type library, and have exactly the same meaning asfor the ole:load-typelib function, which is called at macro expansiontime but not by the form the macro expands into.
connect-to-server
Generic Function
Package: ole
Arguments: control-object &key inplace (default t)
The first argument must be an instance of one of the coclass classesdefined by a def-ole-linkage form. This function attempts to form aconnection between the control-object argument and a live OLEobject. If the control-object appears to be serving a live OLE object,nothing else is done. Otherwise OLE is asked to provide a newconnection. If the object class is defined to have an event channel,connect-to-server tries to open it. The inplace argument defaults tot, and must be specified nil for objects not being activated in place.
connect-event-channel
Function
Package: ole
Arguments: control-object &key event-interface-class
The first argument must be an instance of a coclass class defined bydef-ole-linkage. The event-interface-argument, if present, must be asymbol naming one of the legitimate event classes for the coclass, andoverrides the default class defined by the type library. The functionattempts to establish the OLE linkage for the events, so that Lispcode can process the events.
disconnect
Function
Package: ole
Arguments: ocx-object
The argument must be an instance of a coclass class defined bydef-ole-linkage. disconnect releases all the interfaces, includingevent-channel interfaces so that the OLE object and its resources canbe freed.
load-typelib
Function
Package: ole
Arguments: &key guid major-version minor-version pathname application
This function attempts to loacte a type library and read itsdefinitions. The type library can be specified in one of severalways:
- The pathname of a typelibrary file can be given as a string orpathname.
- A guid can be specified as a string or lisp-guid, along with major andminor version numbers, if necessary, to locate a type library known tothe registry
- A string that uniquely specifies an application can be given as theapplication keyword. In this case, if there is just one entry underRKEY-CLASSES-ROOT that contains the given string, ignoring case, andthat entry has an associated typelib, then that's the typelib that isloaded.
Type libraries loaded are cached in the Lisp, and not reloaded ifalready present. The value returned by the function is theinternalized Lisp structure holding the typelib information.
event-tracing
Function
Package: ole
Arguments: object
This function returns non-nil
ifevent-tracing is enabled for object, which mustbe an instance of a lisp coclass class defined by def-ole-linkage.
Event tracing defaults to nil
at objectcreation. A non-nil
value may be set withsetf and this function. Thedefault event-handling method for all objects will print a message on*trace-output*
ifevent-tracing is non-nil
. Any user-definedspecialized methods will shadow the default method, so this can beused to see what events are arriving and not being handled.
format-idl
Function
Package: ole
Arguments: pathname &optional lisp-typelib
You must load the[Allegro-directory]/ole/client/client/idlout.faslfile before using this function. If the current directory is theAllegro directory, this can be done with the form (load'ole/client/idlout')
.
This function writes out an approximation of the idl that generatedthe typelib. The pathname argument, a string or pathname, specifiesthe file to be written. The optional second argument is theinternalized Lisp form of a typelib. If omitted, the last typelibloaded provides the data to be written.
2.8 Index to high-level interface operators
- connect-event-channel (function)
- connect-to-server (generic function)
- def-ole-linkage (macro)
- disconnect(function)
- event-tracing(function)
- format-idl(function)
- load-typelib (function)
3.0 Introduction to the low-level OLE interface
The facility described in this document simplifies OLE programmingwithout imposing any limit on the programmer's access to OLEfunctionality. To a CLOS program, Microsoft's COM/OLE/ActiveXfacilities look like a foreign library consisting of data types, namedAPI entries, and interfaces, the latter being C++-like objects withassociated virtual tables. Allegro's OLE support provides tools fordealing with these foreign entities. Every API point is reachable,every interface can be used. The support also includes a library ofCLOS classes and functions that make it easier to manage anapplication's OLE component in a CLOS development environment. ThisCLOS-OLE layer is not yet complete as we are continuing to extendit. All the most useful OLE capabilities will be as readilyavailable in CLOS as in any other environment, and will benefit fromthe unique dynamic power inherent in CLOS.
This file contains an overview of Allegro CL OLE 's treatment of OLEconcepts. It lays out the overall organization of the Allegro CL OLE toolsand an Allegro CL OLE application. Detailed documentation of each element inthe Allegro CL OLE system appears in the reference document,ole_reference.htm. Look there for information aboutindividual CLOS functions, macros, classes and data types.
3.1 Sample Programs
You will find a set of sample Allegro CL OLE programs to illustrate writingclient and server applications using Allegro CL OLE. Each sample appears in adirectory ole/samples/samplenn, and includes a readme.txt fileexplaining how to compile and run the example.
- sample01. This is a simple automation client.
- sample02. This is a slightly more complex automation client.
- sample03. This is an automation server and its client.
- sample04. This is a self-registering automation server and a VisualBasic client.
- sample05. This is an inproc Lisp automation server being used by aVisual C++ client.
- sample06. This is an inproc Lisp automation server being used by aVisual Basic client.
- sample07. This shows Lisp using the Microsoft Agent control.
- sample08. This shows a CLOS interface to Excel.
3.2 System Structure
3.2.1 Basic Concepts
Basic Unit of OLE | Treatment in Allegro CL OLE |
Data Types | Most of OLE's primitive data structures are defined and manipulated using the Allegro foreign data interface. A few receive special treatment. See the entries for Unicode, GUID's, BSTR's, and Interface Pointers. |
Interface Definition | An OLE Interface definition specifies the methods of an interface, giving their order in the VTBL and the arguments and return-value type for each. An interface is seen from two sides, client and server. On the client side, an interface allows the program to invoke its methods without knowing how they are implemented. The method implementations exist on the server side. Allegro CL OLE provides separate macros to
|
Reference Counting | OLE uses a reference counting scheme to allow it to do garbage collection on OLE resources. Every OLE interface inherits from the IUnknown interface, which provides AddRef and Release methods to record object usage. Allegro CL OLE reflects these OLE methods as the CLOS generic functions add-ref and release . Functions in the Allegro CL OLE subsystem make add-ref and release calls at the appropriate times. Allegro garbage collection finalizations perform a release call on each client-interface object that dies without already having been released. |
Starting an OLE Session | Before using any OLE facilities, an application has to call certain OLE API functions to initialize state. Allegro CL OLE provides start-ole and stop-ole , functions that perform all necessary initialization calls and disconnect from OLE, respectively. |
3.2.2 Important CLOS Issues for an Allegro CL OLE Application
- Classes: Some confusion can arise between CLOS classes and COM/OLE classes. CLOS classes define objects in the Lisp world. Their semantics are specified by the ANSI standard and the application code. COM/OLE classes define objects that are supported by a server application and made available to client applications that may reside in a different address space or on a different machine. Instances of CLOS classes are created by invoking the CLOS
make-instance
function. Instances of COM/OLE classes are created by asking OLE to locate the server and ask it to make an instance. The point of Allegro CL OLE is to provide CLOS classes and functions that let Allegro applications be clients and servers of COM/OLE objects. There will be CLOS objects representing OLE/COM objects and vice versa. It should be clear from context which meaning of 'class' is appropriate each time the word appears.
- Package Structure: The Allegro CL OLE symbols reside in the
ole
package; exported symbols name the documented CLOS functions, macros, constants, classes and foreign data types that Allegro CL OLE supports.Users should not place
(in-package :ole)
forms in their source files. They should either include a(use-package :ole)
form or use explicit qualification on Allegro CL OLE symbols, as in(ole:query-interface foo ole:IID_IUnknown)
.
- Case Conventions: ANSI Common Lisp specifies that when reading symbols, the default action is to convert unescaped lower case letters to upper case; all standard Common Lisp symbols (e.g.,
FORMAT
andDEFUN
) appear in upper case. Allegro CL can operate in this mode (and does so with the executables/images named alisp and alisp8); but Allegro CL also operates in the modern mode, consistent with UNIX and C usage. In the modern mode, used by executables/images named mlisp and mlisp8, symbol names are read without case conversion and all Common Lisp symbols (e.g.,format
anddefun
) appear in lower case.When operating in ANSI mode, symbols in the OLE package, including function, macro and CLOS class names, are all upper case. The case in which they are written in a source file is not significant. Two symbols that differ only in case cannot be used to name separate entities without escaping the lowercase letters. These last two points mean that errors due to inconsistent case usage disappear, but at the same time, the common C convention of using a capitalized symbol for a structure or class name and lower case for an object, as in
Party
andparty
, introduces a naming conflict.When operating in modern mode, Allegro CL allows source files to contain distinct symbols that differ only in the case of individual letters. In this mode, all symbols that represent interfaces, OLE functions and OLE constants appear in Lisp with the same case configuration they have in C, e.g.,
IUnknown
,GetClassObject
,DISP_E_UNKNOWNINTERFACE
. OLE types appear in the same case they have in C unless the C type is all upper case, in which case the Allegro CL OLE type name is all lower case, e.g.pInterface
,bstr
.Important: An Allegro CL OLE application running in ANSI mode must direct the fasl loader to convert mixed-case symbol names to upper case, something the fasl loader does not do by default. The way to specify this directive is by evaluating
(convert-mixed-case-symbols t)
Loading the Allegro CL OLE system into Allegro by evaluating
(require :ole)
or(require :ole-dev)
automatically sets the correct convert-case-mode.An Allegro CL OLE file that has been compiled in modern, case-sensitive-lower mode can be successfully loaded into a Lisp running in ANSI mode, as long as the shift to all upper case doesn't introduce any name clashes. The reverse is not true. An Allegro CL OLE application file compiled in ANSI mode will not successfully load into a modern Lisp, because there is no way to recover the mixture of upper and lower case in symbols such as
IUnknown
. For this reason, it is a good plan to compile Allegro CL OLE applications in modern mode, so the compiled application can be loaded and run by a Lisp running in either mode.Once Allegro CL OLE has been loaded into Lisp, it is likely that subsequently changing the system's case mode will render Allegro CL OLE inoperable. Attempting to call set-case-mode in this environment will raise a continuable error warning the user of the problem. Continuing from this error allows the system to change its case convention despite the danger to OLE.
- Modules The Allegro CL OLE subsystem is partitioned into two major modules and a number of separate minor modules. The major modules are
- ole-dev: Compile-time support. Definitions needed to compile an Allegro CL OLE application file.
- ole: Run-time support. Definitions needed to run an Allegro CL OLE application.
An Allegro CL OLE application file should include the following two forms to take advantage of this separation:
The minor modules include special CLOS classes and functions used to support automation clients and servers, a few other special OLE areas that are not needed in every application, and separate files for each client and server interface. Allegro CL OLE provides three macros to include these modules:
- require-client-interfaces: to note client interfaces used.
- require-server-interfaces: to note server interfaces supported.
- require-modules: to note non-interface modules used.
These macros generate code to load the associated modules when they are needed. The macros
require-server-interfaces
andrequire-client-interfaces
are generated as necessary by Allegro CL OLE macros that refer to interfaces by name, such asdef-ocx-class
, and so are rarely coded explicitly. (The macrodef-ocx-class
defines a CLOS server class that supports a named set of interfaces. It generates the appropriaterequire-server-interfaces
forms, so no explicit requires are needed for those server interface modules.) The most common situation in which these macros must be coded is when a program refers to symbols or classes belonging to an interface that it neither defines itself nor names in some other Allegro CL OLE macro.Programs that define part of an OLE server generally need to use
require-modules
to ensure the presence of the server-support functions. A typical automation server would include the formA server that did not provide an IDispatch interface would not need the
:automation-server
support, and could get by with just the:factory-server
.Currently there are no client-side modules that need to be loaded this way.
Allegro CL OLE includes a library of interface definition modules grouped into three directories
- defifc/... has the interface definitions themselves
- client/... has client-side support modules
- server/... has server-side support modules
The IUnknown interface, for example, has a base definition as .../defifc/iunknown.{cl,fasl}, while the associated client-side definitions appear in .../client/iunknown.{cl,fasl} and the server-side definitions are in .../server/iunknown.{cl,fasl}. The defifc/* files are only needed during compilation of the associated server/* and client/* files. The machinery for defining interfaces generates code to ensure the loading of all interface files on which a given interface or module depends. When an interface module is to be loaded, Allegro CL OLE checks the current directory and the value of
*require-search-list*
.
3.2.3 Special OLE Data Types
Allegro CL OLE gives these OLE data types special treatment.
- Unicode: Many string arguments to OLE functions and interfaces are Unicode strings. Unicode is a 2-byte-per-character encoding for all the world's character sets (used, for example, by Microsoft). When operating in standard Allegro CL (which uses 16 bits per character), Lisp character strings are represented as Unicode strings, so there is no problem in passing Unicode data between Lisp and COM/OLE interfaces.
When operating in an 8-bit Allegro CL, Lisp strings are ASCII. They are translated to UNICODE when passed as COM/OLE arguments or return values, by widening the 8-bit unsigned ASCII codes to 16-bit unsigned UNICODE characters. When converting a UNICODE string for Lisp's use, encountering any non-ASCII character signals an error.
- GUIDs: OLE uses 128-bit keys called GUID's whenever it wants a universal name for something. For example, there is a unique key for each interface type and for each OLE object in the system. OLE defines a standard readable representation for a GUID, based on hexadecimal encoding: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. In Allegro CL OLE we represent a GUID by a lisp-guid structure, whose slots record the standard form of the GUID as well as an instance of the GUID's binary encoding. Incoming guid's are usually translated at the interface so that Lisp functions implementing server code see the lisp-guid structure. This allows eql comparison on guid values, as in case statements and (eql ...) discrimination for generic functions.
- Bstrings: Many OLE functions use BSTR's when passing string arguments. These are Basic-style string data. Allegro CL OLE has a small set of functions that give reasonable access to the OLE-supplied bstring manipulation functions.
- Interface Pointers: In Allegro CL OLE each interface instance (pInterface) appears as a CLOS object. There are two different CLOS interface classes for each OLE interface type, a client-interface class and a server-interface class. See Interfaces and Objects for more details.
3.2.4 Language and Locale
Many OLE API functions use codes to allow localization of labels anduser-readable data. The Allegro CL OLE interface uses two parameters toprovide default values for these codes: ole:*ole-language*
and ole:*ole-locale*
. Currently, these are set to themachine-dependent-default values that are OLE'slowest-common-denominator.
3.2.5 Interfaces and Objects
Allegro CL OLE distinguishes between those interfaces that Lisp implements asa server and those that Lisp uses as a client. CLOS objects representinterfaces, and different CLOS classes exist for the client and serverviews of the same interface. This is important because we often haveto deal with an interface from both sides in the same program. Whiledeveloper-defined interface classes can be given any names, the Allegro CLOLE classes are named using the following convention: Allegro CL OLE supportsOLE interface IAbcde with client-side interfaces of classIAbcde-client and server-side interfaces of classIAbcde-server.
Example: When an Allegro CL OLE application obtains an IUnknown interfacefrom some external object, it will be of typeIUnknown-client
. An Allegro CL OLE server application willgenerate IUnknown-server
objects in response to requestsfor the IUnknown interface.
An OLE object may reveal any number of interfaces to the outsideworld. The interfaces and the object are distinct entities, and in anAllegro CL OLE application these will be represented by instances ofdifferent CLOS classes.
The Allegro CL OLE object on the server side will be an instance of a class thatinherits from the lisp-ole-object
class and from severalmixin classes, one for each OLE Interface the object supports. Thesemixin classes are named by the OLE interface name, e.g.,IClassFactory
or IOleObject
. The objectitself is completely under the server's control; only the interfacesare exported to the rest of the world. As a server, the CLOSapplication must implement the methods of these interfaces.
A developer will often do this by using def-ocx-class
todefine the object class, specifying the interface mixins. Here, forexample, is the definition for Allegro CL OLE's class-factory
class .
Here we are saying that a class-factory has the usual semantics for anOLE object implemented in Lisp, and that it exports two interfaces:IUnknown (supported by default) and IClassFactory. These interfaceshave been defined previously with def-ole-interface and areimplemented by IUnknown-server
andIClassFactory-server
instances, respectively. This classdefinition form arranges that class-factory
objects willrespond to QueryInterface requests for the IUnknown and IClassFactoryinterfaces, constructing and caching each interface the first time itis needed.
3.2.6 The Registry
The registry is where most system information is kept in Windows. Anole server must store information about itself in the registry ifit wants to be invoked automatically or allow certain automationclients (such as Visual Basic) to create its objects. This sectionwill describe the registry and how it is manipulated from Lisp.
The registry is stored as a tree. Each node in the tree is called akey. Each key has a name, a collection of zero or more values, and aset of zero or more child keys. Each value stored in a key is alsonamed (except for one value, which has no name, and is called thedefault value). The name of a registry key must consist of printablecharacters and no spaces.
Manipulating the registry from Lisp consists of first getting apointer to the particular key you want to modify. This is done bystarting with an existing open registry key and traversing down thetree by using the names of successive keys that should befollowed. Since you have to start somewhere in this process youcan use one of the pre-opened registry keys to begin the registryscan. These pre-opened keys are
rkey-classes-root
- opened to HKEY_CLASSES_ROOT, for OLE class informationrkey-current-user
- opened to HKEY_CURRENT_USER, for user profile informationrkey-local-machine
- opened to HKEY_LOCAL_MACHINE, for machine configuration informationrkey-users
- opened to HKEY_USERS, for information about all users
The following functions and macros are provided to open keys and toread and modify the registry. See the reference document fortheir definitions.
open-registry-key
with-open-registry-key
do-registry-subkey-names
do-registry-value-names
registry-value-present-p
registry-value
(setf registry-value)
3.3 Writing an Automation Client
Automation allows one application to communicate with and controlanother. The server application offers a set of objects tocontrol. The client application controls the objects offered by theserver. The server can be a standalone application (often called an'exe' or local server) or it can be a so-called in-proc server, i.e.,one that is implemented in a dll that is loaded into the clientapplication. The client need not know which method is beingused, but it can set limits, refusing to use a local server, forexample.
An automation object has a set of properties and a set ofmethods. Properties can be read or set (although the object server canignore an attempt to set a property the server considersread-only). Methods can be called on an object and a value returnedfrom the method. Properties and methods are named. The name is acase-insensitive string; Allegro CL OLE functions to access them can usestrings or symbols.
A property and a method can have the same name because when that nameis used it is clear from the use whether the property or method isintended.
3.3.1 Dynamic naming
Automation is similar to Lisp itself in that the binding of name toproperty or method is done at runtime. Some automation objects supportearly-binding of names to properties and methods using a typelibrary. The lisp-ole interface does not support this yet.
3.3.2 Unique ids
In order for applications to talk about classes and interfaces and tobe sure that they are talking about the same ones, they useGUIDs. You'll often see a guid written this way
where the x's are hex digits. In Lisp we represent guids as lisp-guidstructures and provide functions for converting between any of thecommon guid representations.
There is a Microsoft program to generate unique ids that areguaranteed to be (almost-but-not-quite certainly) distinct from anyother on Earth for all time. You'll want to use this program if youplan on distributing your automation server. For just experimentingyou can choose any random sequence of digits and chances are it willbe different than anything else on your machine.
3.3.3 Classes
An OLE class describes a collection of objects. Each COM/OLE class hasa unique guid. The class is the key to getting communication startedbetween the client and the server. The client initiates thecommunication by asking for a pointer to a class object's classfactory. Once the class factory is returned, the client can ask thefactory to create one or more automation objects.
3.3.4 The Lisp remote-autotool Class
Allegro CL OLE defines the ole:remote-autotool
class tofacilitate control of automation objects. An instance of ole:remote-autotool
holds the Ole machinerythat communicates with the server application.
3.3.5 Set-up
To establish a connection to an automation object you can use thefunction ask-for-autotool
.
is the form to use if you know the OLE class id. If theapplication that supports the class is registered, you can bypass theclass id and use the registered application name:
If you expect to create more than one instance of the same object typethen it's more efficient to ask for the class factory and then ask thefactory for the specific objects you want to create.
If xdi
is an IDispatch-client
interface for an object that supports automation, you can build anautotool object for it like this:
Whichever route you take to acquire theremote-autotool
instance, you can then use thefunctions auto-getf
, (setfauto-getf)
, and auto-method
to readproperties, set properties, and call functions on the automationobject.
For example,
will ask for the value of the x property of the automation object.
will set the x property value to 555.
will call the foob
method on theautomation object, passing in two extra arguments, 3 and 4.
When you've completed using the remote object do (ole:releaseautoinstance) to free it on the server side. After the call toole:release, don't use the autoinstance object again since it nolonger refers to an object on the server.
3.4 Writing a Server
Writing an automation server is simplified by using the Allegro CL OLEautomation and factory interfaces. See ole/samples/sample04/server.clfor an example.
Suppose you, a Lisp programmer, have some functionality you want tooffer to clients via OLE/COM.
First figure out which interfaces you want to support in thisobject. You don't have to declare them all immediately, you can addmore later on. You must support IUnknown at least. Each interface mustbe defined in your application. Many interfaces are alreadydefined. Check the ole/defifc directory to see which. If there isalready a definition, you probably want to use it. If the interfacedoesn't appear in ole/defifc, then you will need to provide adefinition using def-ole-interface
anddef-server-interface
. You can put the definitions inyour application source code if the interface is unique to thatapplication. Alternatively, you can add it to the Allegro CL OLE library ifyou expect to use it in more than one application.
Next you define a CLOS class whose instances will represent objectsallocated on behalf of the client. This CLOS class should be definedwith def-ocx-class
or be a subclass of such a class. Thedef-ocx-class
form will name each interface that thisobject will export to clients, except possibly IUnknown, which getsput in automatically if you don't name it. The interface names aresymbols like IStorage
, IOleObject
,etc. Example:
Put in all the interfaces you want to support after the :interfaceskeyword. If you want to support two different interfaces with the sameinterface object, where one is based on the other, include a list ofthe related interfaces as one of the entries after the :interfaceskeyword, as in
Here, a request for either IViewObject or IViewObject2 will besatisfied with the same object, which will be of typeIViewObject2-server. The last named interface in a set is the one thatis used for any of them.
With the CLOS class my-class
defined you must now makesure that the methods for each exported interface are defined overthis type of data object. Suppose your class supports the IFoointerface, an interface that has four methods: the three fromIUnknown, plus the method 'addem' that adds its two integer argumentstogether and returns an integer result. The interface definition mightlook like this:
When a client allocates an object of your class and gets a pointerto the IFoo interface and then calls addem, control will eventuallyreach your server. When that happens, the generic functionaddem
will be called with three arguments: the firstargument is the CLOS object of your class that the client has remotelyallocated, and the other two arguments are the integers to add. Youcould thus write your server method in this way:
Cannot Load The Ole 2.0 Or Doc File Libraries Free
In this particular case, as in most cases, the function of the addemmethod in the IFoo interface doesn't depend on the object itself, sowe might just want to write that method for all classes that exportthat interface:
this works because all classes that export the IFoo interface are asubclass of IFoo. Or we could write it for the interface objectitself and not bother to look for an object-specific function.
Allegro CL OLE uses this ability to write methods over an interface todefine the three methods inherited from IUnknown: add-ref, release,and query-interface. Thus the server class writer generally doesn'thave to worry about writing these methods. (And in fact, should notreplace the primary methods, ever. :before, :after, and :aroundmethods are OK.)
3.5 Defining Interfaces
The def-ole-interface
macro defines each interface. Withit you name the interface (without the '-server' or'-client' as that is added bydef-server-interface
anddef-client-interface
). The def-ole-interface
macro allows you to specify the IID and the methods for the interface,possibly specifying a base interface to inherit methods from. You listthe methods by name and give an argument map (name and type) for eachargument of each method. The macro expands into code that creates astructure containing all this information. The argument-typeencoding is the one used by ff:def-foreign-type. An older form,approximating what appears in the C header files, is also accepted,but is deprecated.
With def-server-interface
you specify the interfaceyou're generating linkage code for, as in
The result is to define two classes: IFoo-server
is theserver interface class. IFoo
is the mixin class for allobjects that support the IFoo interface.
It may be confusing to have two classes representing an interface onthe server side: IFoo-server
andIFoo
. The difference between the classes is this:Instances of IFoo-server
are interface objects,which have relatively simple and unchanging functionality. Thesemethods are called first when a client call comes in so you might wantto write methods that do argument transformation before passing thecall to the object-specific code.
An object could reasonably be both IViewObject
andIOleObject
. That would mean that it made bothtypes of interfaces available to clients and responded appropriatelyto methods on either interface. However, anIOleObject-server
object is definitely notan IViewObject-server
object. They have completelydifferent virtual function tables attached to their proxies. (Avirtual function table, or vtable or Vtbl, is aC++ object (C++ is typically used to implement OLE) which is a tablewhich associates functions with objects, allowing for method-likefunctionality.)
Thus if you want to write methods over your server objects that dependon them having an IFoo interface, then you write those methods overIFoo. As an example, the IUnknown reference counting methods would bebest written over IUnknown
, since all objects thatsupport an IUnknown interface will inherit fromIUnknown
.
3.6 Low Level View
3.6.1 Class Hierarchies
The mixin class hierarchy for the IUnknown
interface:
The mixin class hierarchy for a random IFoo
interface:
The server class hierarchy for a random interfaceIFoo
is
The application class hierarchy for a random classmy-class
supporting the IUnknown
and IFoo
interfaces is
3.6.2 Control Flow
Now we'll look at what happens when you define a class like
In this case my-class
inherits from IFoo
explicitly and from lisp-ole-object
andIUnknown
implicitly. The lisp-ole-object
class contributes two instance slots:
The ref-count
is used to count the number of users ofthis object; we don't track uses by each interface separately. Theinterfaces
slot holds data that controls the allocationand caching of the interface objects for this instance ofmy-class
. The data is built and stored in this slotautomatically through some :around method magic; newly allocatedinterface objects are cached for later reuse.
When an instance of my-class
is polled withQueryInterface, an interface object is either found or is built andcached. Each interface object has two slots
owner
handle
The owner
slot points to the instance ofmy-class
that has this interface object on itsinterfaces list. The handle
slot points to a proxyobject. A proxy object is a :c foreign array made to look like a C++(COM/OLE) object whose first slot points to a vtbl of functions forthis interface. This proxy object is created when first needed. Thesecond slot of the proxy contains information that helps us quicklyfind the associated Lisp interface object when a method call comes infrom the outside world.
Here is how it all works: When a client makes a call on an interfacemethod, and control reaches the Lisp server, Lisp is passed theaddress of the proxy object as the first argument (this is the C++'this' pointer). Lisp then can use some internal machinery to locatethe interface object, and calls the generic function associated withthat method, usually a function with the same name as the OLEinterface method. The generic function's arguments are the instance ofthe interface object associated with the proxy object, and the rest ofthe method arguments. If the interface was created in the usual way(with def-server-interface
), then a method was automaticallywritten that specializes on the first argument being an instance ofthis interface, and that method calls the same generic function, thistime with the first argument being the instance of my-class
found in the interface object's owner
slot.
Here's an example using our IFoo interface with its addem(int x, inty) function. When the client calls lpFoo->DoSomething (3, 4)control reaches our (automatically generated) defun-c-callablefunction
this function finds the interface object, an IFoo-server, from theproxy_address and calls the addem generic function:
This in turn invokes the specialized method
which is automatically defined to do (slot-value obj 'owner) to findthe instance with this interface and call the generic function
This selects the specialized method
That method, defined explicitly in the application code, computes andreturns a value, which is then returned to the client.
You may receive an OLE error when opening Word and Excel documents that contain embedded objects.
The error may read: Microsoft Excel (or Word) is waiting for another application to complete an OLE action.
This message may occur for different reasons. It is important to determine the cause of the error.
Verify:
- You have Microsoft Office 32-bit is installed.
- The Excel or Word document that contains embedded objects.
- A session of Excel.exe is opened.
- Office 2010 or higher is installed.
- Checkpoints Tool Framework v. 1.0.140 or higher is installed.
If you answered Yes to the above items, this could be due to a change Microsoft made within the Office suite. An update to the Checkpoint Tools Framework v. 1.1.11 includes an update for Microsoft integration that addresses this error. Ensure that current service packs and hot fixes are applied to your operating system and Microsoft Office, proper settings for trusted sites used, and add-ins enabled. For more information, refer to FAQs at http://support.rg.thomsonreuters.com/toolsppc.asp.
For further assistance with this process, contact PPC Technical Support at 800-431-9025.
Note: Other 3rd party vendors who also have .NET Office add-ins may also experience the same issue, and you may continue to see the issue even after updating to the new framework version.
The 32-bit version of Microsoft Office is required to take advantage of integration with Office applications. To learn more about 64-bit or 32-bit versions of office visit, Choose between the 64-bit or 32-bit version of Office (What's this?)
Was this article helpful?
Great! Can you tell us why? (optional)
Microsoft Word Cannot Load The Ole 2.0 Or Doc File Libraries Mac
We're sorry. Can you tell us why? (optional)