Windows 2000: Script Heaven

 

Andrew Clinick
Microsoft Corporation

February 14, 2000

Download Win2kclinic.exe.

Contents

Windows Script
What's Scriptable in Windows 2000?
Web Development
Scripting the Operating System
Summary

The Windows Script Team has been working on Windows 2000 and its related script technologies for quite a while now (certainly a lot longer than we first thought—but better late than never!). This week's release of Windows 2000 represents the culmination of Microsoft's first attempt at providing a truly scriptable operating system. To celebrate the launch, I thought I'd take you on whistle-stop tour of Windows 2000 from a script perspective and show you how you can use your script knowledge to develop Web applications, administer them, and do a few things you probably didn't think script could do.

Windows Script

The core of the scripting support in Windows 2000 is the inclusion of all the Windows Script Technologies and COM+. COM+ provides the plumbing for a whole bunch of applications and services in Windows, and Windows Script provides the glue for taking advantage of those cool COM+ services. To briefly recap: Windows 2000 ships with version 5.1 of Windows Script, which includes:

  • Visual Basic® Scripting Edition (VBScript)
  • JScript®
  • Windows Script Runtime (including the File System Object and Dictionary)
  • Windows Script Host (WSH) 2.0
  • Windows Script Components
  • Windows Script Debugger
  • Windows Script Control

That's all of our scripting technologies—bar Remote Scripting (which is only a small download away)—and Windows will include all of these in all future releases. To protect the integrity of your Windows installation, they are now System File Protected (SFP). SFP means that you can't delete any file covered by the scheme—and even if you delete it or overwrite it with an older version (perish the thought), Windows 2000 will replace it with the version that ships with Windows 2000. This is great in that it makes it very difficult for an errant application to come along and just overwrite files, potentially causing problems for other applications on the machine.

Being a part of the system is a double-edged sword, though, since it means that you can't just upgrade your component without an upgrade of Windows. As a result, the script engines will now start to upgrade on the Windows schedule. This means slightly longer development times, but allows us to concentrate more on quality—something we hope that users will like.

What's Scriptable in Windows 2000?

The short answer is: just about everything. I'll break my guided tour of the script sites in Windows into two sections: Web development and scripting the operating system. This is an obvious oversimplification of what's available, but it's a good start and will hopefully give you a flavor of what's possible. In each section, I'll offer examples and links to the Web sites that provide more in-depth documentation and samples.

Web Development

The Web has probably driven the growth of scripting more than any other technology in the past few years. It started with early CGI programs written in Perl, progressing to Active Server Pages (ASP) technology and Dynamic HTML (DHTML) in the browser. The Web is moving so quickly that people find building a program with script allows them to keep up with the pace—and somehow writing throw-away code seems a bit more palatable when you've written it in a script language.

Windows 2000 provides a great platform for building Web services, and particular attention has been focused on making it easy to develop robust services that will scale to meet your requirements. The core to all this is COM+ and ASP, which I'm sure many of you are already familiar with through using Internet Information Server (IIS) 4.0. For Windows 2000, the ASP team really concentrated on making its technology as reliable as possible, and spent much of their time investigating how to make the server less prone to crashing and memory leaks. We worked very closely with the ASP team to eliminate as many bottlenecks as we could between script and ASP. The version of script and ASP in Windows 2000 has been stress-tested by both Microsoft.com and many customers for a long time now, and we've worked hard to ensure that any holes exposed by the stress testing are now closed.

In addition to reliability, we took the time to increase the performance of the script engines when used within IIS. This work included early binding to the response.write and response.writeblock, methods which are used in just about every ASP page, and in the results, we're seeing up to 300 percent performance increases in ASP throughput. This is a general figure, and not all your pages will get a 300 percent performance increase, but your pages should speed up noticeably just by running on Windows 2000.

The ASP folks took the time to add a few features to the ASP object model that enable easier development on the server. There are a couple of methods that stand out for me: Server.Execute and Server.Transfer. Server.Execute allows you to call a different ASP file as if it were part of the same ASP file, which means you can use ASP pages as "components" on the server. Here's a really simple example:

On the client: test.asp

<html>
<%server.execute "date.asp" %>
</html>

