APGen Documentation Previous Topic: Logging in APGen Next Topic: Sinking COM Events in APG Scripts Parent Topic: APGen Developer's Guide    APGen Developer's Guide
Pluggable Streams
See Also:

Pluggable Streams is a feature of Active Page Generator that allows the developer to:

Output and Log Streams

APGen Output and Log objects have Stream properties that can be used to set or retrieve an object that implements the IStream interface.

In C++, the objects returned from the Stream properties can be QueryInterface()ed (using IID_IStream) to return an IStream*.  The objects cannot be accessed by scripting languages or Visual Basic, because the IStream interface is not a COM automation interface.  The IStream interface is described in the Microsoft Win32 SDK documentation.

If a Stream property is set to refer to an object, then the object must implement the IStream interface.  If the object does not implement the IStream interface, then an error will be raised when the Stream property is set.

Default Streams

If custom streams are not set, then default streams are used.  The default streams are streams that write to files:  For example, the default Output stream writes to a file with path Output.Path.  Similarly, the default Log stream writes to a file with path Log.Path.

The default streams are created automatically under the following conditions:

  1. No stream currently exists. 
  2. Content is written to the object. 

For example, if Output.Write() or Output.BinaryWrite() are called, and no Output.Stream currently exists, then a stream is created that writes to the output file.  Essentially, Output.Open() is implicitly called if no stream exists and content is generated.

Closing Streams

Output.Close() releases the current Output stream.  There is no equivalent Log object method.  However, this code:

Log.Stream = Nothing

releases the Log stream, so it is equivalent to a Log.Close() method.

A reference to a stream is maintained until Output.Close() is called, the containing script is released, or the Stream property is set to point to another object.

When all references to a default stream are released, the file is closed.

Sharing Streams Between APG Scripts

The Pluggable Streams feature can be used to share streams between multiple APG scripts.  This involves setting a script's Output.Stream (or Log.Stream) property to another script's Output.Stream (or Log.Stream) property.

This example uses the Output.Stream property to share output streams between two APG scripts.  Script.apg uses programmatic execution to direct the execution of a second APG script, htmlfrag.apg.  All content generated by both APG scripts is sent to the file output.htm.

Script.apg:

<%#  ' -- script.apg --
Option Explicit
Output.Filename = "output.htm"
#%>
<HTML><BODY>
First line generated by script.apg<BR>
<%#

Dim oAPGen, oScriptHtmlFrag
Set oAPGen = CreateObject("APGen")
Set oScriptHtmlFrag= oAPGen.OpenScript("htmlfrag.apg")

' This is where the output stream is shared
' Send htmlfrag.apg's output to script.apg's output stream.
oScriptHtmlFrag.Output.Stream = Output.Stream

' Now, run "htmlfrag.apg"
oScriptHtmlFrag.Run

#%>
</BODY></HTML>

Note that HtmlFrag.apg contains no script blocks.  HtmlFrag.apg:

<P>
     HTML Fragment
</P>

Together these two scripts create output file output.htm:


<HTML><BODY>
First line generated by script.apg<BR>
<P>
     HTML Fragment
</P>
</BODY></HTML>

The line that shares the output stream is:

oScriptHtmlFrag.Output.Stream = Output.Stream

This redirects the output stream for the oScriptHtmlFrag object (which represents HtmlFrag.apg) to the output stream for Script.apg (which writes to output.htm).  This line is necessary, else calling

oScriptHtmlFrag.Run

would send output to HtmlFrag.htm.

For another example that shares output streams and utilizes the APGScript.Globals property, see the APGScript.Globals topic.

Sending Output to Custom COM Objects

To send output (Output object output or Log object output) to a custom COM object, the COM object must implement the IStream interface.  Since the IStream interface is a non-automation interface, the object must be written in C++, or another language that supports custom COM interfaces.

The IStream interface is described in the Win32 SDK documentation.

Your custom object should implement the following IStream methods:

Method Comment
IStream::Write() Must be implemented to receive content.
IStream::Seek() Required if Append property is True.  Otherwise, does not have to be implemented.

The other IStream methods do not have to be implemented (they can return E_NOTIMPL).  IStream::Seek() is called if the Append property (Output.Append or Log.Append) is True.  Note that the default value for Log.Append is True, so if you are implementing a custom object that will receive the log stream, and you want to append information to the stream, then you will need to implement IStream::Seek().

Once you have written an object that implements IStream, you can use APG script code to place your object on the receiving end of the stream:

' Let's say your object has ProgID "Company.StreamObject"
Dim oStreamObject
Set oStreamObject = Script.CreateObject( "Company.StreamObject" )

' Send output to your object
Output.Stream = oStreamObject

That's all it takes to send output to your object. 

The Output object will hold onto your object until the script is released, Output.Close() is called, or Output.Stream is set to point to another object.