Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Script "Cooker"

5 views
Skip to first unread message

Alex K. Angelopoulos (MVP)

unread,
Nov 22, 2002, 9:15:58 AM11/22/02
to
While trying to create a pseudo-parser for VBScript, I put together a few
routines which can be used to "massage" a script preparatory to doing special
things with it such as formatting it for display or "mining" it for
procedures/classes/structures.

I have wrapped what I have so far as a class, and it is embedded below with a
sample script at the top. Here's some notes on it...

POSSIBLE USES

This is immediately useful for reformatting code and for "script mining". With
some minor extensions, it should be able to do the following soon:
+ identify the objects instantiated in the script
+ pull out a list of all special names used (e.g. variables, etc)
+ basic analysis of procedures for argument lists.

Extended uses which are not too hard after this include looking for minor coding
issues within script: loops that may cause CPU lugging, byval/byref calls,
redeclarations, and "dead code" not called from elsewhere.

DETAILS ON HOW YOU USE THE CLASS

The "ScriptCleaner" class is more than a cleaner but not quite a lexer or parser
yet. You instantiate it with the "New" keyword of course:

Set Scr = New ScriptCleaner

You then have to feed it a script. You can do this either by loading it from a
string:

Scr.LoadScript sData

Or by loading it from a file (just give it the full path to the file):

Scr.LoadFromFile sData

The first handy thing this can do is attempt to "orthogonalize" a script. It
will attempt to reduce the script to a logically identical structure which is
easier for the parsing techniques to handle, by calling the Orthogonalize
method:

Scr.Orthogonalize

Orthogonalization consists of stripping all leading and trailing blank
characters from lines, removing empty lines, changing all line endings to vbLf,
and joining lines which have continuation characters. It will then ignore
quoted text and split statements which have been concatenated with ':' onto
separate lines, change all of the embedded whitespace delimiters into spaces,
and merge multiple spaces into a single space. You can access the
orthogonalized script by reading the property orthogonal:

WScript.Echo Scr.orthogonal

Next, you can "cook" the script down into formatted structures with the cook
method:

Scr.cook

After cooking the script, you can get an array containing all classes with

classes = scr.classes

get an array containing all of the non-class procedures with

procs = scr.procedures

access the external (non-class, non-procedural code) with

main = scr.main

and retrieve the entire script reformatted somewhat with:

cooked = scr.cooked


CURRENT POSSIBLE ISSUES

It MAY have problems with the following two situations under certain
circumstances:
+ If you have a comment line which ends with a '_', it could attempt to
concatenate that with a following line. In traditional VB this is correct
operation; VBScript uses different rules, however, and apparently just discards
comments without checking for a terminal '_' at compile time.
+ It will parse embedded comments such as the following, and strip out the extra
spaces embedded in the comment:
a = b ' this is a comment
this problem does not occur for lines where the first non-whitespace character
is a ', and should be fixed by me in the nect revision of this.


EXAMPLE SCRIPT AND THE SCRIPTCLEANER CLASS
' ==========================================
' NOTE - YOU WANT TO RUN THIS WITH CSCRIPT
' this script demos the scriptcleaner class
' by cleaning itself.

Option Explicit

Dim Scr, x, i, y

Set Scr = New ScriptCleaner

Scr.LoadFromFile WScript.ScriptFullName
Scr.Orthogonalize
Scr.Cook


MsgBox "About to display the orthogonal script."
WScript.Echo Scr.Orthogonal


MsgBox "About to display the cooked script."
WScript.Echo Scr.Cooked

x = Scr.Classes
If UBound(x)>-1 Then
MsgBox " About to display classes; found " _
& UBound(x) + 1
For each y in x
WScript.echo y
next
End If

x = Scr.Procedures
If UBound(x)>-1 Then
MsgBox " About to display procedures; found " _
& UBound(x) + 1
For each y in x
WScript.echo y
next
End If

x = Scr.Main
MsgBox "About to display main body of code."
WScript.Echo Scr.Main

Class ScriptCleaner

Dim m_Raw, m_Cooked, m_classes, m_procedures
Dim rx, Main, m_Orthogonal

Private Sub Class_Initialize
Set rx = New RegExp
rx.IgnoreCase = True
rx.Global = True
rx.Multiline = True
End Sub

