<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Garrett Serack: Open Source Development at Microsoft : JScript</title><link>http://blogs.msdn.com/garretts/archive/tags/JScript/default.aspx</link><description>Tags: JScript</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Using JScript as a batch scripting language (Part III)</title><link>http://blogs.msdn.com/garretts/archive/2009/05/18/using-jscript-as-a-batch-scripting-language-part-iii.aspx</link><pubDate>Mon, 18 May 2009 23:15:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9625922</guid><dc:creator>GarrettS</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/garretts/comments/9625922.aspx</comments><wfw:commentRss>http://blogs.msdn.com/garretts/commentrss.aspx?PostID=9625922</wfw:commentRss><description>&lt;p&gt;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.&lt;/p&gt;  &lt;p&gt;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.&lt;/p&gt;  &lt;p&gt;First, the one-stop-universal-arguments helper, which we can add to the source from before:&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td class="gsCodeTitle"&gt;Scripting.js &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;         &lt;pre class="brush: js;"&gt;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 = &amp;quot;&amp;quot;;

    if (arguments.length == 1) {
        if (typeof (args) == &amp;quot;object&amp;quot;) {
            args = ArgsToArray(args);
            result = &amp;quot;&amp;quot; + (args.shift());

            if (args.length == 1 &amp;amp;&amp;amp; arguments[0].length &amp;gt; 0)
                args = arguments[0];

            return result.Format(args);
        } else return (&amp;quot;&amp;quot; + args).Format();
    } else if (arguments.length == 2) {
        if (typeof (args) == &amp;quot;string&amp;quot; &amp;amp;&amp;amp; typeof (moreargs) == &amp;quot;object&amp;quot;) {
            result = args;
            args = ArgsToArray(moreargs);
            args.shift();

            return result.Format(args);
        }
    }
    throw &amp;quot;Invalid Argument passed to FormatArguments&amp;quot;;
}&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;br /&gt;

&lt;p&gt;&lt;strong&gt;FormatArguments()&lt;/strong&gt;&amp;#160; 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:&lt;/p&gt;

&lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td class="gsCodeTitle"&gt;Test-4.js&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;
        &lt;pre class="brush: js;"&gt;// use the first string as the format string, 
// the rest are potential value substitutions
function Test1() {
    var foo = FormatArguments(arguments)
    WScript.echo( foo );
}

Test1(&amp;quot;the path is {$PATH}&amp;quot;);

// 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 = &amp;quot;Copy {0} to {1}&amp;quot;.Format(srcfile, destfile);
    WScript.echo(msg);
}

Test2(&amp;quot;{$WINDIR}\\system32\\notepad.exe&amp;quot; , &amp;quot;{$USERPROFILE}\\desktop\\notepad.exe&amp;quot;);&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Knowing that, we can create a few functions that will use the FormatArguments function:&lt;/p&gt;

&lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td class="gsCodeTitle"&gt;Scripting.js&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;
        &lt;pre class="brush: js;"&gt;// Some global objects we'll need 
var WSHShell = WScript.CreateObject(&amp;quot;WScript.Shell&amp;quot;);
var WinShell = WScript.CreateObject(&amp;quot;Shell.Application&amp;quot;);
var procEnvironment=WSHShell.Environment(&amp;quot;PROCESS&amp;quot;)
var fso = new ActiveXObject(&amp;quot;Scripting.FileSystemObject&amp;quot;);

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);
}&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Now, we can do some pretty nifty little batch scripting:&lt;/p&gt;

&lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td class="gsCodeTitle"&gt;test-5.js&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;
        &lt;pre class="brush: js;"&gt;// Bootstrap Scripting Library
eval(new ActiveXObject(&amp;quot;Scripting.FileSystemObject&amp;quot;).OpenTextFile(&amp;quot;Scripting.js&amp;quot;, 1, false).ReadAll());

$ORIG_DIR = pwd();

if( exists(&amp;quot;{$WINDIR}\\log.txt&amp;quot;) ) {
    Print(&amp;quot;Deleting log file&amp;quot;);
    erase(&amp;quot;{$WINDIR}\\log.txt&amp;quot;);
}

