Windows Server 2008 Server Core : Working with Scripts - Testing Scripts

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
11/12/2012 2:53:42 AM
Scripting languages provide far more than batch files do in the way of flow control and error handling support. In addition, you can debug your scripts with greater ease because Microsoft includes a script debugger with Windows. If you find this script debugger a tad limited (many people do), you can also use third-party utilities to debug your scripts. You can learn more about the Microsoft Script Debugger at The following sections discuss some script techniques you can use to create robust script applications in a command line environment.

1. Mapping a Network Drive

You can map a network drive using a batch file, but it's more difficult and error prone than using a script. A script can provide one thing that a batch file can't in this case, great interactivity. Using a script lets you interact with the user in a way that would be difficult using a batch file. In addition, the script provides a modicum of additional error handling support that makes error handling easier. Listing1 shows a typical example of how you can implement this functionality using JavaScript.

Using Scripting Effectively

Sometimes you do need to use scripting techniques to ensure you get the right results from your command line activities. The best rule of thumb to follow is that anything that requires direct application access through something other than command line switches requires a script, rather than a batch file. In addition, if you've just spent five hours trying to get a batch file to work and feel that you still haven't made any progress, then perhaps you're not using the right tool for the job.

It's this second point where many people get into endless discussions about the suitability of one technique over another. In many cases, it's part personal preference and part skill or special need. For example, at one time some people tried to use spreadsheets in place of word processors (it really was common in the 1980s). However, anyone who has used both products today knows that each tool has a particular job to perform and it's better to use the right tool for the job. The same rule applies to scripts versus batch files. You might be able to use batch files to meet most of your needs, but eventually, you'll run into a complex task that simply requires a script to perform adequately.

Example 1. Mapping a Network Drive with JavaScript
// Define the network object used to map the drive.
var oNetwork = new ActiveXObject("WScript.Network");

// Detect a request for command line help.
if (WScript.Arguments.length == 1)
    if (WScript.Arguments(0) == "/?")
          // Display the help information
          WScript.Echo("Usage: MapNetwork <letter> <UNC target>\n");

          // Exit the script and provide an error level of 1 to
          // indicate a help request.
          // Display an error message.
          WScript.Echo("Input argument is unknown.");
          WScript.Echo("Usage: MapNetwork <letter>  <UNC target>\n");

          // Exit the script and provide an error level of 2 to
          // indicate  a data entry error.
// Create variables to hold the drive letter and the UNC location.
 var DriveLtr;
 var UNCName;

// Detect the correct number of input arguments.
if ( WScript.Arguments.length < 2 )
    // Ask whether the user wants to continue.
    WScript.Echo("No input provided! Provide it interactively? [Y | N]")
;   var Answer = WScript.StdIn.ReadLine();


// If the user doesn't want to continue, display help and exit.
    // Use an exit code of 2 to indicate a data entry error.
    if (Answer.toUpperCase() == "N")
       WScript.Echo("Usage: MapNetwork <letter>  <UNC target>\n");
    // Input the drive letter.
    WScript.Echo("Type the local drive letter (X:).");
    DriveLtr = WScript.StdIn.ReadLine();

    // Input the UNC drive on the remote machine.
    WScript.Echo("Type the UNC location (\\MyServer\MyDrive).");
    UNCName = WScript.StdIn.ReadLine();
    // Obtain the required inputs from the command line.
    DriveLtr = WScript.Arguments(0);
    UNCName = WScript.Arguments(1);

// Tell the user which drive is mapped.
WScript.Echo("Mapping drive " + DriveLtr + " to " + UNCName);

// Attempt to create the connection.
    // Perform the drive mapping function.
    oNetwork.MapNetworkDrive(DriveLtr, UNCName);
    // Display an error when the task fails.
    WScript.Echo("Couldn't map the drive!\n" + e.description);


The example begins by creating a network object to create the connection. In this case, the code uses the new ActiveXObject() method. You can also use WScript.CreateObject() to perform the same task. The method you use depends on personal taste in most cases. This example uses the ActiveXObject() method for the sake of completeness. If you want to use the other method, you would replace this line of code with var oNetwork = WScript.CreateObject("WScript.Network");.