Public Property Get Cooked
Cooked = m_Cooked
End Property

Public Property Get Orthogonal
Orthogonal = m_Orthogonal
End Property

Public Property Get Procedures
Procedures = m_Procedures
End Property

Public Property Get Classes
Classes = m_Classes
End Property

Public Sub LoadScript(sData)
m_Raw = sData
End Sub

Private Function Matches(sData, Patrn)
rx.Pattern = Patrn
set Matches = rx.Execute(sData)
End Function

Public Sub Cook
Dim sTmp
sTmp = m_Orthogonal
m_Classes = StructureList(sTmp, _
"^(class ).+$", _
"^end (class)", True)
m_Procedures = StructureList(sTmp, _
"^(private |public )*(sub |function).+$", _
"^end (sub|function)", True)
Main = IndentStructures(sTmp)
m_Cooked = IndentStructures(m_Orthogonal)
End Sub

Public Sub Orthogonalize
' code-cleaner; returns as orthogonal lines separated by vbLf
Dim aData, i, j, mlstate
' REMOVE EXTRALINEAR WHITESPACE
' kill in-line leading/trailing WS and
' change line separators to vbLf
m_Orthogonal = RxReplace(m_Raw, "\s*$\s*", vbLf)
' This "efficiently" cleans up the whitespace
' before the first line of code.
mlstate = rx.Multiline
rx.Multiline = False
m_Orthogonal = RxReplace(m_Orthogonal, "^\s*", "")
' Kill the last linefeeds while we're at it.
m_Orthogonal = RxReplace(m_Orthogonal, vbLf & "+$", "")
rx.Multiline = True
' this joins multiline statements into one expression.
' correctly ignores lines with leading comments, but
' if a line has an EMBEDDED comment and ends with '_'
' this could have problems. In theory this is fine;
' VB syntax honors continuation in comments; but VBScript
' does not.
m_Orthogonal = RxReplace(m_Orthogonal, "^([^'].*)_" & vbLf, "$1")
aData = Split(m_Orthogonal, vbLf)
for i = 0 to Ubound(aData)
aData(i) = Split(aData(i), """")
next
for i = 0 to Ubound(aData)
if left(aData(i)(0), 1) <> "'" then
for j = 0 to UBound(aData(i)) step 2
aData(i)(j) = lcase(RxReplace(aData(i)(j),"\s+", " "))
next
end if
aData(i) = Join(aData(i), """")
next
m_Orthogonal = Join(aData, vbLf)
rx.Multiline = mlstate
End Sub

Private Function StructureList(sData, rxOpenStruct, _
rxCloseStruct, bStrip)
' give it open/close regexes for a structure, and this
' procedure will retrieve them.
dim open, close, match, i, startPos, lenStruct, structs()
set open = Matches(sData, rxOpenStruct)
set close = Matches(sData, rxCloseStruct)
redim structs(open.count-1)
For i = open.Count - 1 to 0 step -1
startPos = open.Item(i).FirstIndex
lenStruct = close.Item(i).FirstIndex + 1 _
+ Len(close.Item(i).value) - startPos
structs(i) = IndentStructures(Mid(sData, _
startPos + 1, lenStruct))
If bStrip Then
sData = Left(sData, startPos - 1) _
& Mid(sData, startPos + lenStruct)
End If
next
StructureList = structs
End Function

Private Function RxReplace(sData, oldPatrn, newPatrn)
rx.Pattern = oldPatrn ' Set pattern.
RxReplace = rx.Replace(sData, newPatrn)
End Function

Public Sub LoadFromFile(FilePath)
'Given the path to a file, will return entire contents
' works with either ANSI or Unicode
Dim FSO, CurrentFile
Const ForReading = 1, TristateUseDefault = -2, _
DoNotCreateFile = False
Set FSO = createobject("Scripting.FileSystemObject")
If FSO.FileExists(FilePath) Then
If FSO.GetFile(FilePath).Size>0 Then
Set CurrentFile = FSO.OpenTextFile(FilePath, _
ForReading, _
False, TristateUseDefault)
LoadScript CurrentFile.ReadAll: CurrentFile.Close
End If
End If
End Sub

Private Function IndentStructures(sData)
Dim StructStartMarkers, aData, i, StructEndMarkers, Depth, prefix
' next set needs to be tweaked a bit for class structures
StructStartMarkers = Array("sub ", "function ", "class ", "if ", _
"for ", "do ", "while ", "with", "select", "public", _
"private", "property")
StructEndMarkers = Array("end ", "loop", "wend", "next")
aData = Split(sData, vbLf)
For i = 0 To UBound(aData)
prefix = String(Depth, vbTab)
If IsMarker(aData(i), StructStartMarkers) Then
Depth = Depth + 1
ElseIf IsMarker(aData(i), StructEndMarkers) Then
' Crude hack to prevent negative depths
If Depth > 0 Then Depth = Depth - 1
prefix = String(Depth, vbTab)
End If
aData(i) = prefix & aData(i)
Next
IndentStructures = Join(aData, vbLf)
End Function

Private Function IsMarker(sData, Markers)
' given a string sData and an array of markers [Markers]
' returns true if the string starts with the marker
Dim marker
For each marker in Markers
If LCase(Left(sData, Len(marker))) = marker Then
IsMarker = True
Exit Function
End If
Next
IsMarker = False
End Function

End Class


Han

unread,
Nov 22, 2002, 9:59:01 AM11/22/02
to
Aweful. If there is an interface, the application can be loved by a lot of
scripters, I guess.

--
Han Pohwan, Microsoft MVP, Seoul, Korea
Mail with any alphabets in the title will be removed. Use only numbers.
"Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message
news:Oj61rHjkCHA.2008@tkmsftngp08...

Joe Fawcett

unread,
Nov 22, 2002, 10:13:14 AM11/22/02
to
"Han" <hp4...@kornet.net> wrote in message
news:e9NerejkCHA.1368@tkmsftngp09...

> Aweful. If there is an interface, the application can be loved by a lot of
> scripters, I guess.
>
The English language has changed so much. When King Georege I saw St. Paul's
cathedral for the first time he called it both 'aweful' and 'artificial',
both great compliments. I suppose nowadays awful should be awesome.
Joe

Ned Flanders

unread,
Nov 22, 2002, 10:42:45 AM11/22/02
to
Actually, aweful still means a compliment; it's awful that's the bad one.

Joe Fawcett <joefa...@hotmail.com> said (and I quote):

Alex K. Angelopoulos (MVP)

unread,
Nov 22, 2002, 10:46:53 AM11/22/02
to
Unless Han really _did_ mean "awful". I know him well enough, he can get away
with saying that. Maybe. <g>

--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp
------
I'd like to change the world, but they won't give me the source code.
- Kees Couprie
"Joe Fawcett" <joefa...@hotmail.com> wrote in message
news:O#PamnjkCHA.4256@tkmsftngp08...

Joe Fawcett

unread,
Nov 22, 2002, 10:47:12 AM11/22/02
to
"Ned Flanders" <ned...@hotmail.com> wrote in message
news:uH6eN3jkCHA.3244@tkmsftngp10...
>Well according to my normally reliable :) Microsoft Word
thesaurus/spellchecker aweful does not exist.
So it can't be a word.
Also my email client spellchecker says 'emails' is not a word.