On the server: date.asp

Today's date is <%=formatdatetime(now)%>

This is not a particularly exciting demo, but you could extend it. For example, you could use this feature to provide a template mechanism for your ASP pages that always called headline.asp, which would returned the latest headlines.

The next logical step from executing another ASP page as if it were in the same ASP page is to transfer control from one page to another. Luckily Server.Transfer does exactly this. When called, all the state information from the calling page is transferred to the called page. This makes for simpler programming, because you don't have to worry about how to get information between the pages. Just assign your information to session variables, and you're set. Here's a simple example (with apologies to any Scottish rugby fans out there):

<html>
<form method="POST" action="transfer.asp">
<p>Get me the sports news</p>
<p><input type="radio" value="UK" checked name="country">UK</p>
<p><input type="radio" name="country" value="US">US</p>
<p><input type="submit" value="Submit" name="B1">_
    <input type="reset" value="Reset" name="B2"></p>
</form>
<%
select case request.form("country")

case "UK"
   server.transfer "uk.asp"
case "US"
   server.transfer "us.asp"

end select

%>

</html>

UK.asp

<%Server.execute "date.asp"%>
<h1>England beat Ireland in thrilling encounter</h1>
<h1>Scotland goes back to drawing board after Italian upset</h1>

US.asp

<%Server.execute "date.asp"%>
<h1>St Louis wins the Superbowl</h1>
<h1>TIger Woods takes 5</h1>

Depending on the user input, the ASP page transfers the request onto either US.asp or UK.asp, which then returns the relevant information for the selected country and the generated HTML is sent to the client.

Windows 2000 Server comes with ASP preinstalled, as well as a number of very useful COM+ components that simplify Web service development. If you've ever done any ASP development, you are sure to know that ActiveX® Data Objects (ADO) has been updated for Window 2000 to version 2.5. There's a wealth of information on ADO on the MSDN Web site, so I won't go into detail here.

Increasingly, people are providing e-mail solutions on their Web sites, and Windows 2000 provides a simple object model, Collaboration Data Objects (CDO), for manipulating the SMTP server. The great thing about CDO is that it is scalable from the SMTP server that comes with Windows 2000 Server all the way through to Exchange, so your e-mail solution on your Web server can grow with your requirements. For more info on CDO, check out Introduction to CDO for NTS in the MSDN Online Library.

Finally, where would any Web development platform be without some form of XML story? Windows 2000 has XML and XSL built in, so you can take advantage of this exciting new technology both on the client and on the server. I'm not even going to try to compete with Charlie Heinemann on explaining XML, so you should check out his article on What's new in Windows 2000.

The combination of these powerful object features and script make Windows 2000 the most flexible Web development platform yet from Microsoft, and hopefully this whistle-stop tour of Windows 2000 highlights will give you some hints into developing great solutions.

Scripting the Operating System

You've started to use the new services available in Windows 2000 and your Web site is about to go live on your Web server farm. Great—but how are you going to administer the site? Previously, this hasn't been the easiest thing to accomplish with the Windows NT® operating system, but manageability was a major focus for Windows 2000. I've written in the past about the wonders of the ADSI-WMI combination, but I've given only examples of how to use theose technologies. For this article, I thought I'd try and provide a more in depth sample that you could actually use.

One of the nightmare scenarios for all administrators is when a server stops responding—and no matter how many times you press the stop button in the management console, the errant process refuses to shut down. Those of you familiar with Unix are probably thinking, "I'd just run PS, get the process ID, and then kill it." Unfortunately, Windows 2000 doesn't come with those utilities built in. It does provide all the right components to achieve the same result—and with a little script, we can recreate these features.

Writing PS in script is reasonably simple with Windows Management Instrumentation (WMI). You just have to query the Win32_process service. This returns a collection of all the processes that are running on the machine. The script to return the process name and ID looks like this:

VBScript

set objService = getobject("winmgmts:")

for each Process in objService.InstancesOf("Win32_process")
   WScript.echo Process.Name & vbTab & Process.processid
Next

JScript

var e= new Enumerator(GetObject("winmgmts:").InstancesOf("Win32_process"))

