Encoding for the Masses

No matter your job (or platform), scripting makes life easier.

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.

Featured