Before listing the steps of the process let see what the
processed file may contain:
It could be an ASP page or HTML file. In general there are no
considerable differences between the processing mechanism in the
both cases thus for simplicity we could assume HTML file.
The file may contain <SCRIPT RUNAT=COMPILER> tags with
some script in them. Also a script could be attached to the file
(file options dialog). The file may contain some CUSTOM/CUSTOMFILED
tags or also some other user-defined ones. One simple file
containing the mentioned elements may look like this:
Something <COSTOMFIELD ID="SomeField"> Something else ...
<SCRIPT RUNAT=COMPILER Language=VBScript>
Custom("SomeField")("Class") = "Text"
Custom("SomeField")("Content") = "Some text to replace the tag"
Also, invisible here, a script in external file or from the CTS
library could be attached to the file.
Now let follow the steps the compiler does:
- Initializing the attached compile time script (CTS). This
includes loading the script file as specified in the file
options, preparing environment information for it. Passing
this information to the script - e.g. the project as data
tree implemented using VarDictionary
collections, compiler object (to allow the script to issue
messages), additional data as paths, variables etc.
- Then the compiler will fire to the script's OnProcessFile
event. The script is able to prevent file processing or
allow it. Also the output file name is defined by the script
during the event handling.
- The compiler will prepare for file parsing phase. It will
initialize the appropriate parser - for ASP or
HTML/SSI file and before starting will fire to the attached
script OnModifyParser event. If the attached script needs to
retrieve/change parts of the file other than those in the
CUSTOM/CUSTOMFIELD tags it could use the parser's AddTag
method to request additional HTML tags to be parsed. For
example the script may want to access the document title.
- The file is parsed, all includes are resolved and finally
a Page Object Model (POM) is prepared in a tree constructed
using VarDictionary collections.
- The compiler inspects the tree and executes all the script
found in the <SCRIPT RUNAT=COMPILER> tags. It passes
to them the document tree and they are able to modify not
only the part they occupy but also other parts of the
document. The above example will replace a CUSTOMFIELD tag
with some text.
- After completing with all the embedded script compiler
will fire to the attached script OnCheckStructure event. The
embedded scripts are still active thus during the event
handling the attached script is able in theory to call
methods defined in the embedded scripts. This feature does
not follow any pre-defined pattern thus it is mostly for
developers who want to construct a specialized programming
scheme where the attached script invokes the embedded
scripts. Usually during this event the embedded script will
find some tags, record some information from them, replace
others with some texts from DB and/or multiply some parts of
the page if these parts are to be repeated to match a number
of records returned by a query or some other sets of
information. For example this could be the contents of the
CUSTOM tag in the above sample HTML.
- The compiler will clean up (the embedded scripts are no
longer needed, nor the temporary information needed for the
preceding events). And the OnCreateOutput event will be
fired to the attached script. This allows it to prevent
further file processing (i.e. generation of the physical
output). This could be the desired result if the project is
developed to collect information only or if the project's
aim is creating index or some other similar structure for
the files in it.
- Now the changes in the file are made - in fact they are
made in the POM (the document tree) and compiler regenerates
the file from it. Depending on the processing option the
result will be generated in file or in a memory stream. For
example in case of ASPtoVB processing there is no need to
save the intermediate result in a file and it is kept in a
memory stream that is them passed to the next phase - VB
files and project generation.
- The compiler fires the OnOutputCreated event to the
attached script to inform it and allow it to inspect the
file in some very specific way. This is rarely needed but
however it is provided as feature. The attached script
receives as parameters the file name and the file as opened
read/write stream. Thus it is able to modify it, but as it
was mentioned this is provided just for some very specific
cases not related to the typical ASP Compiler functionality.
- This completes the file processing, but in case of
compilation to VB and DLL one additional event will be fired
to the attached script - OnLoaderFileCreated. This allows
some specific rarely needed tasks to be performed on the loader
file by the attached script.
- End of processing. The compiler returns to the first step
and if the attached script needs this it could cause file to
be processed again and again till a certain condition is
met. This is for example the typical way HTML static pages
are generated from a DB - the page that acts as a template
is processed one time for every record returned from a query
or for every 10 records (if it is a list of some items and
paging is implemented with page size 10 records).
After the embedded script ends the processing of the file the
OnRequireCompletion event is fired to it. This allows the
script to register procedures to be performed after all the
files in the project are processed. Why need this? For example
it is very convenient to generate pages and collect some index,
keyword information for them at the same time. This information
will not be full till the last file in the project is processed.
Thus if you want to implement something that uses the collected
information during the build and generate some files or update a
DB you will need to do so at the end of the project processing.
One very nice example is the HTML help generation. The pages
require some simple replacements - a few line of CTS are enough
to tune them but you need also to generate project file, index
file and contents for the Microsoft HTML Help compiler. Thus the
attached script reads also the document titles, some META tags
and stores the information in a temporary storage. At the end of
the project processing it generates these files.
Note that if the file has no attached CTS the compiler will not
fire any events to it and will skip the steps related explicitly
to the attached compile time script - 1,2, 6,9,10,11. In this case
the file is processed only once.
As you can see the processing depends on the attached compile
time script and if it does not exist the process is much simple.
But the attached script is able to extend the compiler behavior
and as it was mentioned (see step 6) the attached scripts could
implement a custom driving mechanism that invokes the embedded
scripts and some functions/subs defined in them from
"outside". Of course this is advanced trick and you may
never need it, but suppose you work on a project too flexible to
be implemented once and changing part of its goals too frequently.
The only way to help your self will be to implement some
components and group them in some structures as needed. Then this
feature that looks a bit strange could save a lot of work
So, it is reasonable to concentrate only on the features you
currently need and only note the existence of the others.
Requirements to the CTS are flexible and you do not need to read
the entire help in order to write something. For example an
embedded script needs only knowledge about the information and
objects available for it and how the document tree looks. We
designed the environments of the embedded and the attached scripts
to match each other at the possible maximum. Thus an embedded
script could evolve to attached script requiring only the changes
that caused the decision to change its role. You may select the
right form - embedded or attached script, embedded script but
moved in external file to met your needs and preferences.
Extending and improving your CTS you may need to change its form,
but this will not involve additional work.