PowerShell_2 Welcome to this addition of the PowerShell ABC's where you'll find 26 posts detailing a component of the PowerShell scripting language, one letter at a time.  Today's letter is the letter "J".  Bet you thought I was going to go with Jagged Arrays for this one huh?  Nope!  Today's word is JavaScript.

Huh?  You may ask why I would pick JavaScript since that is a completely different scripting language and this is a series on PowerShell features.  Well, I'm glad you asked.  PowerShell is a very extensive scripting language, but it is relatively new to the scene of windows systems management.  Before PowerShell, network administrators used a combination of other scripting languages to manage their systems from simple batch files to more advanced VBScripts.  The ability to integrate the older scripts into PowerShell can be very valuable during the transition process of moving from old processes to newer ones.  Luckily for all you out there with VBScript to maintain, PowerShell has the ability to integrate those scripts directly into it's scripting environment with it's access to the COM libraries and specifically the ScriptControl control.  With the help of the New-Object Cmdlet, one can embed fragments of VBScript into a PowerShell script.

Here's an example

function Create-VBScript()
{
  param([string]$code = $null);
  if ( $code )
  {
    $sc = New-Object -ComObject ScriptControl;
    $sc.Language = "VBScript";
    $sc.AddCode($code);
    $sc.CodeObject;
  }
}

PS> @vbcode = @"
Function vblen(ByVal s)
  vblen = Len(s)
End Function
"@
PS> $vbs = Create-VBScript $vbcode;
PS> $str = "abcd";
PS> $vbs.vblen($str);
4

jscript-file-256x256 You'll see in the above code, I've defined a VBScript function called vblen that returns the length of a string.  with the included Create-VBScript function, I've created a VBScript ScriptControl object and stored that in the $vbs variable.  I then created a PowerShell string $str with the contents of "abcd" which is then passed into the VBScript function vblen and the length is returned to the output.  Pretty cool huh!

So, by now are you likely wondering why I used JavaScript since I've talked solely about VBScript.  Well, the ScriptControl object is able to work with any language that has a ActiveScript engine which includes JavaScript.  By changing the Language on the ScriptControl object to "JScript", you can be working in JavaScript just as easily as VBScript.  Here's a more generic function that let's you specify the language.

function Create-ScriptEngine()
{
  param([string]$language = $null, [string]$code = $null);
  if ( $language )
  {
    $sc = New-Object -ComObject ScriptControl;
    $sc.Language = $language;
    if ( $code )
    {
      $sc.AddCode($code);
    }
    $sc.CodeObject;
  }
}
PS> $jscode = @"
function jslen(s)
{
return s.length;
}
"@
PS> $js = Create-ScriptEngine "JScript" $jscode;
PS> $str = "abcd";
PS> $js.jslen($str);
4

I'm sure there are some interesting combinations of PowerShell with JavaScript and VBScript.  Imagine combining Google Analytics into your PowerShell script and being able to use their services to track all that use your PowerShell script.

Function Get-UrchinCode()
{
  $url = "http://www.google-analytics.com/urchin.js";
  [System.Net.WebClient]$webClient = New-Object System.Net.WebClient
  [System.IO.Stream]$stream = $webClient.OpenRead($url);
  [System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $stream;
  $sr.ReadToEnd();
}
$urchinCode = Get-UrchinCode;
$urchinCode += "_acct = `"UA-XXXXX-1`";";
$js = Get-ScriptControl "JScript" $urchinCode;
$js.urchinTracker();

There is one thing from stopping this from working, the Google Analytics tracking code relies on the browser's document extensions to JavaScript to determine the info about the referenced page.  But, one could create a separate set of JavaScript that implemented the relevant features of the document object so that the urchinTracker script could function.  I'll leave this as an exercise to the reader.  If anyone implements it, let me know and I'll post it here!