Now that I’ve shown how to build a cool .Format() method for strings, we can put it to good use in a lot of places.

In batch scripting, it’s really nice to be able to make nearly every call support replacement arguments in a consistent fashion. In cmd.exe batch scripts, we use %var% all over the place. In JScript batch scripting, we simply use {$VAR} instead, and put a little bit of code in the top of our functions to help out with that.

First, the one-stop-universal-arguments helper, which we can add to the source from before:

Scripting.js
function ArgsToArray(x) { return Array.prototype.slice.call(x);} 

// FormatArguments must be passed either:
//     one argument: 
//          containing the arguments object from the caller
//          where the first argument of that should be the format string.
//          == or ==
//          just the format string.
//
//     two arguments:
//          the first argument is the format string
//          the second argument is the argument collection from the caller.
function FormatArguments(args, moreargs) {
    var result = "";

    if (arguments.length == 1) {
        if (typeof (args) == "object") {
            args = ArgsToArray(args);
            result = "" + (args.shift());

            if (args.length == 1 && arguments[0].length > 0)
                args = arguments[0];

            return result.Format(args);
        } else return ("" + args).Format();
    } else if (arguments.length == 2) {
        if (typeof (args) == "string" && typeof (moreargs) == "object") {
            result = args;
            args = ArgsToArray(moreargs);
            args.shift();

            return result.Format(args);
        }
    }
    throw "Invalid Argument passed to FormatArguments";
}

FormatArguments()  gives us the ability to do variable substitution in any function, in a very flexible way. You can simply use the function to give you a completed string:

Test-4.js
// use the first string as the format string, 
// the rest are potential value substitutions
function Test1() {
    var foo = FormatArguments(arguments)
    WScript.echo( foo );
}

Test1("the path is {$PATH}");

// both arguments are used as format strings. any 
// parameter substitution should use numbers starting
// at {1}, since the 'destfile' parameter is techincally {0}
function Test2(srcfile, destfile) {
    var srcfile = FormatArguments(srcfile, arguments);
    var destfile = FormatArguments(destfile, arguments);
    var msg = "Copy {0} to {1}".Format(srcfile, destfile);
    WScript.echo(msg);
}

Test2("{$WINDIR}\\system32\\notepad.exe" , "{$USERPROFILE}\\desktop\\notepad.exe");

Knowing that, we can create a few functions that will use the FormatArguments function:

Scripting.js
// Some global objects we'll need 
var WSHShell = WScript.CreateObject("WScript.Shell");
var WinShell = WScript.CreateObject("Shell.Application");
var procEnvironment=WSHShell.Environment("PROCESS")
var fso = new ActiveXObject("Scripting.FileSystemObject");

function Print() {
    WScript.echo(FormatArguments(arguments));
}

function cd() {
    WSHShell.CurrentDirectory = FormatArguments(arguments);
}

function pwd() {
    return WSHShell.CurrentDirectory;
}

function erase(file) {
    file = FormatArguments(arguments);
    if (exists(file))
        fso.DeleteFile(file);
}

function rmdir(folder) {
    folder = FormatArguments(arguments);
    if (folderExists(folder))
        fso.DeleteFolder(folder, true);
}

function exists(file) {
    return fso.FileExists(FormatArguments(arguments));
}

function folderExists(folder) {
    return fso.FolderExists(FormatArguments(arguments));
}

function mkdir(folder) {
    folder = FormatArguments(arguments);
    if (!folderExists(folder))
        fso.CreateFolder(folder);
}

Now, we can do some pretty nifty little batch scripting:

test-5.js
// Bootstrap Scripting Library
eval(new ActiveXObject("Scripting.FileSystemObject").OpenTextFile("Scripting.js", 1, false).ReadAll());

$ORIG_DIR = pwd();

if( exists("{$WINDIR}\\log.txt") ) {
    Print("Deleting log file");
    erase("{$WINDIR}\\log.txt");
}

mkdir("{$TEMP}\\tempdir");

Next time, we’ll see how we can call on command-line tools to do our bidding, and play with the results.