Joe


Ned Flanders

unread,
Nov 22, 2002, 10:55:08 AM11/22/02
to
Joe Fawcett <joefa...@hotmail.com> said (and I quote):
>> Well according to my normally reliable :) Microsoft Word
> thesaurus/spellchecker aweful does not exist.
> So it can't be a word.
> Also my email client spellchecker says 'emails' is not a word.

Well, I wouldn't consider Word an authority on very much....<g>
However, you are right, my bad, I went to several online (and paper!)
dictionaries and was unable to find aweful anywhere. I guess it stuck in my
head from all those "olde Englishe" texts I read last year and I thought it
was still in use today.


Alex K. Angelopoulos (MVP)

unread,
Nov 22, 2002, 11:18:28 AM11/22/02
to
Use the word anyway. It's not an "unword", you're just "embracing and
extending" English. <g>

--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp
------
I'd like to change the world, but they won't give me the source code.
- Kees Couprie

"Ned Flanders" <ned...@hotmail.com> wrote in message

news:ObgUI#jkCHA.2380@tkmsftngp09...

Han

unread,
Nov 22, 2002, 11:20:10 AM11/22/02
to
I mean awe(admiration) + ful(adjective tail). Some years ago, My American
teacher asked me; Am I fat? I answered; You're common. She didn't like it.
Later I knew I had to say "average". Similar case. I refered my Longman
dictionary, and found that if I said awful, that can be even more
contradictary to my feeling. Thanks all. I learned one word exactly.

