| << 16.2.0- Writing Our Own Components | Chapter16 | 16.3.0- Components and Data Access >> |
Using Windows Script Components
In order to build components using WSC, you'll need the WSC wizard. The wizard takes care of setting up the framework of the component. We'll use this in our examples in this chapter, but first you need to download the wizard from Microsoft's web site . This comes in a single executable file called wz10en.exe.
Download this file to a location on your hard disk; when the download is complete, execute the file to install the wizard. When you've done that, you're ready to go!
The Basic WSC Elements
There are three basic elements to a WSC: the XML framework, the script itself, and a runtime DLL called scrobj.dll. Let's take a quick look at these three elements, and then we'll get our teeth into an example.
The Extensible Markup Language (XML) Framework
When we use the WSC wizard to create a component, it generates a .wsc file that contains a framework for the component. Then, we add our own script to this framework, which defines the functionality of the component.
As it happens, the framework is written in a language called Extensible Markup Language (XML), which we'll learn more about in Chapter 18 . For now, it's enough to know that XML uses tags (similar to HTML tags) to label different parts of the code. In our WSC files, we'll meet five different tags that are used to label five different parts of the code:
|
XML Tags in a .wsc file |
Description |
|
<component> … </component> |
Contains the entire component definition |
|
<registration> … </registration> |
Contains information that is used to register the component |
|
<public> … </public> |
Contains the definitions of the properties, events, and methods of the component |
|
<script> … </script> |
Contains the script logic that describes how the component works. Includes the script that defines how the methods, properties and events work |
|
<implements> … </implements> |
Contains the definition of the component type |
How do these tags work? The name of the tag describes the contents of the tag. For example, between the <registration> and </registration> XML tags, we expect to find information relating to the way the component is to be registered on the server machine. In this way, it works rather like, say, the HTML <SCRIPT> and </SCRIPT> tags.
The Component Implementation Script
As part of the design process, we have to decide what methods, properties and events our component should support. When we come to write the component, we need to provide the executable code that describes how these methods, properties and events will work.
In a WSC component, we write the component's logic using a scripting language (for example, VBScript, JScript, PerlScript, etc.). This script has a very specific place within the XML framework that we met a moment ago – we place it between the <script> and </script> tags. We'll see an example in a moment.
The Runtime DLL – scrobj.dll
Finally, WSC provides a file called scrobj.dll, which organizes the compilation of the .wsc file. Here's how scrobj.dll fits into the workings:
- In our ASP page, we request an instance of our WSC component, using a line like this:
Set objObject = Server.CreateObject("MyComponent.wsc")
- Our WSC component (MyComponent.wsc in this case) should already be registered in the registry. It works like the registry entry for the AdRotator component that we looked at earlier – it tells the system where to find the MyComponent.wsc code. However, this entry has an extra piece of information that tells the system where to find scrobj.dll
- The system uses scrobj.dll to compile the contents of MyComponent.wsc, after which it has executable component code
So you can see that a WSC component works slightly differently than a precompiled component. As we said before, the WSC component is compiled at runtime – after it is called but before it can be used. However, a WSC component (like any other component) still has its own entry in the registry.
Now, let's jump right in by building a simple component.
Try It Out – Write a Simple Script Component
For our first look at script components, we will create a component called CarpetPricer, which will contain all the functionality needed to calculate the price of a piece of carpet. Our component will be a very simple component, exposing just one method and one property:
|
Method name |
Parameters |
Purpose |
|
CalculatePrice |
intLength, intWidth |
Calculates the price of a rectangle of carpet of the size specified by intLength and intWidth |
|
Property name |
Possible Values |
Purpose |
|
CarpetType |
Draylon |
Specifies the type of carpet that the customer wants to buy. In the component, each carpet type refers to a different price |
You might imagine this component being used in a page that offers the customer (or the sales assistant, on behalf of the customer) to select from one of the available types of carpet, and also to specify the size of the room that they're buying carpet for. Then, when the user submits these values, the page passes these values to the component, which calculates the price of a piece of carpet based on the submitted values, and returns them to the ASP page for display on the browser.
Let's use the Windows Script Component Wizard to build the framework for our CarpetPricer component. When we've done that, we'll insert the executable script code within the <script> … </script> tags. Finally, we'll register our new component, and we'll write an ASP page to test it.
|
1. Start up the Windows Script Component Wizard (from the Start menu, select Programs | Microsoft Windows Script | Microsoft Script Component Wizard). The first screen in the wizard looks like this:
|
|
The text fields in this dialog will be blank, and you'll need to fill them in. As you fill in the Name field, you'll notice that the Filename and Prog ID fields are filled in automatically. We're going to call the component CarpetPricer – the CarpetPricer.wsc script file will be created automatically by the wizard.
You can specify the version number (we'll leave it as version 1, since this is our first attempt at writing this component). You can also specify a folder on your hard disk, where the resulting .wsc script file will be stored. I've selected C:\Wrox\BegASP, but you can choose any folder that is convenient for you. When you've filled in all the text boxes like this, click Next.
If you've specified a new folder in the Location field, you'll get a dialog warning you that the folder doesn't currently exist and asking you to confirm that you want it to be created. Just click Yes.
|
2. The second wizard dialog invites you to specify various characteristics for the component:
|
|
The first part asks us to choose the scripting language in which we will write the executeable code for the component. As you can see, the wizard gives us a choice of scripting languages. We're going to use VBScript for all our script-based components in this book – since that's the scripting language of choice for this book – so ensure VBScript is selected here.
The second block gives us options relating to the situations where we want to use the script component with DHTML behaviors, or if we want the component to support ASP. We aren't using DHTML behaviors (indeed, they're beyond the scope of this book). The 'support for ASP' option allows us to access the ASP intrinsic objects (Request, Response etc) within the executable script in the component. That's not necessary either in this particular component. Therefore, ensure that the checkbox is empty – as shown above.
Under the runtime options list, enable both Error checking and Debugging – they'll make it easier to find any errors that occur. Click Next again when you've made all these settings.
|
3. Now we can define the properties that our component will expose. In this case, there's just one property, which we'll call CarpetType. This will have a default value of Draylon. Note that we've specified that it should have Read/Write permission – thus, when we use the component in the ASP page we'll be able to change its value and write it to the page.
|
|
When you've done this, click Next.
|
4. The next dialog is similar to use – it's where we define the component's methods. Note that each method's 'definition' consists of the method's name and a list of parameters, and that the the parameters are listed in the order that we must specify then when we come to use the method in our code. We don't specify the executable code for the methods yet – that comes later. |
|
|
The CarpetPricer component will have just one method, called CalculatePrice. This method has two parameters: intLength and intWidth. When you've completed the two boxes as shown above, click Next. 5. The next step allows us to create the events handlers that we want our component to support. The CarpetPricer component won't be implementing any events, so just leave the dialog box empty and click Next.
|
|
|
6. On the final page of the wizard, we see a display of the attributes of our new component:
|
|
Notice that under the Registration heading, there are two items listed. The first, CarpetPricer.WSC, is the component's ProgID – you'll recall that this is the 'common name' for the component, and the name that we might when creating an instance of the component. For example, in ASP, we might use the line:
Set objCP = Server.CreateObject("CarpetPricer.wsc")
As we mentioned earlier in the chapter, the ProgID of the component is not necessarily unique – it's possible to create other components that have the same ProgID. However, the ClassID is an automatically-generated unique identifier for the component. As you can see, the wizard has generated a ClassID for our component, and it's listed here as the second item under the Registration heading. The ClassID for the component I've created here is 52047c4b-61d1-4684-9edf-cd97c036f023 – the ClassID for your component will be different of course, because all ClassIDs are unique.
Click Finish – the wizard will complete the task of generating the component. You should get a dialog box confirming the location of the new .wsc file.
7. The WSC wizard has generated the framework for the component, based on the instructions we gave in the steps of the wizard. However, we still haven't written the executable script code that will define how the methods work. We'll do that in this step.
Using Windows Explorer, go to the folder that you specified in Step 1 of the wizard (I specified C:\Wrox\BegASP) – there, you'll find the CarpetPricer.wsc file that we just created. Now start Notepad and use it to open the CarpetPricer.wsc file, so that you can see its code (we'll take a look at what it all means after we've built and tested the example). For now, we must make only one change to the existing code, and that is to add the functionality for the CalculatePrice method. To do that, locate the following code in the CarpetPricer.wsc file:
function CalculatePrice(intLength, intWidth)
CalculatePrice = "Temporary Value"
end function
Remove the shaded line above, and replace it with the following shaded code:
function CalculatePrice(intLength, intWidth)
Dim intPricePerSqFoot
Select Case CarpetType
Case "Axeminster"
intPricePerSqFoot = 10
Case "Draylon"
intPricePerSqFoot = 15
Case "Twistpile"
intPricePerSqFoot = 18
End Select
CalculatePrice = intWidth * intLength * intPricePerSqFoot
end function
Now save and close the CarpetPricer.wsc file without changing its name.
|
8. Now we need to create an entry in the registry for our new component. To do this, right-click on the CarpetPricer.wsc file in your Windows Explorer window and select Register from the resulting menu:
|
|
|
If the script component registers correctly, you'll get the following message box:
|
|
How It Works – The XML Framework
The first thing to notice relates to the message box that we get at the end of this process. The message is generated by RegSvr32.exe, which we first saw in Chapter 11 and is responsible for registration and unregistration of components on our machine. Here, it's telling us that DllRegisterServer and DllInstall in scrobj.dll succeeded (but note that it doesn't mention our CarpetPricer.wsc file). This makes sense, because the scrobj.dll file is the COM-compliant 'wrapper' that handles the calls to our script components.
Now let's take a look at the code in our CarpetPricer.wsc file. Part of the code (the XML framework) is generated by the WSC wizard, and part of the code (the implementation of the component) was written by us.
The first thing that the .wsc script does is declare the version of XML that it's using:
<?xml version="1.0"?>
All of the code for the component (including registration information, public methods and properties, and script) is enclosed in <component> … </component> tags. There's also a <?component?> tag, which specifies that we selected the error checking and debugging options for this component:
<component>
<?component error="true" debug="true"?>
Next, the <registration> … </registration> tags contain information that is used when the component is registered into the registry:
<registration
description="CarpetPricer"
progid="CarpetPricer.WSC"
version="1.00"
classid="{52047c4b-61d1-4684-9edf-cd97c036f023}"
>
</registration>
This is so that, when we come to use the component in our code, the machine will know where to look for it. In our code, we can specify the ProgID of the component like this:
Set objCP = Server.CreateObject("CarpetPricer.wsc")
When the code executes, the server consults its registry to find out the location and other details relating to the given ProgID, and then uses that information to access the component's functionality.
Next come the declarations of the public methods of the component. These are the names of the methods, properties and events that the component exposes to any application that's using it:
<public>
<property name="CarpetType">
<get/>
<put/>
</property>
<method name="CalculatePrice">
<PARAMETER name="intLength"/>
<PARAMETER name="intWidth"/>
</method>
</public>
In this example, the CarpetPricer component is exposing a property called CarpetType. It is also exposing a method called CalculatePrice (which takes two parameters, as we can see here). This tallies with the information we inserted when we used the WSC wizard to build the component.
What do we mean when we say that the component exposes only these methods and properties? It means that, regardless of the internal workings of the component, any application that uses this component can only access the values contained in the properties of this component, and it can only access the functionality of the methods of this component. It can't use the component for any other (hidden) properties or functionality that the component might use under the covers.
In this example, it means that the only methods and properties available to our ASP page are the CarpetType property and the CalculatePrice method.
The Component's Implementation
Finally, we come to the <script> … </script> tags, which should look familiar – they contain the implementation of the component's methods and properties. In the <script> tag, we declare that we intend to use the VBScript language in the code that defines our methods and properties:
<script language="VBScript">
<![CDATA[
VBScript code goes in here
]]>
</script>
Don't worry about the <![CDATA[ … ]]> that the wizard puts here. It is simply there to tell the XML engine to ignore anything that lies between the <![CDATA[ and the ]]>. This makes sense if you think about it, because the code is VBScript, not XML!
The VBScript itself is quite simple. First, it declares a variable called CarpetType that will hold the value of the component's CarpetType property:
dim CarpetType
CarpetType = "Draylon"
In the wizard, we set the default value of this property to "Draylon" – the second line above assigns the default value to the property at this stage. Next, come two functions called get_CarpetType() and put_CarpetType():
function get_CarpetType()
get_CarpetType = CarpetType
end function
function put_CarpetType(newValue)
CarpetType = newValue
end function
These two functions are internal to the component, which means that we can't call them from outside the component (for example, we can't call these functions directly from the ASP page). What do they do? Well, get_CarpetType() is responsible for getting the current value of the CarpetType variable whenever it is requested; and put_CarpetType() is responsible for changing the value of the CarpetType variable whenever we assign a new value to the CarpetType property.
So, for example, suppose we need to get hold of the value of the CarpetPricer object's CarpetType property sometime, using a line of ASP like this:
strTempString = objCP.CarpetType
This causes the component to execute its get_CarpetType() function, which fetches the current value of its CarpetType varaiable and returns it to our ASP page. And if we try to assign a new value to the property, like this:
objCP.CarpetType = strTempString
This causes the component to execute its put_CarpetType() function, passing the newly-assigned value as a parameter – and it assigns that parameter value to its
CarpetType variable.
Finally, we have the CalculatePrice() function, which contains our own implementation of the CalculatePrice method that the component exposes:
function CalculatePrice(intLength, intWidth)
Dim intPricePerSqFoot
Select Case CarpetType
Case "Axeminster"
intPricePerSqFoot = 10
Case "Draylon"
intPricePerSqFoot = 15
Case "Twistpile"
intPricePerSqFoot = 18
End Select
CalculatePrice = intwidth * intlength * intPricePerSqFoot
end function
This function checks the value of the component's CarpetType property, and sets the price-per-unit for that type of carpet. Then it multiplies that value by the area of carpet required to calculate the price of the required carpet, and returns the result.
In order to see our component in action, we'll write an ASP page.
Try It Out – Using the Script-Based Carpet Pricer Component in an ASP Page
We'll try it out by creating a little 'front-end' for the component – a simple ASP page that allows the user to select from a choice of different types of carpet, and then displays sample prices for different carpet sizes based on the user's selection. The ASP code for this is really quite straightforward.
Remember that you can obtain all this code from the Wrox web site , if you don't want to type it all in.
1. Create a new file using your code editor, and enter the following code:
<HTML>
<HEAD>
<TITLE>Testing the CarpetPricer</TITLE>
</HEAD>
<BODY>
<H2>Carpet Sir?</H2>
<%
If Request.ServerVariables("HTTP_METHOD") = "POST" Then
Dim objCarpetPricer, strCarpetType
strCarpetType = Request.Form("carpettype")
Set objCarpetPricer = Server.CreateObject("CarpetPricer.wsc")
objCarpetPricer.CarpetType = strCarpetType
Response.Write "Last time, you selected to view prices of our range " & _
"of <B>" & strCarpetType & "</B> carpets. " & _
"Here is a sample range of prices:<BR><BR>"
Response.Write "<TABLE BORDER=1><TR><TD></TD>" & _
"<TD COLSPAN=6 ALIGN=CENTER>Length</TD></TR>" & _
"<TR><TD ROWSPAN=7>Width</TD><TD></TD>" & _
"<TH>2</TH><TH>4</TH><TH>6</TH><TH>8</TH><TH>10</TH></TR>"
For intWidth = 1 To 5
Response.Write "<TR><TH>" & intWidth & "</TH>"
For intLength = 2 To 10 Step 2
Response.Write "<TD> $" & _
objCarpetPricer.CalculatePrice(intLength, intWidth) & "</TD>"
Next
Response.Write "</TR>"
Next
Response.Write "</TABLE>" & _
"<HR>Would you like to view sample prices " & _
"for a different type of carpet?<BR><BR>"
Set objCarpetPricer=Nothing
End If
%>
<FORM ACTION="CarpetPricer.asp" METHOD="POST">
Select carpet type:
<SELECT NAME="carpettype">
<OPTION>Draylon</OPTION>
<OPTION>Axeminster</OPTION>
<OPTION>Twistpile</OPTION>
</SELECT>
<INPUT TYPE="SUBMIT" VALUE="View Prices">
</FORM>
</BODY>
</HTML>
2. Save the file into your \inetpub\wwwroot\BegASPFiles directory, as CarpetPricer.asp.
|
3. Open your web browser, and browse to the page.
|
|
|
Select a carpet type from the drop-down list, and click the View Prices button. You should get a screen that looks something like this:
|
|
How It Works
This page is in two parts – the HTML form that captures the user's input, and the HTML table that displays the prices on the browser. Let's look at the form first – it simply asks the user to select one of three different carpet types:
<FORM ACTION="CarpetPricer.asp" METHOD="POST">
Select carpet type:
<SELECT NAME="carpettype">
<OPTION>Draylon</OPTION>
<OPTION>Axeminster</OPTION>
<OPTION>Twistpile</OPTION>
</SELECT>
<INPUT TYPE="SUBMIT" VALUE="View Prices">
</FORM>
The name of the inputted data will be carpettype, and since the form uses the POST method to submit the selection, the data will be captured in the new page by the Request.Form collection.
Now let's look at the display part, which is much more exciting. The If statement at the top checks to see whether any data was posted to the page. If so, then we know that the user is submitting input about a carpet type, about which he wants to know sample prices and so we continue:
<%
If Request.ServerVariables("HTTP_METHOD") = "POST" Then
Dim objCarpetPricer, strCarpetType
strCarpetType = Request.Form("carpettype")
The first thing we do is assign the submitted information (the carpettype value in the Request object's Form collection) to a local variable called strCarpetType.
Now we're ready to start using our CarpetPricer component. The first thing we must do is create an instance of the component, and assign the instance to a variant name in our code:
Set objCarpetPricer = Server.CreateObject("CarpetPricer.wsc")
This is a syntax we've seen many times before – for example, when creating an instance of an ADO Connection object. Here, we're using the ASP Server object's CreateObject method to create an instance of the component specified in the parameter. In this case, the specified parameter is CarpetPricer.wsc – which you'll recall is the ProgID of our component. The ASP engine goes away to our machine's registry and asks where it will find a component of that name. Of course, we have already registered our component, so the registry is able to tell the ASP engine exactly where it must look to find the necessary code for the instance (in this case, using a combination of the scrobj.dll file and the CarpetPricer.wsc file).
Now, we can use the methods and properties of this object in just the same way as we use the methods and properties of any other object. First, we'll assign our objCarpetPricer object's CarpetType property to the type selected by our user:
objCarpetPricer.CarpetType = strCarpetType
Now we can set about building the table of values. First, we display a message and set up the first part of the table:
Response.Write "Last time, you selected to view prices of our range " & _
"of <B>" & strCarpetType & "</B> carpets. " & _
"Here is a sample range of prices:<BR><BR>"
Response.Write "<TABLE BORDER=1><TR><TD></TD>" & _
"<TD COLSPAN=6 ALIGN=CENTER>Length</TD></TR>" & _
"<TR><TD ROWSPAN=7>Width</TD><TD></TD>" & _
"<TH>2</TH><TH>4</TH><TH>6</TH><TH>8</TH><TH>10</TH></TR>"
Now, we write the rows of the table. The rows of the table are numbered 1 to 5 here, to represent the widths of different rooms, and the columns are numbered 2 to 10 to represent the lengths of different rooms. Then, for each of these room sizes we call our object's CalculatePrice method, specifying the width and length in the two parameters:
For intWidth = 1 To 5
Response.Write "<TR><TH>" & intWidth & "</TH>"
For intLength = 2 To 10 Step 2
Response.Write "<TD> $" & _
objCarpetPricer.CalculatePrice(intLength, intWidth) & "</TD>"
Next
Response.Write "</TR>"
Next
Response.Write "</TABLE>" & _
"<HR>Would you like to view sample prices " & _
"for a different type of carpet?<BR><BR>"
Right in the middle of this block of code, is a line where the ASP page calls the CalaculatePrice method of our CarpetPricer component. It's just like calling the method of any other object – something we've done many times already in this book. Easy, isn't it?
At the end, we've finished with our CarpetPricer object so we clean up, just as we would do with any other objects we were using:
Set objCarpetPricer = Nothing
End If
%>
| << 16.2.0- Writing Our Own Components | Chapter16 | 16.3.0- Components and Data Access >> |

RSS