Of course, you also need to handle the case where someone provides a single input, but it isn't the /? command line switch. The code displays a special error message along with the same help that you would normally display for the /? command line switch. Notice that in this case the script exits with an error level of 2. Using a different error level lets you trap this particular problem in a batch file.

At this point, the code begins looking at the input. The input must provide two arguments to map a network drive to a local drive letter. Consequently, when the script detects two input arguments, it places them in the appropriate variables and attempts to map the network drive. You might wonder why the script doesn't perform all kinds of odd error checking on the input arguments. The try...catch statement is the secret in this case. If the user provides incorrect input, the oNetwork.MapNetworkDrive(DriveLtr, UNCName) call fails and the catch part of the statement traps the error. The script displays an error message in this case and exits again. Because this is another kind of error, the script sets the error level to 3. Notice that the script conveniently disregards any more than two inputs.

At this point, all the code needs to handle is the case where the user doesn't provide any input arguments. This is where the interactive features of scripting pay off. The script begins by asking the user whether they want to provide the input interactively. If so, the code asks some simple questions and tries to map the drive. If not, the code exits with a help message and an error level of 2. The reason the script uses an error level of 2 is that this is the same kind of error as providing a single input that isn't the /? command line switch.

2. Creating a CSV File

Sometimes it's important to see the same example using two different techniques.  When you compare the code in Listing 2 with the code in 5.7, you'll notice that Listing 6.4 is significantly longer, even though it produces the same output. In addition, the code in Listing 2 is significantly more complex. However, if you perform just these two comparisons, you'll miss some of the reasons to use scripts. Mostly notably, the script version demonstrates the flexibility that this form of coding can provide. For example, you have more control over the files. The input files are read only, which means that the code can't damage them, even accidentally. Consequently, the files are safer than when you use a batch file to manipulate them. Listing 2 shows the script version of the CSV output example.

Example 2. Creating CSV Output Using a Script
// Create a File System Object to work with files.
var FSO = WScript.CreateObject("Scripting.FileSystemObject");

// Determine whether the Output2.CSV file exists and delete it.
if (FSO.FileExists("Output2.CSV"))
   FSO.DeleteFile("Output2.CSV", false);

// Create a WshShell object to obtain environment variables.
var Shell = WScript.CreateObject("WScript.Shell");

// Create variables to hold the static data.
var CompName = Shell.ExpandEnvironmentStrings("%COMPUTERNAME%");
var UserName = Shell.ExpandEnvironmentStrings("%USERNAME%");
var DateTime = new Date();

// Obtain the list of file specifications.
WScript.Echo("Locating temporary files to delete.");
var DirSpec = FSO.OpenTextFile("DelFiles.TXT", 1);

// Process each entry in the file.
while (!DirSpec.AtEndOfStream)
   // Get a single file specification.
   var ThisSpec = DirSpec.ReadLine();

   // Process the directory specification.
   WScript.Echo("Adding database values for " + ThisSpec);
      "Cmd /C Dir " + ThisSpec + " /B /S >  TmpDirFiles.TXT", 0, true);

   // Open the file containing the individual file entries.
   var Files = FSO.OpenTextFile("TmpDirFiles.TXT", 1);

   // Open the CSV file to accept the file entries.
   var Output = FSO.OpenTextFile("Output2.CSV", 8, true);

   // Process each of the file entries in turn.
   while (!Files.AtEndOfStream)
      // Get an individual file entry.
      var File = Files.ReadLine();

      // Create the CSV file entry. Begin with the computer name and
      // the username.

      // Processing the date requires a little additional work. You
      // must extract the individual elements and put them together as
      // desired. Begin by converting the day number to a day string.
      var DayNum = DateTime.getDay();
      switch (DayNum)