--
Han Pohwan, Microsoft MVP, Seoul, Korea
Mail with any alphabets in the title will be removed. Use only numbers.

"Joe Fawcett" <joefa...@hotmail.com> wrote in message

news:OzYBl6jkCHA.1492@tkmsftngp09...

Tom Jones

unread,
Nov 22, 2002, 11:23:13 AM11/22/02
to
I found this definition at www.atomica.com....

aw·ful adj.
Extremely bad or unpleasant; terrible: had an awful day at the office.
Commanding awe: “this sea, whose gently awful stirrings seem to speak of
some hidden soul beneath” (Herman Melville).
Filled with awe, especially:
Filled with or displaying great reverence.
Obsolete. Afraid.
Formidable in nature or extent: an awful burden; an awful risk.
adv. Informal.
Extremely; very: was awful sick.
[Middle English aweful, awe-inspiring, blend of awe, awe. See awe, and
*ayfull, awful (from Old English egefullege, dread-full, -ful).]
aw'ful·ly adv.
aw'ful·ness n.


"Ned Flanders" <ned...@hotmail.com> wrote in message

news:ObgUI#jkCHA.2380@tkmsftngp09...

Ned Flanders

unread,
Nov 22, 2002, 11:51:44 AM11/22/02
to
What an aweful idea.
;-p

----------------------------------------------------
On the negative side, I've been getting charged
for a ton of stuff I didn't order lately.
On the positive side, I did win that "Who's Got
the Best Password" contest on AOL last week.
----------------------------------------------------

Alex K. Angelopoulos (MVP) <a...@mvps.org> said (and I quote):


> Use the word anyway. It's not an "unword", you're just "embracing and
> extending" English. <g>
>

Paul Randall

unread,
Nov 22, 2002, 6:03:58 PM11/22/02
to
Comments inline

"Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message news:Oj61rHjkCHA.2008@tkmsftngp08...

> While trying to create a pseudo-parser for VBScript, I put together a few
> routines which can be used to "massage" a script preparatory to doing special
> things with it such as formatting it for display or "mining" it for
> procedures/classes/structures.
>
> I have wrapped what I have so far as a class, and it is embedded below with a
> sample script at the top. Here's some notes on it...

I'd call it awesome. So much functionality in such little code.
One small problem to think about is how to keep comments that precede a subroutine/function with the code of the sub/function.

Quote from SCRIPT56.CHM:
~The following code adheres to VBScript coding conventions.
~
~'*********************************************************
~' Purpose: Locates the first occurrence of a specified user
~' in the UserList array.
~' Inputs: strUserList(): the list of users to be searched.
~' strTargetUser: the name of the user to search for.
~' Returns: The index of the first occurrence of the strTargetUser
~' in the strUserList array.
~' If the target user is not found, return -1.
~'*********************************************************
~Function intFindUser (strUserList(), strTargetUser)
~ Dim i ' Loop counter.
~ Dim blnFound ' Target found flag
~ intFindUser = -1
~ i = 0 ' Initialize loop counter
~ Do While i <= Ubound(strUserList) and Not blnFound
~ If strUserList(i) = strTargetUser Then
~ blnFound = True ' Set flag to True
~ intFindUser = i ' Set return value to loop count
~ End If
~ i = i + 1 ' Increment loop counter
~ Loop
~End Function

I appended my 'append to file' routine to your code, and changed the Wscript.Echo statements to instead send that info to files.
All of the comments on my routine that preceded the sub statement ended up with the 'main' code.

I'm looking forward to the next revision.
The variable list is one thing I would really like.

-Paul Randall


Alex K. Angelopoulos (MVP)

