OLE Extensions for Windows NT Perl 5
SYNOPSIS
Perhaps the most prominent new feature of Perl 5 is its object-oriented
programming. This, coupled with the powerful capabilities of OLE 2.0
Automation in Windows NT, enables the average Perl hacker to peform
complex tasks using a mere few lines of code.
The Perl OLE interface is quite simple, allowing one to interact with
OLE Automation objects via Perl objects. Using MkOLEx, a
provided utility, one can build Perl module extensions for OLE
Automation objects. Once a module for a particular class has been
created, one can simply load the module with the "require"
(or "use") function, and can then create objects and invoke
methods in the usual Perl object-oriented fashion. All supported
methods that the OLE object possess are defined within the Perl
object, and methods are provided for retrieving/modifying instance
variables.
If the interface for the OLE Automation object is not registered, then
one must use the OLE interaction
routines in order to manipulate the OLE Automation object. These
objects are usually obtained from registered objects, for example a
chart object within the Excel.Application object.
MkOLEx
MkOLEx (Make OLE Extensions) is a Perl script that creates Perl
object-oriented extensions from OLE Automation objects. If supplied with
the name of an object class, MkOLEx creates the object and enumerates all
variables and member functions of that object. If supplied with the
name of a type library file, MkOLEx queries the type library and
enumerates all variables and functions under the CoClass type
description. Note that MkOLEx does not create Perl extensions for OLE
Automation objects embedded within other objects. One must manipulate
these objects directly using the low-level
routines described in the next section.
Usage:
MkOLEx -h Get this help message
MkOLEx <typelib file> [ <typelib file> ... ]
Generate perl OLE objects from type libraries
MkOLEx <class name> [ <class name> ... ]
Generate perl OLE objects from object classes
Examples provided here are based on the DispCalc Display
Calculator application, supplied with Visual C++ 2.x Resource Kit.
DispCalc is a simple accumulator-based arithmetic calculator.
Using MkOLEx
As an example, to create a Perl module from the application class
"DspCalc2.Application.1", type the following:
> MkOLEx DspCalc2.Application.1
To create the Perl module from Disp Calc's type library, type the
following:
> MkOLEx filepath/dspcalc2.tlb
where filepath
is the path to the type library file.
If the supplied arguments are valid, MkOLEx will query the
object/library and enumerate all member functions and variables.
Unfortunately, Windows NT Perl 5 does not support all OLE Automation
data types. Functions or variables that rely on these unsupported
data types will be discarded. Consult the file "NT.ph" in the perl
library to determine which data types are supported and which aren't.
MkOLEx allows only word and numeric characters in OLE module names, and
will replace all other characters ([^\w\d]) with an underscore. Once an
object class has been enumerated, MkOLEx creates a module in the
"OLE" subdirectory of the Perl library directory, naming both
the module file and the Perl package as the object class name. For
example, our Display Calculator module will be named
$perldir/lib/OLE/Dspcalc2_Application_1.pm
, and the
contents of that file will resemble something like this:
#
# Auto-generated OLE Automation module
#
# OLE object type : Dspcalc2_Application_1
#
# Edit at your own risk!!
#
package OLE::Dspcalc2_Application_1;
sub CreateObject {
my $hObject;
main::NTOLECreateObject( 'Dspcalc2.Application.1', $hObject )
|| return undef;
my $self = {};
$self->{ 'hObject' } = $hObject
|| return undef;
bless $self;
}
[...et cetera ad infinitum ad nauseam...]
In addition, MkOLEx will generate an HTML document that lists all
member variables and methods in an klingon-readable form. The file is
saved under the same name as the module file is (but with an
"htm" extension, naturally) and placed in the directory where
the other Perl documentation resides. A hypertext link to that document
will automatically be inserted onto this page.
Using extensions created by MkOLEx
The first thing to do when using an OLE object is to load its
corresponding module file. For example
require OLE::Dspcalc2_Application_1
will load and compile the module file
$perldir/lib/OLE/Dspcalc2_Application.pm
. We then
create the Display Calculator object with the CreateObject
method, which is the standard constructor for all OLE objects created
by MkOLEx.
$expensive_paperweight = CreateObject OLE::Dspcalc2_Application_1
Methods can now be called from the object like any other Perl object.
The following code depresses the "1" button on our glorified
silicon abacus:
$expensive_paperweight->Button( 1 );
Finally, we destroy the object using the standard destructor
"DestroyObject".
$expensive_paperweight->DestroyObject();
As a side note, Windows NT Perl will automatically clean up all OLE
objects it created on exit, one doesn't have to explicitly destroy
every single object. However, if Perl chokes midway
through execution, OLE objects it has created will not
be mopped up and will be left floating around the system, eating up
resources like little sharks in a goldfish bowl.
The following sample script will direct Display Calculator to peform the
amazing feat of single digit multiplication.
require OLE::Dspcalc2_Application_1;
$expensive_paperweight = CreateObject OLE::Dspcalc2_Application_1;
$expensive_paperweight->Button( 'c' );
$expensive_paperweight->Button( '8' );
$expensive_paperweight->Button( '*' );
$expensive_paperweight->Button( '5' );
$expensive_paperweight->Button( '=' );
$expensive_paperweight->Quit;
$expensive_paperweight->DestroyObject;
If all goes well, the final result displayed should be "40".
CAUTION!
Windows NT isn't case sensitive, whereas Perl
is (rightly so!). This becomes a problem when the user
supplies an object class as an argument to MkOLEx. For example, the proper
classname for the Display Calculator application is
"Dspcalc2.Application.1", but typing
> MkOLEx dspcalc2.application.1
generates the module OLE::dspcalc2_application_1,
not OLE::Dspcalc2_Application_1. When the time comes
for a user to actually "require" the modules, the differences in
case will undoubtedly become a major source of irritation and confusion.
The following Perl code
require OLE::Dspcalc2_Application_1
will fail. One need not worry about this when a module is generated
from a type library, since the object class name is automagically
extracted from the type library.
OLE Interact routines
The following routines interact directly with OLE objects. If an
interface to an OLE Automation object is not registered in the Windows
Registry (e.g. for embedded objects), then one will have to use these
low-level routines to manipulate the object. One should have a solid
understanding of OLE programming concepts before attempting to use
these routines.
Assuming the user knows what methods and variables exist, it
is still possible to invoke these methods and retrieve/modify these
variables. Having retrieved an object from a registered object using
one of its methods or properties, it is good practise to ensure it has
an IDispatch interface by using the NTOLEIsDispatch function. Then one
retrieves the function DISPID / variable member ID using
NTOLEGetIDofName, and generates a magic string using
NTOLECreateMagicString if necessary. One can then use NTOLEPropertyGet
/ NTOLEPropertySet or NTOLEMethod in order to manipulate the object.
All functions return true on success and false on failure.
- NTOLEIsDispatch HOBJECT
-
Given the handle HOBJECT of an ITypeLib object, returns true if in fact this
object has an IDispatch interface attached to it.
- NTOLEGetIDofName HOBJECT, MEMBERNAME, MEMBERID
-
Given the handle HOBJECT of an object created by NTOLECreateObject or
returned by an OLE Automation object, returns the DISPID of the
function or the MEMBERID of the variable named by MEMBERNAME.
- NTOLECreateMagicString STRING, TYPE1, TYPE2, ... , TYPEN
-
Creates a magic string returned in STRING, given valid OLE Automation variable
types TYPE1 to TYPEN, as listed in NT.ph. This is supplied as the
FUNCMAGIC for NTOLEMethod.
- NTOLEPropertyGet HOBJECT, VARMEMBERID, VARTYPE,
VARRETURN
-
Given the handle HOBJECT, retrieves the variable identified by
VARMEMBERID, returning its type in VARTYPE and its value in
VARRETURN.
- NTOLEPropertyPut HOBJECT, VARMEMBERID, VARTYPE,
VARVALUE
-
Given the handle HOBJECT,
sets the value of the variable identified by VARMEMBERID to be
VARVALUE. VARTYPE must match the type of the variable for a call to
this function to succeed.
- NTOLEMethod HOBJECT, FUNCMAGIC, FUNCDISPID, FUNCRETURN,
@PARAMS
-
Given the handle HOBJECT,
invokes the method identified by FUNCDISPID. The supplied FUNCMAGIC
parameter must correctly identify the types of parameters that the
method accepts, and parameters are supplied in the @PARAMS array. The return
value of the function is placed in FUNCRETURN.
Using the following routines, one can query type libraries for
objects, create objects, enumerate methods and variables, and of
course invoke any methods an object posseses. These routines are used
by MkOLEx to build the Perl object interfaces to the OLE
objects. Warning: the routines are not for the faint
of heart, you should have a solid understanding of OLE programming
before attempting to use these functions.
- NTOLECreateTypeLib FILENAME, HOBJECT, COUNT
- Given the FILENAME of a type library, creates an ITypeLib object
and stores its handle in HOBJECT, and retrieves the number of type
descriptions and stores that in COUNT.
- NTOLETypeLibTypeKind HOBJECT, TYPEINDEX, TYPEKIND
- Queries the ITypeLib interface of the given object, and returns the
TYPEKIND for the type description indexed by TYPEINDEX.
- NTOLETypeLibGetTypeInfo HOBJECT, TYPEINDEX, FUNCCOUNT,
VARCOUNT
-
Returns the function count FUNCCOUNT and variable count VARCOUNT for
the TYPEINDEX of the ITypeLib object.
- NTOLETypeLibGetDispatchIndex HOBJECT, INDEX, DISPSTRING, FUNCCOUNT,
VARCOUNT
-
Given the handle HOBJECT of an ITypeLib object, searches for the CoClass
indexed by INDEX, and returns the object classname in DISPSTRING, with
the function count in FUNCCOUNT and the variable count in VARCOUNT. One
can now use HOBJECT for typelib queries using NTOLETypeInfoVar,
NTOLETypeInfoFunc and NTOLETypeInfoFuncInfo. This functions does more or
less what NTOLETypeInfo does.
- NTOLETypeLibGetDispatchCount HOBJECT, INFOCOUNT
-
Given the handle HOBJECT of an ITypeLib object, places the number of items in
that object in INFOCOUNT.
- NTOLECreateObject CLASS, HOBJECT
-
Given an object CLASS string, creates the object and returns its handle
in HOBJECT. The object may now be queried using NTOLETypeInfo,
NTOLETypeInfoVar, NTOLETypeInfoFunc, NTOLETypeInfoFuncInfo. Methods
may now be invoked using NTOLEMethod, and variables can be
retrieved/modified using NTOLEPropertyGet/NTOLEPropertyPut.
- NTOLEDestryObject HOBJECT
-
Destroys the object whose handle is HOBJECT. Once the object is
destroyed, the handle HOBJECT should not be used again.
- NTOLETypeInfo HOBJECT, FUNCCOUNT, VARCOUNT
-
Given the handle HOBJECT of an object created by NTOLECreateObject,
returns FUNCCOUNT, the number of functions; and VARCOUNT, the number of
variables; that the object possesses.
- NTOLETypeInfoVar HOBJECT, VARINDEX, VARNAME, VARMEMBERID,
VARTYPE, DUMMY, DUMMY, DUMMY
-
Given the handle HOBJECT of an object created by NTOLECreateObject,
returns information regarding the variable indexed by VARINDEX
including VARNAME, the variable name, VARMEMBERID, a magical
identifier, and VARTYPE, the variable type.
In order to enumerate the variables of an object, one usually starts
with VARINDEX being 0, and incremementing VARINDEX with each subsequent
call to NTOLETypeInfoVar until VARINDEX exceeds VARCOUNT. Alternately,
one could start at VARCOUNT and decrement until VARINDEX is 0.
VARMEMBERID uniquely identifies each variable that an object has, and
must be supplied for calls to NTOLEPropertyGet and NTOLEPropertyPut.
OLE Automation data types are defined in the file "NT.ph", this
file must be "required" for contained definitions to be
loaded. Not all data types are supported by Windows NT Perl 5, consult
"NT.ph" to determine which types are supported and which aren't.
DUMMY variables must be supplied, their use will be documented in the
next source. If you're brave enough, browsing through the source code will
give you an idea what extra functionality is provided. Be warned: these
features are completely untested!
- NTOLETypeInfoFunc HOBJECT, FUNCINDEX, FUNCNAME, FUNCDISPID,
FUNCRETURNTYPE, PARACOUNT, FUNCMAGIC, DUMMY, DUMMY, DUMMY
-
Given the handle HOBJECT of an object created by NTOLECreateObject,
returns information regarding the function indexed by FUNCINDEX
including FUNCNAME, the name of the function; FUNCDISPID, a magical
identifier; FUNCRETURNTYPE, the function return type; PARACOUNT, the
number of parameters the function requires; and FUNCMAGIC, a coded
string that identifies the parameter types.
In order to enumerate the functions of an object, one usually starts
with FUNCINDEX being 0, and incremementing FUNCINDEX with each subsequent
call to NTOLETypeInfoVar until FUNCINDEX exceeds FUNCCOUNT. Alternately,
one could start at FUNCCOUNT and decrement until FUNCINDEX is 0.
FUNCDISPID and FUNCMAGIC uniquely identify the function and its
parameters respectively, and both must be supplied for calls to NTOLEMethod.
OLE Automation data types are defined in the file "NT.ph", this
file must be "required" for contained definitions to be
loaded. Not all data types are supported by Windows NT Perl 5, consult
"NT.ph" to determine which types are supported and which aren't.
DUMMY variables must be supplied, their use will be documented in the
next source. If you're brave enough, browsing through the source code will
give you an idea what extra functionality is provided. Be warned: these
features are completely untested!
- NTOLETypeInfoFuncInfo HOBJECT, FUNCINDEX, PARAINDEX,
PARANAME, PARATYPE
-
Given the handle HOBJECT of an object created by NTOLECreateObject, the
index of a function FUNCINDEX and the index of a parameter of that
function PARAINDEX, returns the parameter name PARANAME and parameter
type PARATYPE.
OLE Automation data types are defined in the file "NT.ph", this
file must be "required" for contained definitions to be
loaded. Not all data types are supported by Windows NT Perl 5, consult
"NT.ph" to determine which types are supported and which aren't.