case 0:
           Output.Write("Sun ");
        case 1:

           Output.Write("Mon ");
        case 2:
           Output.Write("Tue ");
        case 3:
           Output.Write("Wed ");
        case 4:
           Output.Write("Thu ");
        case 5:
           Output.Write("Fri ");
        case 6:
           Output.Write("Sat ");

      Output.Write(DateTime.getMonth() + 1);
      Output.Write("/" + DateTime.getDate() +
                   "/" + DateTime.getFullYear());

      // Extract the time from DateTime.
      Output.Write(DateTime.getHours() + ":" +
                  DateTime.getMinutes() + ":" +

      // Finally, add the filename to the output.
   // Close the working files
// Close the file containing the file specifications.


The code begins by removing any existing output file. JavaScript and VBScript lack file support. However, you have access to the Scripting.FileSystemObject object, which does provide full file system support. You can use this object to perform a multitude of tasks with files, including creating, deleting, and editing them. The FileSystemObject also includes functionality for working with folders.

The next step is to retrieve the username, computer name, date, and time. In many cases, you can simply use the ExpandEnvironmentStrings() method to obtain the information you need from the system. Notice that the example code uses the Date object in place of obtaining the date from the environment variables using the Shell.ExpandEnvironmentStrings("%DATE%") method. When working with JavaScript, you can only access the environment variables that you can see with the Set command. JavaScript doesn't support the extended functionality that's available at the command line. In fact, you'll find that this general rule applies to both VBScript and JavaScript; neither scripting language supports the extensions that you can access from a batch file at the command prompt. The Date object also provides time support, so you don't need a separate Time variable.

At this point, it's time to begin collecting a list of temporary files on the system. This example, like its batch file counter, relies on an external file to hold the file specifications. The code opens the file and begins processing it one line at a time. The use of a constant value of 1 for the FSO.OpenTextFile() method opens the file in read-only mode. The code processes the file one line at a time (one file specification at a time) using the DirSpec.ReadLine() method. You can read one character at a time using the DirSpec.Read() method instead.

This example points out a very special feature of the scripting languages. Notice the use of the Shell.Run() method. You can use this method to run any application. To use this feature at the command prompt, you have to begin by creating a command processor using the CMD utility as shown. In this case, the code runs the Dir command with the file specification obtained from DelFiles.TXT. This line of code begs the question of why the code doesn't use the FileSystemObject. In this particular case, you can perform the task faster and without any loss of functionally by using the Dir command. The point is that you don't always have to use a scripting object; sometimes a command line tool works just as well or even better.

The code now has two files to work with. The first is an input file, TmpDirFiles.TXT, which contains the list of temporary files. The second is an output file, Output2.CSV, which contains the database of file entries. The FSO.OpenTextFile() constant of 8 opens the file in append (read/write) mode. If the file doesn't exist, the code raises an error unless you also set the third argument to True, which tells the method to create the file when it doesn't exist.

Now all the code needs to do is process the data and output it. The user and computer names are straightforward. Processing the date requires the most code because the code has to put the date string together. The downside of all this code is that it makes the example harder to read than the batch file. The plus side is that you can create a date string in any format required, even nonstandard formats.

As a final note on this example, make sure you close files when you finish working with them. Otherwise, the script raises an error when you try to open the file again. In some cases, the file could remain open until you reboot the system, making it inaccessible to everyone.

  •  Windows Server 2008 Server Core : Working with Scripts - Impersonating a User with the RunAs Utility, Changing the Environment
  •  Switching to Microsoft Windows 7 : Migrating Applications and Data to a New Windows 7 Computer (part 2)
  •  Switching to Microsoft Windows 7 : Migrating Applications and Data to a New Windows 7 Computer (part 1)
  •  Switching to Microsoft Windows 7 : Migrating Data on a Single Computer
  •  The Download Directory - November 2012 (Part 3) - Multiplicity 2.0, LastPass Password Manager 2.0.0
  •  The Download Directory - November 2012 (Part 2) - UltraVNC Beta, Firefox 16 Beta 3, BlueScreenView 1.45 Description: BlueScreenView
  •  The Download Directory - November 2012 (Part 1) - USB Disk Security 6.2, WindowBlinds 7.4
  •  Windows Vista : Migrating User State Data - Developing Migration Files, Using USMT in BDD 2007
  •  Windows 7 : Sharing Resources on a Network - Using Public Folders, Identifying Shared Folders, Sharing a Printer
  •  Windows 7 : Sharing Resources on a Network - Windows 7 Homegroups
    Top 10
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
    - Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
    - Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    programming4us programming4us