Windows Script Components |
Windows Script Components (WSC), formerly known as Scriplets, is a technology
for developing powerful COM components in an easy fashion. WSC's can be authored
in any scripting language that has implemented the ActiveX Scripting Interfaces,
which means that units of PerlScript code can be encapsulated as Windows Script
Components.
Be warned, reader, a lengthy introduction to the Component Object Model (COM)
stretches until the topic of Windows Script Components. Please move directly
to the topic of Windows Script Components if you feel that you understand the
COM; the COM is essential to WSC, thus it is necessary to cover the fundamentals
of the COM.
The Component Object Model (COM) is a language-independent and object-oriented programming model.
It is not, however, a programming language, and it does not demand that a new style of programming
be learned. It is a binary standard that enables software to be implemented as units called
components. The component can be authored in any programming language or scripting language provided
that the language supports the standard defined by the COM. After the binary unit has been built, it
can communicate with other units that were produced in any other language, on the same machine or on
remote machines provided that the units were written as COM components.
As many see it, the Component Object Model is elegant and powerful. The basic yet ingenious
programming model provides the foundation for application-development. The power resides in that
everything built on the same foundation can communicate with each other without any restrictions
such as programming languages or platforms. When developing an application devoted to COM,
components should encapsulate every functionality that the application requires. A task performed by
the application would be executed by a component, and these components would be reused in other and
future applications. For example, a Perl-component can contain the process of sending an email or
performing a series of regular expressions on text. The component can then be used to provide
functionality for an Active Server Pages application or a Windows desktop application.
In summary, although the language in which a component is generated may vary from component to
component, a binary standard overcomes the limitation of programming in different languages. It does
not care about anything else but the binary form of the machine code that the once source code was
turned into and the fact that is implemented into COM. In this sense, the component is not a regular
script or executable, but a black box that performs one task and returns the projected result.
Multiple languages can be used for one application because COM provides a binary standard. A binary
standard also results in platform-independence provided that multiple platforms support COM. Units
of code that are used in COM are known as components, and on Windows a component is normally file
with the extension .dll; however, there are offshoots such as Windows Script Components, which have
the extension .wsc. The purpose of the component is to perform the one task that it has been
programmed for, and through COM, it can communicate with other components, languages, and platforms.
COM is both a specification and an implementation. And being both a specification
and an implementation, the COM defines a standard for how the components are
created and how they communicate namely as objects. As a result, the specification
solves the implementation issues of the following key issues:
When wondering what makes up a component, recall that COM is an object-oriented programming model
that requires every component to be implemented as an object, so from this we know that we will be
talking about classes, methods, properties, and such entities that belong in an object-oriented
programming model. However, let痴 start at the bottom level and move our way up from interfaces,
to classes, and to objects.
VT_EMPTY | No Value |
VT_NULL | Null Value |
VT_I2 | 2-byte integer |
VT_I4 | 4-byte integer |
VT_R4 | 4-byte real value |
VT_R8 | 8-byte real value |
VT_CY | Currency |
VT_DATE | Date |
VT_BSTR | Binary string |
VT_DISPATCH | Automation object |
VT_ERROR | Error code |
VT_BOOL | Boolean value |
VT_VARIANT | Variant |
VT_UNKNOWN | IUknown Pointer |
VT_UI1 | Unsigned 1-byte character |
VT_BYREF | Describes the data as passed by reference |
VT_ARRAY | An OLE Safearray |
<?xml version="1.0"?> <component> <registration description="Easy" progid="Easy.WSC" version="1.00" classid="{74bb1ba9-2e69-4ad6-b02c-c52f3cbe153b}" > </registration> <public> <method name="SayHello"> </method> </public> <script language="PerlScript">As seen above, you have a Window Script Component that is an XML file. The first declaration of the WSC enables strict XML. In that mode, the elements and attributes are case-sensitive, and attribute values must be enclosed within single quotes or double quotes. You may omit the XML declaration on top of the document and it will not be compiled as strictly, but in these examples, we will stick with XML conformity and leave the declaration in each document. To note about XML elements is that they, like HTML, have end-tags like "<registration>" and "</registration>"; however, as you will see, you can replace the end-tag in some operations by simply writing "<registration/>".
<![CDATA[ ]]> </script> </component>
Secondly, you have a component element. This element is used to enclose each component. You will place one at the beginning, and one at the end. As an exception to the rule, there is an element that has a higher priority than the component, and that element must be used whenever you keep more than one component in your WSC file. Is is the package element. It will as a single element enclose all components; however, as mentioned, it is not required when you have one component within the file.
Next, the registration element contains the information about your component such as the progid, classid, description, and version number. Description is a string in which you can write a short abstract summary the funcitonality of your component. The progid is used by the program which creates an instance of your component, and the version number should be incremented if you release a new version of your component. The version number can also be appeneded to the progid as as Easy.WSC.1.00 when creating the instance of your component.
After the registration element, the data and functionality that the component expose are defined. The public element will hold properties, methods, and events. We declare a method by the name "SayHello" and then skip on down to the script-elements. As you can tell, there is no source code, so we need to fill that out. In the empty space, enter the following:
sub SayHello { my($param) = shift @_; return reverse($param); }
<script language="PerlScript"> <![CDATA[ sub SayHello { my($param) = shift @_; return reverse($param); } ]]> </script>
Now, it's time to register the component on the system so that it can be used. There are two ways to do this and we assume that the file is saved as c:\easy.wsc.
<%@Language=PerlScript%> <% $obj = $Server->CreateObject('Easy.WSC'); $retval = $obj->SayHello("Hello World"); $Response->Write($retval); %>
<?xml version="1.0"?> <component> <registration description="First" progid="First.WSC" version="1.00" classid="{d0ccb637-bd0c-4c90-a4bd-7473f499d35a}" > <comment> This makes the messagebox pop up on registration and unregistation </comment> <script language="PerlScript"> <![CDATA[ sub register { use Win32; Win32::MsgBox('Windows Script Component says: First.WSC has been registered!'); } sub unregister { use Win32; Win32::MsgBox('Windows Script Component says: First.WSC has been unregistered!'); } ]]> </script> </registration> <comment> The methods and properties to expose to the data consumer </comment> <public> <property name="YourName"> <get internalName="hiddenGetProperty"/> <put internalName="hiddenSetProperty"/> </property> <method name="SayHello"> </method> </public> <comment> The code that implements the functionality of the component </comment> <script language="PerlScript"> <![CDATA[ use vars qw($YourName_Property); sub hiddenGetProperty { return $YourName_Property; } sub hiddenSetProperty { my($param) = shift; $YourName_Property = $param; } sub SayHello { return "Hello $YourName_Property!"; } ]]> </script> </component>
<component> . . . </component>
<? component error="true" debug="true" ?>
In case your file will contain more than one component, you use a &component id=componentID>
element for each, and you are required to then enclose all components within a <package>
element.
<package> <component id="ComponentA"> . . . </component> <component id="ComponentB"> . . . </component> </package>
createComponent(componentID)
function.<registration>
contains the necessary information in order
to successfully register the component as a COM component, and it has two ways
of writing. Syntax: <registration progid="progID" classid="GUID" description="description" version="version" [remotable=remoteFlag] />or
<registration progid="progID" classid="GUID" description="description" version="version" [remotable=remoteFlag] > <script> (registration and unregistration script) </script> </registration>
<public> <property name="myProperty"/> <method name="myMethod"/> <event name="myEvent"/> </public>
<property name="myProperty" [internalName="propertyScalarVariable"]
/>
<property name="myProperty" get="getSubroutineNamet"
put="putSubroutineName"/>
<property name="myProperty">
<get [internalName="getSubroutineName"] />
<put [internalName="putSubroutineName"] />
</property>
<method name="methodName" internalName="subroutineName"
dispid=dispatchID />
<method
name="methodName"
internalName="subroutineName"
dispid=dispatchID
>
[<parameter name="param"/>]
</method>
<parameter name="param"/>
<event name="name" dispid=dispatchID/>
fireEvent(eventname);
method to execute an event.<implements
type="COMHandlerName"
[id="internalName"]
[default=fAssumed]
>
Information related to the COMHandler goes here
</implements>
<component>
<registration progid="SimpleASP.WSC"/>
<public>
<method name="TestWrite"/>
</public>
<implements type="ASP"/>
<script language="PerlScript">
<![CDATA[
sub TestWrite {
Response.Write("Hello World, says ASP!")
}
]]>
</script>
</component>
<script language="languageName"> code </script>
<?XML version="1.0"?>
<component>
...
<script language="PerlScriptt">
<![CDATA[
sub ReturnValue {
#
# Perl code here
#
}
]]>
</script>
</component>
<object id="objectID"
[classid="classid:GUID" | progid="progID"]
/>
The objectID is the name by which you want to reference the object within your
script, and you can use either the progID or classID to locate the component.
For example, how to create an instance using the COM components progID:
<?XML version="1.0"?>
<component>
<object id="conn" progid="ADODB.Connection.2.5">
<script language="PerlScript">
<![CDATA[
sub OpenConn {
my($status);
$conn->Open(<<EOF);
Provider=SQLOLEDB;
Persist Security Info=False;
User ID=sa;
Initial Catalog=Northwind
EOF
if($conn->{State} == adStateOpen) {
$status = "Connection was a success";
}
else {
$status = "Connection failed because ";
$status .= $conn->Errors(0)->{Description};
}
$conn->Close();
return $status;
}
]]>
</script>
</component>
<resource id="resourceID">
text or number to represent resource goes here
</resource>
You use the getResource(resourceID)
to retrieve the contents of the
resource specified in the resourceID parameter.<reference
[object="progID"|guid="typelibGUID"]
[version="versionNo"]
/>
For example, you can use an ActiveX Data Object within your component.
<?XML version="1.0"?>
<component>
<reference object="ADODB.Connection.2.5"/>
<registration progid="SimpleADO.WSC"/>
<public>
<method name="OpenConn"/>
</public>
<script language="PerlScript">
<![CDATA[
sub OpenConn {
my($status);
$conn = new Win32::OLE("ADODB.Connection");
$conn->Open(<<EOF);
Provider=SQLOLEDB;
Persist Security Info=False;
User ID=sa;
Initial Catalog=Northwind
EOF
if($conn->{State} == adStateOpen) {
$status = "Connection was a success";
}
else {
$status = "Connection failed because ";
$status .= $conn->Errors(0)->{Description};
}
$conn->Close();
return $status;
}
]]>
</script>
</component>
<comment>
Author: John Doe
Description: This WSC component is used to output a Binary Large Object (BLOB) from an SQL Server database . . .
</comment>
Copyright (c) 2000 Tobias Martinsson. All Rights Reserved.
When included as part of the Standard Version of Perl, or as part of its complete documentation whether printed or otherwise, this work may be distributed only under the terms of Perl's Artistic License. Any distribution of this file or derivatives thereof outside of that package require that special arrangements be made with copyright holder.
Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required.
Windows Script Components is copyright (c) 1991-1999 Microsoft Corporation. All rights reserved.
Windows Script Components |