|
Windows Clients
Using VBScript
The preceding sections provide many examples of using the IOM interfaces in a full Visual Basic environment (or in a Visual Basic for Applications (VBA) environment like Microsoft Word and Excel).
You can also use the IOM interfaces from a VBScript environment. VBScript is a commonly used scripting language that is available in Active Server Pages (ASP), Dynamic HTML (DHTML), Microsoft Outlook 97 and later, and Windows Scripting Host. For configuration information, see Configuring COM/DCOM for Active Server Page Access in the SAS Integration Technologies: Server Administrator's Guide.
Scripto is an ActiveX DLL that has been developed by SAS in order to provide
workarounds for the following common VBScript limitations:
- Method calls in VBScript are limited to a single return value of type Variant
- Arrays can only contain Variants
- There is no support for reading or writing binary files
Note: If you are developing your code or macros to run in a full Visual Basic or VBA environment, then you do not need the Scripto DLL.
Scripto is provided with SAS Integration Technologies so that developers who choose to use VBScript can effectively use the SAS automation interfaces. However, Scripto is not specific to SAS and can be used with other automation interfaces.
The performance of VBScript is usually less than a VB application for several reasons. First, VBScript provides only late binding (it uses IDispatch instead of v-table calls). Also, VBScript is interpreted, not
compiled. In addition, the way that VBScript invokes methods (InvokeMethod) causes additional overhead because all parameters must be copied twice to get them in the proper format in which VBScript expects them.
This is especially evident in the case of safearrays in which SAS expects to contain the actual type of element in the array (such as string or an enumeration value). VBScript expects it to contain only VARIANTS, which in turn contain the appropriate type of element. InvokeMethod takes care of this conversion. However, it produces an additional copy of the array.
Scripto does not address these performance issues. We recommend that if performance is an issue, consider something other than a scripting language for your implementation. We also recommend that you
only use Scripto when calling methods whose signatures require it.
There are 2 components implemented by the Scripto DLL: Scripto and StreamHelper.
The Scripto Interface: IScripto
IScripto is the single interface to the Scripto component. It
provides two methods:
- SetInterface IUnknown
- This method is used to specify the IOM interface that contains the
method that you want to invoke. The interface must be set prior to using
InvokeMethod.
The interface specified must support IDispatch, and that IDispatch
implementation must support type information. If either of these is not true,
SetInterface will return E_INVALIDARG(&H80070057).
An instance of the Scripto component can handle only a single
interface at a time. Although you can create multiple instances of
Scripto that handle with a different interface, you typically only
need a single instance of Scripto. You would use this instance for all
interfaces that need the service. Switching between interfaces does not
consume a significant amount of system resources.
SetInterface performs an AddRef function on the interface that is
specified. You can release this reference when you are finished
with the interface using the following statement:
SetInterface Nothing
Also, when you release IScripto, it will release any interface that
Scripto still references.
Note that after you set an interface, you can still make calls on it
without using Scripto.
- retParam InvokeMethod( methodName, params)
- This method invokes the desired IOM interface method through the Scripto DLL.
This method can only be invoked after the interface has been set using SetInterface.
methodName is a string that contains the name of the method to
invoke on the interface that has been set.
params is an array whose elements contain the parameters for
the method to be invoked.
The order of the parameters placed in the
array must be in reverse order of how they are specified in the method
signature.
The array must have exactly the same number of
elements as there are parameters to the method. Otherwise, InvokeMethod
returns DISP_E_BADPARAMCOUNT(&H8002000E) .
Note: If the method has a parameter that uses the [retval]
modifier, then this parameter is returned as the return value to
InvokeMethod and you do not need an element in the params array for it.
retParam is the return value from the
method you are invoking, if that method returns a value.
Note: If the method returns a reference to an object,
make sure to use the Set keyword. For example:
Set obServer = obScripto.InvokeMethod(_
"CreateObjectByServer", ServerDefParms)
The StreamHelper Interface
The StreamHelper interface contains three methods related to working with the
SAS BinaryStream (available through the SAS FileService). These methods
are only useful when working with SAS; these methods make calls on IBinaryStream
to read and write binary data.
Microsoft supplies the FileSystemObject, which can be used to read and write text
files. The FileSystemObject does not work with binary files, so SAS has provided the following methods.
The StreamHelper interface is implemented in Scripto.dll using the SASScripto.StreamHelper progid.
- WriteBinaryFile IBinaryStream, fileName
-
This method copies the entire contents of the given IBinaryStream into the
specified file. This method can be useful for copying a SAS ResultPackage from the
SAS server to the machine where the VBScript is running. It can also be used to
copy GIF images. The BinaryStream that is passed in must have
already been opened with permission to read.
- ReadBinaryFile fileName, IBinaryStream
-
Reads the entire contents of the file into the SAS BinaryStream. This method
does the reverse of what WriteBinaryFile does. The BinaryStream that is passed in
must be open for permission to write. Sending binary data to SAS can be useful
if you want to include a binary file in a SAS package.
- arrayOfBytes = ReadBinaryArray (IBinaryStream, numBytes)
-
Reads the specified number of bytes from the BinaryStream and returns them
in the arrayOfBytes. If numBytes is 0, the entire contents of the
BinaryStream is returned in the array. The array is a variant containing
a SAFEARRAY of bytes. This array can be passed directly to the Response.BinaryWrite
method of Microsoft Active Server Pages.
Programming Examples
The first example illustrates using the Scripto component to reverse the order
of parameters when invoking a method. Assuming the method
has been defined with the following IDL code:
HRESULT MethodToInvoke([in]param1, [out]param2, [out]param3)
To make this call with Scripto:
Dim f(2) 'An array of 3 VARIANTS
obScripto.SetInterface myInterface
f(2) = param1
obScripto.InvokeMethod "MethodToInvoke", f
param3 = f(0) ' Note that the order of parameters is reversed
param2 = f(1)
The next example uses the IOM LanguageService to submit
SAS language statements to the IOM server. It then uses
Scripto to invoke the FlushLogLines method of the
LanguageService. Using Scripto provides two important
advantages over invoking the method directly from VBScript:
- It converts the three arrays that are returned from the method from arrays of long integers to arrays of variants. (Note that VBScript can only use arrays that contain elements of data type variant.)
- It allows the VBScript application to receive more than one return parameter from the method that is invoked. (Note that when you invoke a method directly from VBScript, you are limited to a single return value.)
set obSAS = CreateObject("SAS.Workspace.1.0")
Set obScripto = CreateObject("SASScripto.Scripto")
obSAS.LanguageService.Submit "proc options;run;"
obScripto.SetInterface obSAS.LanguageService
' This example uses Scripto to invoke the FlushLogLines method
' instead of invoking the method directly from VBScript
' as shown in the following statement:
' obSAS.LanguageService.FlushLogLines 1000, carriageControls,_
' linetypes, logLines
Dim flushLogLinesParams(3)
' Note that the FlushLogLines method takes 4 parameters:
' 1) numLinesRequested (in) Specifies an upper limit on the
' number of lines to be returned.
' 2) carriageControls (out) An array that indicates carriage
' control for each line returned.
' 3) lineTypes (out) An array that indicates the line type
' for each line returned.
' 4) logLines (out) Contains the SAS log output lines
' retrieved by this call.
flushLogLinesParams(3) = 1000
obScripto.InvokeMethod "FlushLogLines",_
flushLogLinesParams
' flushLogLinesParams(0) now has logLines
' flushLogLinesParams(1) now has lineTypes
' flushLogLinesParams(2) now has carriageControls
' Print the first line
wscript.echo flushLogLinesParams(0)(0)
The CreateObject() call in this previous example creates a server object by providing a COM ProgID. The ProgID is a string form of the COM class identifier (CLSID). In this case, the ProgID describes a SAS session providing the Workspace interface. By explicitly specifying the major and minor version "1.0" as a suffix to the ProgID "SAS.Workspace", you can ensure compatibility with all versions of the SAS Integration Technologies IOM server (the server can emulate earlier versions). If you are using a Version 9 SAS Integration Technologies client and you do not specify a version suffix to the ProgID, you cannot connect to a Version 8 COM server.
Note: Two-level version suffixes were not available in previous versions of the SAS Integration Technologies Windows client.
The next example illustrates using ReadBinaryArray with Microsoft Active Server Pages.
Assume a SAS program has already run that uses SAS/GRAPH to write a GIF image to a fileref called "img".
This example then uses the FileService to read that file back to the browser, with no intermediate files on the Web server.
set obFref = obSAS.FileService.UseFileref("img")
set obBinaryStream = obFref.OpenBinaryStream(1)
' SAS.StreamOpenModeForReading=1
set obStreamHelper = CreateObject("SASScripto.StreamHelper")
response.contenttype = "image/gif"
response.binarywrite obStreamHelper.ReadBinaryArray(_
obBinaryStream, 0)
The next example shows how to use WriteBinaryFile to copy a SAS ResultPackage.
Demo.sas is a stored procedure that creates a ResultPackage in an archive.
obSAS.LanguageService.StoredProcessService.Execute "demo.sas",_
parameters
The following lines move the package that was just created from the SAS server to the local machine.
Set obRemotePackageFileRef = obSAS.FileService.AssignFileref(_
"", "", "./demo.spk", "", "")
Open a binary stream on the SAS server for the package file.
Set obRemotePackageBinaryStream = _
obRemotePackageFileRef.OpenBinaryStream(1)
'StreamOpenModeForReading
Because VBScript cannot handle binary files, use the Scripto object to
write the binary file on the local machine.
Set obStreamHelper = Server.CreateObject("SASScripto.StreamHelper")
obStreamHelper.WriteBinaryFile obRemotePackageBinaryStream,_
"c:\myfile.spk"
|