mkdir(&amp;quot;{$TEMP}\\tempdir&amp;quot;);&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Next time, we’ll see how we can call on command-line tools to do our bidding, and play with the results.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9625922" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/garretts/archive/tags/scripting/default.aspx">scripting</category><category domain="http://blogs.msdn.com/garretts/archive/tags/JScript/default.aspx">JScript</category></item><item><title>Using JScript as a batch scripting language (Part II)</title><link>http://blogs.msdn.com/garretts/archive/2009/05/15/using-jscript-as-a-batch-scripting-language-part-ii.aspx</link><pubDate>Sat, 16 May 2009 02:17:56 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9620215</guid><dc:creator>GarrettS</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/garretts/comments/9620215.aspx</comments><wfw:commentRss>http://blogs.msdn.com/garretts/commentrss.aspx?PostID=9620215</wfw:commentRss><description>&lt;p&gt;Last time, I wrote about synthesizing an &lt;strong&gt;&lt;em&gt;#include &lt;/em&gt;&lt;/strong&gt;facility along with handling environment variables in a trivial way.&lt;/p&gt;  &lt;p&gt;This time, let’s look at filling in a couple more gaps in JScript’s basic scripting functionality. &lt;/p&gt;  &lt;h4&gt;&lt;u&gt;What’s wrong with String?&lt;/u&gt;&lt;/h4&gt;  &lt;p&gt;The String class in JavaScript/JScript is … ok. If you work in .NET enough, you’ll eventually get to the point where you’d like a couple of functions that seem to be missing. First, is &lt;strong&gt;Trim&lt;/strong&gt;, which I’ve always thought as obvious:&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td class="gsCodeTitle"&gt;Scripting.js – String Prototypes&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;         &lt;pre class="brush: js;"&gt;//----------------------------------------------------------------------------&lt;br /&gt;// String Prototypes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;String.prototype.Trim = function() {
    return (this || &amp;quot;&amp;quot;).replace(/^\s+|\s+$/g, &amp;quot;&amp;quot;);
}&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;And secondly, is something I miss dearly from when I’m in .NET, is a string &lt;strong&gt;Format &lt;/strong&gt;function. Now, I’ve seen a couple of these that were pretty simple, but I wanted to be able to do some really cool Format strings (and, since the rest of my scripting will rely on them quite a bit, I’m going for the gold here.&lt;/p&gt;

&lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td class="gsCodeTitle"&gt;Scripting.js – String Prototypes&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;
        &lt;pre class="brush: js;"&gt;String.prototype.Format = function() {
    var args = (arguments.length == 1 &amp;amp;&amp;amp; typeof (arguments[0]) == &amp;quot;object&amp;quot;) ? arguments[0] : arguments;

    result = this;
    while (z = /{(.*?)}/.exec(result))
        try { result = result.replace(z[0], isNaN(z[1]) ? eval(z[1]) : (args[z[1]]||&amp;quot;??&amp;lt;&amp;quot; + z[1] + &amp;quot;&amp;gt;??&amp;quot; )); }
    catch (x) { result = result.replace(z[0], &amp;quot;??&amp;lt;&amp;quot; + z[1] + &amp;quot;&amp;gt;??&amp;quot;); }
    return result.replace(&amp;quot;??&amp;lt;&amp;quot;, &amp;quot;{&amp;quot;).replace(&amp;quot;&amp;gt;??&amp;quot;, &amp;quot;}&amp;quot;);
}&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;So, with this tasty little script in my pocket, I can do ad-hoc format strings that use one of a few types of replacement:&lt;/p&gt;

&lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td class="gsCodeTitle"&gt;test-3.js&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;
        &lt;pre class="brush: js;"&gt;// simple parameter # replacement like .NET
var foo = &amp;quot;My Name is {0}. Please to meet you {1}&amp;quot;.Format(&amp;quot;Garrett&amp;quot;, &amp;quot;Mr. Serack&amp;quot;);
WScript.echo(foo);

// *global* variable replacement
ABC = &amp;quot;this is a test&amp;quot;;
var bar = &amp;quot;'{ABC}' is really a replacement string&amp;quot;.Format();
WScript.echo(bar);

// really, any legal expression in there is fine.
bar = &amp;quot;'{100+200/75}' is really a replacement value?&amp;quot;.Format();
WScript.echo(bar);

// and if it doesn't match, just leave it alone...
bar = &amp;quot;'{teehee}' isn't really a replacement value.&amp;quot;.Format();
WScript.echo(bar);

// even if it's just a number.
bar = &amp;quot;'{1}' isn't really an index.&amp;quot;.Format();
WScript.echo(bar);&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Which spits out the following:&lt;/p&gt;

&lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td class="gsCodeTitle"&gt;Ouptut&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="border-bottom: #060 1px solid; border-left: #060 1px solid; border-top: #060 1px solid; border-right: #060 1px solid" valign="top" width="100%"&gt;
        &lt;pre class="brush: js;"&gt;My Name is Garrett. Please to meet you Mr. Serack
'this is a test' is really a replacement string
'102.66666666666667' is really a replacement value?
'{teehee}' isn't really a replacement value.
'{1}' isn't really an index.&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Basically, it just looks for anything in braces, and checks to see if it’s a number. if it is, it tries to substitute in the n’th parameter passed in. Otherwise it just does an &lt;strong&gt;eval() &lt;/strong&gt;on it—which, will replace expressions, or global variables. If something goes haywire, it just leaves it alone (well, it does some switcheroo stuff to get past the while loop, but it puts it back in the end). &lt;/p&gt;

&lt;p&gt;Next time, we’ll see how to use this… &lt;em&gt;everywhere&lt;/em&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9620215" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/garretts/archive/tags/scripting/default.aspx">scripting</category><category domain="http://blogs.msdn.com/garretts/archive/tags/JScript/default.aspx">JScript</category></item></channel></rss>