unread,
Nov 22, 2002, 6:45:42 PM11/22/02
to
"Paul Randall" <paul...@cableone.net> wrote in message
news:e4sHotnkCHA.1368@tkmsftngp09...
> Comments inline

>
> I'd call it awesome. So much functionality in such little code.
> One small problem to think about is how to keep comments that precede a
subroutine/function with the code of the sub/function.

I was pondering that specific issue a couple of nights ago; since someone else
is raising it, it sounds like it's the next likely target.

As an aside, that's one thing I found annoying about the "coding standards"
Microsoft implements. Many Microsoft-internal scripts DO use that convention -
and I suspect the reason is that someone decided it would be nice to use a
really simple code-stripping technique for material they keep in a database. A
better standard would be to internalize the documentation so that it always goes
with the procedure, which is what I tend to do - it makes it much easier to
treat the procedures as objects, which is obviously one of the points here.

Regardless, a lot of the "minable" code is from Microsoft, so it would be best
to include preceding documentation lines. Unfortunately, the Microsoft code
isn't always standard in how it behaves; you occasionally see terminal
commented-out code or main-body comments preceding a procedure. Probably the
best general fix is to allow a settable "Microsoft-compatibility" switch to
capture all preceding contiguous comment lines and hope for clean code. To make
ME happy about it, I may set it to allow embedding the commenting within the
procedure block. ;-)

>
> I appended my 'append to file' routine to your code, and changed the
Wscript.Echo statements to instead send that info to files.
> All of the comments on my routine that preceded the sub statement ended up
with the 'main' code.

XML-ified output of some kind might be a good idea as well...

Paul Randall

unread,
Nov 23, 2002, 9:33:27 PM11/23/02
to

"Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message news:#BWcJ7okCHA.448@tkmsftngp11...
> New version - this is a WSC; it will automatically generate a typelib for object
> browser use (a la TLViewer) when it is registered.
>
Hi, Alex

I have this uncanny ability to do things 'differently', causing things to not work.

1) I decided that much as I like the name ChopShop, I would never remember that it is for tidying/extracting VBScripts, so I renamed
it ChopShopVBScriptTidy.wsc before registering it. Needless to say (then why am I saying it???), DllInstall in
C:\Windows\system\scrobj.dll failed. Return code was 0x80020101. After starting a response to you I tried some things to fix it
and I finally tried the original file name, and of course it registered just fine!

2) Then I tried TLViewer to look at its properties and methods. TLViewer couldn't tell me anything about it. I think there may be
a problem with the typelib registration section of your code. I looked in my registry and was expecting to see ChopShop.tlb here,
but instead found:
[HKEY_CLASSES_ROOT\TypeLib\{3C45916E-AE0D-4FCD-A4C7-0F61AACFA509}\7d2.462\0\win32]
@="@"
TLViewer showed '@' as the full path to ChopShop's typelib too.

3) In the process of dinking with the problem, I uninstalled ChopShop, and noticed that the uninstall does not delete ChopShop.tlb.
I kind of thought it would or should.

4) When I ask for the ChopShop object's TypeName, I get {ADBFDC03-FF10-11D6-B0FE-00A0CC3ADCBF}. I was thinking I'd get something
more witty.

I'm learning about things to consider when I write my next WSC.

5) I wrote a short script to test ChopShop, using your
ScriptCleaner.vbs to be Orthogonalized and cooked.
Indentation failed at:

if ismarker(adata(i), structstartmarkers) then
depth = depth + 1
elseif ismarker(adata(i), structendmarkers) then

I haven't tried any other options yet.

I'm impressed with this. I will find it very handy when it is finished.

-Paul Randall


Alex K. Angelopoulos (MVP)

unread,
Nov 23, 2002, 10:05:47 PM11/23/02
to
Don't break my toys!!!

<g>

Other comments inline...

--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp

"Paul Randall" <paul...@cableone.net> wrote in message

news:Orw7SH2kCHA.1688@tkmsftngp09...


