Mr. Script
Encoding for the Masses
No matter your job (or platform), scripting makes life easier.
- By Chris Brooke
- 05/01/2003
It can be argued that the primary purpose of application development
in general, and scripting in particular, is to automate repetitive processes—with
a particular emphasis on simplifying the user’s experience. With that
in mind, let’s flex our new developer muscles and look at last month’s
script. What’s wrong with it? (Go easy on me!) Its fundamental flaw is
that it only encodes one script at a time—and only .WSF scripts, at that.
Not very automated, is it? Let’s see what we can do about that.
<package>
<comment>
EncodeFolder.wsf
This script encodes an entire folder of scripts
</comment>
<job>
<runtime>
</description>
This script encodes
a folder of scripts
</description>
<example>
C:\cscript encodefolder.wsf
/Source: [Source Folder]
/Dest: [Destination
Folder]
</example>
<named
name="Source"
helpstring="The
path and name of the folder containing the scripts
to encode"
type="string"
required="true"
/>
<named
name="Dest"
helpstring="The path and name of the
folder where the
encoded scripts will
be saved"
type="string"
required="true"
/>
</runtime>
<object id="objFSO"
progid="Scripting.FileSystemObject"/>
<object id="objEncode"
progid="Scripting.Encoder"/>
<script language="VBScript">
Option
Explicit
Dim objSourceFolder, objDestFolder,
objFile, objStream, objEncFile
Dim strSourceFolder, strDestFolder,
strSourceFile, strEncFile, strDestFile
Dim strExt, strScriptType
'Get
the command-line arguments
strSourceFolder=WScript.Arguments.Named.Item("Source")
strDestFolder=WScript.Arguments.Named.Item("Dest")
Open
the folder and get the collection of files
If objFSO.FolderExists(strSourceFolder)
Then Set objSourceFolder=objFSO.GetFolder(strSourceFolder)
Else
WScript.Echo "Source Folder Specified does
not exist"
WScript.Quit
End If
'If
Dest folder does not exist, create it
If
objFSO.FolderExists(strDestFolder) Then
Set
objDestFolder=objFSO.GetFolder(strDestFolder)
Else
Set
objDestFolder=objFSO.CreateFolder(strDestFolder)
End
If
'Main
Loop - Cycle through the source folder
For
Each objFile in objSourceFolder.Files
strExt=objFSO.GetExtensionName(objFile.Name)
Select
Case strExt 'REF: 1
Case
"wsf"
strScriptType=".sct"
Case
"vbs"
strScriptType=".vbs"
Case
"js"
strScriptType=".js"
Case
Else
strScriptType="NS"
End
Select
If
strScriptType <> "NS" Then
'Get
the file and read it into a buffer
Set
objStream=objFile.OpenAsTextStream(1) 'REF:
2
strSourceFile=objStream.ReadAll
objStream.Close
'Encode
the script
WScript.Echo
"Now encoding: " & objFile.Name
strEncFile=objEncode.EncodeScriptFile(strScriptType,
strSourceFile,
0, "")
'Write
the encoded file in the correct format
If
strScriptType=".vbs" Then
strDestFile=Left(objFile.Name,
Len(objFile.Name)-3) & "vbe"
ElseIf
strScriptType=".js" Then
strDestFile=Left(objFile.Name,
Len(objFile.Name)-2) & "jse"
ElseIf
strScriptType=".sct" Then
strDestFile="e"
& objFile.Name
End
If
Set
objEncFile=objDestFolder.CreateTextFile(strDestFile)
WScript.Echo
"Now Writing encoded file: " & objDest
Folder.Path
& "\" & strDestFile
objEncFile.Write
strEncFile
objEncFile.Close
Else
WScript.Echo
"Skipping file: " & objFile.Name
End
If
Next
</script>
</job>
</package>
Now That's More Like It!
Geez! We’re thinking like developers now, aren’t we? I’ve taken the code
that encrypts the script and added the capability of encoding an entire
directory of scripts—even if that directory contains different types of
scripts such as .VBS, .JS and .WSF. Furthermore, it ignores any files
that aren’t scripts, just in case you like to keep Readme files or other
assorted documentation in your scripts directory.
I used the FileSystemObject (FSO) extensively to bind to both the source
and destination folders, cycle through each file in the source folder
(encoding any scripts as I find them), and then write those files to the
destination folder. I’ve also programmed the script to keep you informed
about what it’s doing—whether it’s encoding a file, writing that file
to the destination folder or skipping it altogether (if it’s not a script).
This is an important step when writing a script to perform repetitive
actions. If the script fails, it helps to know what it was trying to do.
Think
Like a Developer |
I just got back from Orlando,
Florida where I was a speaker at a developer conference.
During one of the coffee breaks, I wound up having a
20-minute conversation with a developer—an Enterprise
Java developer—about Perl scripting. Perl scripting!
What do you know? It seems that, regardless of platform
or language preference, there are combination code-monkeys/server-jockeys
everywhere.
If you’re doing any amount of scripting
as part of your daily tasks, then you are (at least
in part) a software developer. My point is this: To
the extent that your job involves software development,
you should try to think like a developer. Every once
in a while, pick up one of the developer journals from
your company’s magazine rack or coffee table and
thumb through it. In particular, look at Web-development
periodicals, as many Web applications are almost entirely
based around script code. Don’t be put off if
some of it seems over your head. Keep plowing through,
and you’re sure to find a nugget or two that will
prove indispensable to your scripting toolkit. Who knows?
In a year or two, you may find yourself putting in a
training request to go to a developer conference!
—Chris Brooke |
|
|
Lost in the Translation
Sometimes, as a result of formatting this column for publication, the
script listings might show line breaks at incorrect locations. To alleviate
any potential headaches for you, we’ve started publishing the completed
scripts online for download. Not only will this guarantee that you have
a correctly formatted script, it’ll save you a lot of typing! (Download
the script by Clicking Here
or by right-clicking that link, then choosing "Save As..." from
the context menu. Note that this script or any other script may be falsely
recognized as a virus when you download it.)
I’ve also begun to footnote my inline comments in order to try to keep
the lines shorter. Here are the “complete” comments from the two footnoted
comments in the above script labeled REF: 1
and REF: 2.
REF 1: By using a Select…Case statement, you’re able to check for any
valid script file. If the specified file doesn’t match any of your conditions,
set it to “NS” (No Script) and it will be skipped.
REF 2: When you open a file as a Text Stream, you can specify an I/O mode.
In this case, the I/O mode is 1, which means “For Reading.” Since this
is your source file, you don’t want to write to it accidentally and possibly
corrupt an important script.
Sanity Check
Remember that you must disable strict XML parsing for any .WSF scripts.
This means getting rid of the <?xml?>
and <>> tags. The encoder
can’t deal with that added pressure! Also, because .WSF files have the
same extension whether they’re encoded or not, it is possible that you
might accidentally try to encode a script in your source directory that’s
already been encoded. Fear not! The encoder won’t “re-encode” a script.
The worst that’ll happen is that the filename will have two prefixes (for
example, “eeScript.wsf”). It’ll still run just fine.