for (;!e.atEnd();e.moveNext())
{
   var Process = e.item();
   WScript.echo (Process.Name + "\t" + Process.processid)
}

Once we get the process ID, we need to be able to kill the process. Writing kill in script is a little more complex than returning the processes—but only slightly, as it still uses the Win32_process object. I've attached a full blown kill.vbs and ps.vbs that you can use for more details.

This is all well and good—but what about if the server you're trying to administer is not the machine on which you're running? This has typically been hard to achieve and has often involved using telnet to access the server or launching some form of remote console to access the server. WMI provides an interface that you can use remotely, so that you can run the script on your machine and, if you have the right privileges, actually administer a remote machine. The PS and kill scripts I provided with this article allow you to specify a server name, query a remote server for its processes, and then issue a kill command—all from the comfort of your own office.

The command line integration offered by Windows Script Host allows you to run existing scripts easily. What about those times when you just want to run some script immediately without first saving it to a file. Currently the command shell doesn't have this ability (although it's something we want to work in future releases of WSH), but WSH makes it pretty easy to write a simple script program that takes a script as it's input, runs the script, and returns the result to the command line. Whilst I was thinking about what to write in this article, my colleague Peter Torr just happened to mention that he'd written such a script—so in the best traditions of script, I've "borrowed" his code (thanks, Peter!).

Essentially, each script (js.wsf for JScript and vbs.wsf for VBScript) takes the script passed in as an argument and uses the language's run-time evaluation routines to evaluate and run the code. To deal with the need to pass in quoted strings, Peter chose the # character to represent quotes, and then used a regular expression to replace all instances with quotes. That's about all the script needs to do, but it provides a great way to run some script without having create and save the .wsh file.

VBScript

<job>
   <script id="main" language="vbscript">

      If (WScript.Arguments.Length < 1) Then
         Print("Usage: runcode <script code> [/e]" & vbNewLine _
            & "  Where [/e] can be used to evaluate (rather than _
            execute) the code." & vbNewLine _
            & "  Use the hash (pound) character for embedded quotes." & vbNewLine _
            & "  eg, vbs ""Print(#Hello, World#)""")

         WScript.Quit(1)
      End If

      Dim s, re, evaluate

      ' Is there a "please print the result" argument?
      evaluate = False
      If (WScript.Arguments.Length > 1) Then
         s = WScript.Arguments(1)
         If (UCase(Right(s, 1)) = "E") Then
            evaluate = True
         End If
      End If

      s = WScript.Arguments.Item(0)

      set re = New RegExp
      re.Pattern = "#"
      re.Global = True

      s = re.Replace(s, """")

      Print("Running code: '" & s & "'" & vbNewLine & "-----")

      If (evaluate) Then
         s = Eval(s)
         Print("Result: " & s)
      Else
         ExecuteGlobal(s)
      End If

      Sub Print(str)
         WScript.Echo(str)
      End Sub

   </script>
</job>

JScript

<job>
   <script id="main" language="jscript">

      if (WScript.Arguments.Length < 1)
      {
         print("Usage: js <script code>\n"
            + "  Use the hash (pound) character for embedded quotes.\n"
            + "  eg, runcode \"WScript.Echo(#Hello, World#)\"");

         WScript.Quit(1);
      }

      var s = WScript.Arguments.Item(0);

      s = s.replace(/#/g, "\"");

      print("Running code: '" + s + "'\n-----");

      var x = eval(s);

      if (typeof(x) != "undefined")
         print("-----\nResult: " + x);

      function print(str)
      {
         WScript.Echo(str);
      }

   </script>
</job>

Summary

Windows 2000 provides you with a host of scriptable objects that make Web-service development easier than ever before. The inclusion of scripting in the operating system means that you can rely on a base set of objects and a language to glue them together on every Windows machine, server or workstation. We're working hard on improving this further with future releases—so if we're missing something, please tell us either by the feedback form on this article or by e-mail at msscript@microsoft.com.

 

Scripting Clinic

Andrew Clinick is a program manager in the Microsoft Script Technology group, so chances are, if there's script involved, he's probably had something to do with it. He spends most of his spare time trying to get decent rugby coverage on U.S. television and explaining cricket to his new American colleagues.