>
> "Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message
news:#BWcJ7okCHA.448@tkmsftngp11...
> > New version - this is a WSC; it will automatically generate a typelib for
object
> > browser use (a la TLViewer) when it is registered.
> >
> Hi, Alex
>
> I have this uncanny ability to do things 'differently', causing things to not
work.
>
> 1) I decided that much as I like the name ChopShop, I would never remember
that it is for tidying/extracting VBScripts, so I renamed
> it ChopShopVBScriptTidy.wsc before registering it. Needless to say (then why
am I saying it???), DllInstall in
> C:\Windows\system\scrobj.dll failed. Return code was 0x80020101. After
starting a response to you I tried some things to fix it
> and I finally tried the original file name, and of course it registered just
fine!

A few possibilities come to mind; one is that you may have had a TypeLib browser
such as TLViewer "focused" on it when you tried to register. That will
definitely not work, since it "locks" the file.

> 2) Then I tried TLViewer to look at its properties and methods. TLViewer
couldn't tell me anything about it. I think there may be
> a problem with the typelib registration section of your code. I looked in my
registry and was expecting to see ChopShop.tlb here,
> but instead found:
>
[HKEY_CLASSES_ROOT\TypeLib\{3C45916E-AE0D-4FCD-A4C7-0F61AACFA509}\7d2.462\0\win3
2]
> @="@"
> TLViewer showed '@' as the full path to ChopShop's typelib too.

That's part of how WSCs work (a process I understand only vaguely). Also, you
actually have to register the TLB after registering the component in order to do
the browsing.

>
> 3) In the process of dinking with the problem, I uninstalled ChopShop, and
noticed that the uninstall does not delete ChopShop.tlb.
> I kind of thought it would or should.

WSC's are very plain vanilla; you want to unregister and manually undelete.
OBviously, scriptlets weren't designed as full-service objects.

>
> 4) When I ask for the ChopShop object's TypeName, I get
{ADBFDC03-FF10-11D6-B0FE-00A0CC3ADCBF}. I was thinking I'd get something
> more witty.

Oh, that I can provide! I bet you a dollar that if you check Typename now, you
don't get the number above retrieved.

In any case, that's a hexadecimal representation of the Klingon for "your mother
is a hamster."

Alex K. Angelopoulos (MVP)

unread,
Nov 23, 2002, 10:34:46 PM11/23/02
to
> 5) I wrote a short script to test ChopShop, using your
> ScriptCleaner.vbs to be Orthogonalized and cooked.
> Indentation failed at:
>
> if ismarker(adata(i), structstartmarkers) then
> depth = depth + 1
> elseif ismarker(adata(i), structendmarkers) then
>
> I haven't tried any other options yet.
>
> I'm impressed with this. I will find it very handy when it is finished.
>
> -Paul Randall


Actually, the failure above is one of the "special cases" that has problems - I
haven't accounted for it yet.

Related to that, this is an outgrowth of my approach to my parser (it isn't
really a parser yet, though). It's hand coded instead of using a formal grammar
to build it. As I may have mentioned before, for various reasons I am suspicious
that the VBScript parser was "hand coded" by Microsoft anyway; the VB family is
so syncretistic that it would be endlessly painful to write a formal grammar and
attempt to use that as a foundation for the language.

One issue I need to think out is some differences between my approach and that
of the Scripting developers. For example, they appear to just throw comments
away immediately prior to compilation; this is harder to emulate if I want to
preserve comments, but is an intelligent approach to running the code. A couple
of the quirks of usage between VB and VBScript and appear to be due to shortcuts
the developers took is marginal differences in how things like the line
continuation and commenting affect things.

For example, in VB the following is a 2-line comment:
x = "World" ' say hello to this _
MsgBox "Hello, " & x & "!"

The continuation prevents display of the MsgBox, showing that the VB parser does
parse comment lines and then interprets the underscore as a continuation; run
the above code in VB and you will get nothing. In VBScript, however, the
' say hello to this _
gets dumped right away, and you will see
Hello, World!
displayed.

An oddity with the continuations is that VBScript will accept continuations
without a space preceding them. This is more flexible, but using ,_ instead of
, _ with VB5/6 is not valid syntax. This is a pretty fundamental item for a
formal grammar, which is why I suspect hand-coding in its history.

(Oh, yeah, I suppose I should fix the quirk with elseif...)


Alex K. Angelopoulos (MVP)

unread,
Nov 24, 2002, 11:18:51 AM11/24/02
to
"Paul Randall" <paul...@cableone.net> wrote in message
news:Orw7SH2kCHA.1688@tkmsftngp09...

> 1) I decided that much as I like the name ChopShop, I would never remember
that it is for tidying/extracting VBScripts...

This means you're thinking of new names for it? (Hint, hint).


Paul Randall

unread,
Nov 24, 2002, 11:54:17 AM11/24/02
to
I thought that my job as toy-tester required me to try to break them <g>
Comments inline

"Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message news:uEAnSe2kCHA.2204@tkmsftngp08...


> Don't break my toys!!!
>
> <g>
>
> Other comments inline...

> > that it is for tidying/extracting VBScripts, so I renamed


> > it ChopShopVBScriptTidy.wsc before registering it
>

> A few possibilities come to mind; one is that you may have had a TypeLib browser
> such as TLViewer "focused" on it when you tried to register. That will
> definitely not work, since it "locks" the file.

I just renamed the file and tried to register it. That had worked for me when I was playing with a .WSC with no typelib info
inside -- this had allowed me to access a testing version and working version from the same script. TLViewer was not running at the
time I registered the script. I think that your line:
oTL.AddURL "ChopShop.wsc"
was now referencing a non-existent file, which probably caused Return code of 0x80020101.


> > 2) Then I tried TLViewer to look at its properties and methods. TLViewer

> > TLViewer showed '@' as the full path to ChopShop's typelib too.
>
> That's part of how WSCs work (a process I understand only vaguely). Also, you
> actually have to register the TLB after registering the component in order to do
> the browsing.

Hmmm. My knowledge of typelibs is minimal. But I think their purpose is to allow running software to ask them for the names of the
associated objects' properties, methods, events, etc. The running software might be a .WSF, accessing the info in the typelib with
a statement like:
<reference [object="progID" | guid="typelibGUID"] [version="version"] />
Without a typelib section in the .WSC, I think that the registration process puts progID and other info in the registry so that the
object can be instantiated. I think the Function Register() section is supposed to do two things: 1) create the .TLB file, getting
info from the specified .WSC file, and 2) add info to the registry about where to find this new typelib file. My registry just
shows '@' as the path to the .TLB. But I can't find anything in Dino Esposito's Windows Script Host book, or anywhere else, that
actually says what should show up in the registry. For all the other objects whose typelib info TLViewer can display, I see an
entry in the registry with the full path to the typelib file. What good is it if the object created by this statement:
set oTL = CreateObject("Scriptlet.TypeLib")
creates the typelib file but does not put the path to it in the registry?

> > 3) In the process of dinking with the problem, I uninstalled ChopShop, and
> noticed that the uninstall does not delete ChopShop.tlb.
> > I kind of thought it would or should.
>
> WSC's are very plain vanilla; you want to unregister and manually undelete.
> OBviously, scriptlets weren't designed as full-service objects.
>

I don't know that it is possible, but it seems logical that in the
Function UnRegister()
section within the
<registration progid="ChopShop.wsc"
section, you should be able to undo everything that was done in the
Function Register()
section.

Maybe that is really difficult unless you know exactly what
oTL.Write
does, or until they come up with the
oTL.UnWrite
method.

> >
> > 4) When I ask for the ChopShop object's TypeName, I get
> {ADBFDC03-FF10-11D6-B0FE-00A0CC3ADCBF}. I was thinking I'd get something
> > more witty.
>
> Oh, that I can provide! I bet you a dollar that if you check Typename now, you
> don't get the number above retrieved.
>
> In any case, that's a hexadecimal representation of the Klingon for "your mother
> is a hamster."

ROFL

-Paul Randall


Paul Randall

unread,
Nov 24, 2002, 12:02:37 PM11/24/02
to

"Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message news:eIRAtU9kCHA.1864@tkmsftngp10...

VBSCooker comes to mind.

-Paul Randall


Alex K. Angelopoulos (MVP)

unread,
Nov 24, 2002, 6:36:31 PM11/24/02
to
That's not bad... I was thinking about other names involving lexing and parsing,
and it isn't genuinely any of those.

New update; I've been trying this as a compiled DLL (the idea is to switch to
API copies eventually to make for rapid string processing) and have incidentally
discovered that VB cracks up when I try some of the tricks I have been using
with on-the-fly retyping of arrays to contain other arrays. Yet another
asymmetry, although not grammatical at least...

--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp

"Paul Randall" <paul...@cableone.net> wrote in message

news:#0U47s9kCHA.1392@tkmsftngp12...

Alex K. Angelopoulos (MVP)

unread,
Nov 24, 2002, 6:58:10 PM11/24/02
to
"Paul Randall" <paul...@cableone.net> wrote in message
news:#Z6JSo9kCHA.2692@tkmsftngp08...

> I thought that my job as toy-tester required me to try to break them <g>

I keep forgetting that part.


> "Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message
news:uEAnSe2kCHA.2204@tkmsftngp08...
> > Don't break my toys!!!


>

That would be nice; unfortunately the Scriptlet.TypeLib class just creates a
typelib - it doesn't provide a native mechanism for registering it; that could
be added if I figure out the syntax using tlbinf32.


> I don't know that it is possible, but it seems logical that in the
> Function UnRegister()
> section within the
> <registration progid="ChopShop.wsc"
> section, you should be able to undo everything that was done in the
> Function Register()
> section.
>
> Maybe that is really difficult unless you know exactly what
> oTL.Write
> does, or until they come up with the
> oTL.UnWrite
> method.

AFAIK, the Write method purely writes the TLB it has generated out to a disk; it
doesn't even provide a technique for reading the TLB. Removal on un-registration
is a good idea; it isn't going to happen with scrobj.dll though, since it is
more-or-less now a part of a legacy package.

Paul Randall

unread,
Nov 24, 2002, 8:02:45 PM11/24/02
to
Hi, Alex

I searched my registry for "{3C45916E-AE0D-4FCD-A4C7-0F61AACFA509}", which is in the typelib section of the WSC. It shows up seven
times. I'm guessing that the typelib is registered. I just think it is lacking the correct path to the TLB file. Maybe a bug in
Scriptlet.TypeLib.

I'm guessing that five of these are orphaned entries. I may have registered and unregistered it that many times. Do we have a WSC
expert in the house who can tell us exactly what Scriptlet.TypeLib does during the register and unregister process when you have
included a typelib section?

-Paul Randall


Alex K. Angelopoulos (MVP)

unread,
Nov 24, 2002, 9:26:39 PM11/24/02
to
Michael may be able to tell us something about this...

I believe the first 6 should be there; they are all of this form:
HKCR\Interface\{A GUID}\Typelib

and point to a version of 7d2.462 (which is hex for 2002.1122)

The last one is the actual lookup itself, and will be under this key:

HKCR\TypeLib\{3C45916E-AE0D-4FCD-A4C7-0F61AACFA509}\7d2.462\0\win32


--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp

"Paul Randall" <paul...@cableone.net> wrote in message

news:#ieeO5BlCHA.716@tkmsftngp11...

Alex K. Angelopoulos (MVP)

unread,
Nov 27, 2002, 11:56:35 AM11/27/02
to
I still haven't had a chance to do the only tests I can think of for this, but
the idea of those 6 typelib refs being proxy entries on XP makes sense, Mark -
and I see that many showing up after a SINGLE registration of a component...

--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp


"Mark_Pryor" <mpry...@NETsprintmail.com> wrote in message
news:eBMEv6ZlCHA.2260@tkmsftngp07...
Hi,

To get the TypeLib to register I still used
/regtlib chopshop.tlb

Attached is a patch file with 4 changes.
1) names the CoClass
2)simplifies major and minor version
3)fixed the instr call in ParseObjects

hth,
Mark Pryor
"Alex K. Angelopoulos (MVP)" wrote in message


news:#BWcJ7okCHA.448@tkmsftngp11...
> New version - this is a WSC; it will automatically generate a typelib for
object
> browser use (a la TLViewer) when it is registered.
>

> --
> Please respond in the newsgroup so everyone may benefit.
> http://dev.remotenetworktechnology.com
> ----------
> Subscribe to Microsoft's Security Bulletins:
> http://www.microsoft.com/technet/security/bulletin/notify.asp

> ------
> I'd like to change the world, but they won't give me the source code.
> - Kees Couprie

> "Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message

> news:Oj61rHjkCHA.2008@tkmsftngp08...

0 new messages