Section 9.2. Object References


9.2. Object References

There are some operations that can be performed with the Windows Script Host regardless of the language being used. These operations, such as accessing the filesystem, are made possible by extending the language with objects. For the time being, we can consider an object to be simply a context that is referred to when carrying out certain commands.

Admittedly, this can make carrying out some tasks rather difficult and convoluted, but it is necessary given the modular architecture of WSH. For example, many scripts will require a line similar to the following (using VBScript syntax in this case):

Set WshShell = WScript.CreateObject("WScript.Shell")

which creates and initializes the WshShell object. WshShell is not a visible object like a file or other component of Windows, but rather a required reference used to accomplish many tasks with WSH, such as running programs, creating Windows shortcuts, and retrieving system information.

If you're unfamiliar with object references, your best bet is to simply type them as shown and worry about how they actually work when you're more comfortable with the language. The subsequent topics include many solutions that take advantage of objects, such as WScript.Shell, which has many uses, and Scripting.FileSystemObject, used for accessing files, folders, and drives.

9.2.1. Running Applications from Scripts

This code is used to run a program, which can be a DOS program, a Windows application, an Internet or mailto URL, or anything else you might normally type in the Start Menu's Run command or Explorer's Address Bar. Place this subroutine in your scripts:

Sub RunProgram(Filename, Wait)   Set WshShell = WScript.CreateObject("WScript.Shell")   RetVal = WshShell.Run(Filename, Wait) End Sub

and call the routine like this:

Call RunProgram("c:\windows\notepad.exe", True)

You can replace true with False if you don't want to wait for the program to finish before the next script command is executed.

9.2.2. Accessing the Registry from Scripts

The following code is used to write, read, and delete information in the Registry. Include the following three routines in your script:

Sub RegistryWrite(KeyName, ValueName, ValueData, ValueType)   ValueType = UCase(ValueType)   If ValueType <> "REG_DWORD" and ValueType <> "REG_BINARY" Then _                                                    ValueType = "REG_SZ"   Set WshShell = WScript.CreateObject("WScript.Shell")   WshShell.RegWrite KeyName & "\" & ValueName, ValueData, ValueType End Sub Function RegistryRead(KeyName, ValueName)   Set WshShell = WScript.CreateObject("WScript.Shell")   RegistryRead = WSHShell.RegRead(KeyName & "\" & ValueName) End Function Sub RegistryDelete(KeyName, ValueName)   Set WshShell = WScript.CreateObject("WScript.Shell")   WshShell.RegWrite KeyName & "\" & ValueName, ""   WshShell.RegDelete KeyName & "\" & ValueName End Sub

Using these three routines, you can accomplish nearly all Registry tasks. To create a Registry key, type this (note that all HKEY... roots must appear in uppercase):

Call RegistryWrite("HKEY_LOCAL_MACHINE\Software\My Key", "", "", "")

To assign data to a Registry value:

Call RegistryWrite("HKEY_LOCAL_MACHINE\Software\My Key", "My Value", _                                                     "Some Data", "")

Leave "My Value" blank to set the (default) value. To read the data stored in a given value:

Variable = RegistryRead("HKEY_LOCAL_MACHINE\Software\My Key", "My Value")

Leave "My Value" blank to read the (default) value. To delete a key:

Call RegistryDelete("HKEY_LOCAL_MACHINE\Software\My Key", "")

To delete a value:

Call RegistryDelete("HKEY_LOCAL_MACHINE\Software\My Key", "My Value")

To delete the (default) value in a key, we just set the value to nothing:

Call RegistryWrite("HKEY_LOCAL_MACHINE\Software\My Key", "", "", "")

You'll notice that, in the RegistryDelete subroutine, there's a RegWrite statement. This is necessary to ensure that the key or value that you're trying to delete actually exists. If you don't include this statement and try to delete a nonexistent key or value from the Registry, the Windows Script Host will give an error to the effect that "The system cannot find the file specified." (A helpful Microsoft error message, as always.) This way, the subroutine will create the key or value entry to be deleted if it doesn't already exist.

As part of a security/safety feature present in Windows XP (and Windows 2000), you won't be able to delete a key that contains subkeys (this is not true of Windows 9x/Me) using the RegistryDelete routine. See Section 3.3.5 in Chapter 3 for a workaround using Registry patch files.


See Chapter 3 for more information on Registry keys and values.

9.2.3. Manipulating Files from Scripts

One of the myths surrounding the Windows Script Host, and VBScript in particular, is that there's no provision for accessing the filesystem (copying, deleting, and writing to files). This assumption is based on the fact that VBScript, when used in web pages, is not permitted to access the filesystem for security reasons.

The following routines, all of which rely on the FileSystemObject object, should allow you to script most necessary file operations. The names I've chosen for these functions and subroutines are based on what they act upon and what they're used for; for example, the FolderCopy subroutine is used to copy a folder, and the FileCopy subroutine is used to copy a file.

The following two functions return properties of driveswhether a specific drive letter exists and how much free space a specified drive has, respectively:

Function DriveExists(DriveLetter)   Set FileObject = CreateObject("Scripting.FileSystemObject")   DriveExists = FileObject.DriveExists(DriveLetter) End Function    Function DriveFreeSpace(DriveLetter)   If Left(DriveLetter,1) <> ":" Then DriveLetter = DriveLetter & ":"   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set DriveHandle = _                  FileObject.GetDrive(FileObject.GetDriveName(DriveLetter))   DriveFreeSpace = DriveHandle.FreeSpace End Function

These next seven subroutines and functions are used to manipulate folders. The functions are used to retrieve information about a folder, and the subroutines are used to perform actions on a folder. The arguments should all be full folder names (e.g., "D:\Documents and Settings\All Users\Desktop"). Note that the FolderSize function returns the combined size of all the contents of a folder, including all subfolders, and may take a few seconds to return a result for large folders. You may want to use the FolderExists function before any others to prevent errors:

Sub FolderCopy(Source, Destination)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FileObject.CopyFolder Source, Destination End Sub Function FolderCreate(Foldername)   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set Result = FileObject.CreateFolder(FolderName)   If Result.Path = "" Then     FolderCreate = False   'failure   Else     FolderCreate = True    'success   End If End Function Sub FolderDelete(Foldername)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FileObject.DeleteFolder(Foldername) End Sub Function FolderExists(Foldername)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FolderExists = FileObject.FolderExists(Foldername) End Function Sub FolderMove(Source, Destination)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FileObject.MoveFolder Source, Destination End Sub Function FolderSize(Foldername)   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set FolderHandle = FileObject.GetFolder(Foldername)   FolderSize = FolderHandle.Size End Function   Function FolderParent(Foldername)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FolderParent = FileObject.GetParentFolderName(Foldername) End Function

These next seven subroutines and functions are used to manipulate files, and are similar to their folder counterparts listed above. And likewise, the functions are used to retrieve information about a file, and the subroutines are used to perform actions on a file. The arguments should all be fully qualified filenames (e.g., "c:\windows\notepad.exe"). You may want to use the FileExists function before any others to prevent errors:

Sub FileCopy(Source, Destination)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FileObject.CopyFile Source, Destination End Sub Function FileDate(Filename)   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set FileHandle = FileObject.GetFile(Filename)   GetFileDate = FileHandle.DateCreated End Function  Sub FileDelete(Filename)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FileObject.DeleteFile(Filename) End Sub Function FileExists(Filename)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FileExists = FileObject.FileExists(Filename) End Function Function FileExtension(Filename)   Set FileObject = CreateObject("Scripting.FileSystemObject")   GetFileExtension = FileObject.GetExtensionName(Filename) End Function Sub FileMove(Source, Destination)   Set FileObject = CreateObject("Scripting.FileSystemObject")   FileObject.MoveFile Source, Destination End Sub Function FileSize(Filename)   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set FileHandle = FileObject.GetFile(Filename)   FileSize = FileHandle.Size End Function

These next two functions can be used on either files or folders and allow you to retrieve and set file attributes (Archive, Read-Only, System, and Hidden, respectively).

File attributes are specified numerically: Read-Only = 1, Hidden = 2, System = 4, and Archive = 32. So, to set the Hidden and System attributes for a file, the Attrib parameter would be set to 6 (or 2+4). To read a file's attributes, the same constants are used, but only individually. For example, to see if a file had, say, the System attribute turned on, you would use this statement: If GetAttributes("c:\somefile.txt",4) = True Then Msgbox "This is a system File." :

Function GetAttributes(Filename, Attrib)   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set FileHandle = FileObject.GetFile(Filename)   If FileHandle.Attributes And Attrib Then     GetAttributes = True   Else     GetAttributes = False   End If End Function Sub SetAttributes(Filename, Attrib)   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set FileHandle = FileObject.GetFile(Filename)   FileHandle.Attributes = Attrib End Sub

The following four functions are used to obtain the locations of special Windows folders, or, in the case of GetTempFilename, to generate a new filename in the current user's Temp folder. (Rather than simply returning the location of the Temp folder, the GetTempFilename function returns the full path of a newly generated temporary filename. The corresponding file is guaranteed not to exist, so you can use it for the purposes of temporary storage without fear of conflicting with another open application.)

So, for example, to get the full path of the current user's Desktop folder, you would use GetSpecialFolder("Desktop"). The folders accessible with this function include AllUsersDesktop, AllUsersStartMenu, AllUsersPrograms, AllUsersStartup, Desktop, Favorites, Fonts, MyDocuments, NetHood, PrintHood, Programs, Recent, SendTo, StartMenu, Startup, and Templates. (See Section 9.4 later in this chapter for several examples using these functions.):

Function GetSpecialFolder(Foldername)   set WshShell = WScript.CreateObject("WScript.Shell")   GetSpecialFolder = WshShell.SpecialFolders(Foldername) End Function Function GetSystemFolder( )   Set FileObject = CreateObject("Scripting.FileSystemObject")   GetSystemFolder = FileObject.GetSpecialFolder(1) & "\" End Function Function GetTempFilename( )   Set FileObject = CreateObject("Scripting.FileSystemObject")   GetTempFile = FileObject.GetSpecialFolder(2) & "\" _                 & FileObject.GetTempName End Function Function GetWindowsFolder( )   Set FileObject = CreateObject("Scripting.FileSystemObject")   GetWindowsFolder = FileObject.GetSpecialFolder(0) & "\" End Function

While the previous functions and subroutines are used to manipulate files, the following two are used to manipulate the contents of files. The ReadFromFile function will transfer the contents of any file into a variable (naturally, this is most useful with plain-text files). Likewise, the WriteToFile subroutine will transfer the contents of a variable (called Text) into a file. If the file doesn't exist, it will be created; if the file already exists, the text will be appended to the end of the file:

Function ReadFromFile(Filename)   Const ForReading = 1, ForWriting = 2, ForAppending = 8   Set FileObject = CreateObject("Scripting.FileSystemObject")   Set FileHandle = FileObject.OpenTextFile(Filename, ForReading)   Buffer=""   Do Until FileHandle.AtEndOfStream     Buffer = Buffer & FileHandle.ReadLine & vbCrLf   Loop   FileHandle.Close   ReadFromFile = Buffer End Function Sub WriteToFile(Filename, Text)   Const ForReading = 1, ForWriting = 2, ForAppending = 8   Set FileObject = CreateObject("Scripting.FileSystemObject")   If FileObject.FileExists(Filename) Then     Set FileHandle = FileObject.OpenTextFile(Filename, _                                              ForAppending)     FileHandle.Write vbCrLf   Else     Set FileHandle = FileObject.CreateTextFile(Filename)   End If   FileHandle.Write Text   FileHandle.Close End Sub

The use of all of the "file operations" subroutines and functions listed earlier should be fairly self-explanatory, and they all work similarly. For example, the FolderExists function and the FileExists function are both nearly identical, except that FolderExists checks for the existence of a folder, while FileExists checks for the existence of a single file. See the Section 9.4.5 script at the end of this chapter for an example of these functions and subroutines in action.

9.2.4. Creating Windows Shortcuts and Internet Shortcuts in Scripts

Include the following subroutine in your script to allow easy creation of Internet Shortcuts (*.url ) and Windows Shortcuts (*.lnk):

Sub Shortcut(LinkFile, CommandLine)   Set WshShell = WScript.CreateObject("WScript.Shell")   If LCase(Right(LinkFile, 4)) <> ".lnk" And _           LCase(Right(LinkFile, 4)) <>".url" Then _          LinkFile = LinkFile & ".LNK"   Set ShortcutHandle = WshShell.CreateShortcut(LinkFile)   ShortcutHandle.TargetPath = CommandLine   ShortcutHandle.Save End Sub

To create a shortcut to a program or file, use the following statement:

Call Shortcut("C:\Documents and Settings\All Users\SendTo\Notepad.lnk", _               "Notepad.exe")

To create a shortcut to an Internet address:

Call Shortcut("D:\Prjects\Important\Annoyances.url", _               "http://www.annoyances.org/")

If the first parameter, LinkFile, ends in .lnk (case doesn't matter), the Shortcut subroutine will automatically create a standard Windows shortcut; if LinkFile ends in .url, however, an Internet Shortcut file will be created. Note the If...Then structure in the routine, which automatically adds the .lnk filename extension if no proper extension is found.

The LCase function, which transforms the contents of any variable to lowercase, is vital here, and completely compensates for .URL, .url, .Url, and any other case mismatch in the specified filename.


If you specify a nonexistent folder in the path for the new shortcut file, an "Unspecified Error" will occur. You may want to use the FolderExists function, detailed in the Section 9.2.3 topic earlier in this chapter, to supplement this routine and eliminate the possibility of this error.

9.2.5. Networking with Scripts

VBScript has a few limited networking functions built in that can be used for mapping network drives and connecting to network printers. For advanced network functionality (such as communication and network traffic monitoring), you'll have to look into a different scripting language. For more information on networking, see Chapter 7.

The following routines provide access to some of the more useful network-related functions in VBScript.

The following function checks a given drive letter to see if it has already been mapped. It returns true (-1) if the drive letter has been mapped, False (0) if it hasn't:

Function AlreadyMapped(DriveLetter)   Set WshShell = WScript.CreateObject("WScript.Shell")   Set WshNetwork = WScript.CreateObject("WScript.Network")   Set AllDrives = WshNetwork.EnumNetworkDrives( )   If Left(DriveLetter,1) <> ":" then DriveLetter = DriveLetter & ":"   ConnectedFlag = False   For i = 0 To AllDrives.Count - 1 Step 2     If AllDrives.Item(i) = UCase(DriveLetter) Then ConnectedFlag = True   Next   AlreadyMapped = ConnectedFlag End Function

This subroutine maps a drive letter to any valid remote path:

Sub MapNetDrive(DriveLetter, RemotePath)   Set WshShell = WScript.CreateObject("WScript.Shell")   Set WshNetwork = WScript.CreateObject("WScript.Network")   WShNetwork.MapNetworkDrive DriveLetter, RemotePath End Sub

This subroutine maps an unused printer port (e.g., LPT3) to any valid remote network printer:

Sub MapNetPrinter(Port, RemotePath)   Set WshShell = WScript.CreateObject("WScript.Shell")   Set WshNetwork = WScript.CreateObject("WScript.Network")   WshNetwork.AddPrinterConnection Port, RemotePath End Sub

This subroutine removes the mapping for a previously mapped drive letter:

Sub UnMapNetDrive(DriveLetter)   Set WshShell = WScript.CreateObject("WScript.Shell")   Set WshNetwork = WScript.CreateObject("WScript.Network")   WShNetwork.RemoveNetworkDrive DriveLetter End Sub

This subroutine removes the mapping for a previously mapped network printer:

Sub UnMapNetPrinter(Port)   Set WshShell = WScript.CreateObject("WScript.Shell")   Set WshNetwork = WScript.CreateObject("WScript.Network")   WshNetwork.RemovePrinterConnection Port End Sub

The following script serves as an example using these subroutines. It's used to map a network drive if it's not already mapped or to disconnect a currently mapped drive. The previous routines are required.

DriveLetter = "N:" RemotePath = "\\server\c" If AlreadyMapped(DriveLetter) then   Call UnMapNetDrive(DriveLetter)   Msgbox "Drive " & DriveLetter & " disconnected." Else   Call MapNetDrive(DriveLetter, RemotePath)   Msgbox "Drive " & DriveLetter & " connected." End if

This script requires no user interaction once it has been executed and displays only a single confirmation message when it's done. The first two lines contain the drive letter and network path to be mapped together. Then, the AlreadyMapped function is used to determine if the drive mapping already exists. The script then maps or disconnects the drive, depending on what's needed.

9.2.6. Manipulating Internet Explorer from Scripts

Because VBScript owes its existence, in part, to Internet Explorer (IE), it seems only fair that there would be some integration between WSH and IE. The key is the Internet Explorer object and the properties and methods associated with it.

Note that the code in this section is not presented as a subroutine, mostly because all of the subsequent statements that reference the IEObject object (such as IEObject.Document.Write) would fail if the initial Set statement were isolated in its own routine.

Begin with the following lines in your script, which start the Internet Explorer application, initialize an object to reference, and open a blank IE window:

Set IEObject = CreateObject("InternetExplorer.Application") If Err.number <> 0 Then   MsgBox "There was a problem starting Internet Explorer."   wScript.Quit End If IEObject.Left = 75 IEObject.Top = 75 IEObject.Width = 400 IEObject.Height = 300 IEObject.Menubar = 0 IEObject.Toolbar = 0 IEObject.Navigate "About:Blank" IEObject.Visible=1 Do while IEObject.Busy   Rem -- wait for window to open -- Loop

Note the error checking at the beginning, which quits if there's a problem loading Internet Explorer. The subsequent commands customize the window to our needs. The Left, Top, Width, and Height properties are all in pixels; for the MenuBar and Toolbar properties, 0 means hidden and 1 means visible. Lastly, the Navigate property specifies the URL to load; in this case, we specify About:Blank to show a blank page.

Once the IEObject.Visible=1 command is issued, the window appears, and the real fun begins. (Okay, maybe fun is too strong of a word.) The following lines send HTML code to the active IE window, and form a simple web page:

IEObject.Document.Write "<html>" IEObject.Document.Write "<h1>Hello World</h1>" IEObject.Document.Write "<p>" IEObject.Document.Write "<i>Aren't we sick of that phrase yet?</i>" IEObject.Document.Write "</html>"

This has nearly limitless possibilities, not the least of which is a more elegant way to display information than the MsgBox command, a much more sophisticated way of gathering information than the InputBox command (using fill-out forms), and a way to display an ongoing log of a script's activities without interrupting script flow. To clear the page at any time, simply issue another IEObject.Navigate "About:Blank" command.

Note that the IE window stays open after the script completes; use the IEObject.Quit command to close the window during script execution.

9.2.7. Using Command-Line Parameters in Scripts

A command-line parameter is a bit of text specified after the filename of a script when it is executed from a command prompt (see the following examples). The function used to convert a single command-line parameter into a variable is the following:

Function CommandLine(Number)   Set Arguments = WScript.Arguments   If Number <= Arguments.Count Then      CommandLine = Arguments(Number - 1)   Else     CommandLine = ""   End If End Function

For example, to display the second command-line parameter passed to a script, issue the following statement:

MsgBox CommandLine(2)

Although the command line may seem to be an antiquated concept, it's still very much a part of Windows. When you double-click on a .vbs file, for example, Windows actually executes the following command:

wscript.exe filename.vbs

where filename.vbs (the file that was double-clicked) is the command-line parameter for wscript.exe, telling it which script to run. Scripts also accept command-line parameters, which is accomplished like this:

wscript.exe filename.vbs param1 param2

The two additional parameters,[2] param1 and param2, are both passed to the script as command-line parameters, and can be retrieved during runtime by referencing CommandLine(1) and CommandLine(2), respectively.

[2] You can have as many or as few parameters as you like.

One of the most common uses of command-line parameters in scripts is to accept filenames, and there are two circumstances when this is most useful:

  • When you drag one or more items onto the script file icon. Note that this didn't work in earlier versions of Windows, as scripts were considered to be documents instead of programs.

  • When you place the script in your Send To folder; then, right-click one or more items in Explorer, select Send To, and then select the name of the script. You can also place the a shortcut to the script in your Send To folder, which eliminates the .vbs filename extension that would otherwise appear in the Send To menu.

In either case, the script is executed, and the names of the input file(s) are accessible as command-line parameters, one for each filename. The following script shows the names of all files and folders drag-dropped on the script icon:

Report = "" Set Arguments = WScript.Arguments For i = 1 to Arguments.Count   Report = Report + Arguments(i - 1) + vbCrLf Next Msgbox Report

The script starts off by clearing the Report variable, and then borrows some code from the CommandLine function listed earlier[3] to initialize the Arguments object and determine the number of dropped files. Next, a For...Next structure is used to run through the arguments, adding each one to the Report variable, followed by a linefeed (using vbCrLf, a handy built-in constant containing carriage-return and linefeed characters). Note that the Arguments array is zero-based (the first item is Arguments(0), the second is Arguments(1), and so on), so we need to include the (i - 1) part to compensate. Lastly, a Msgbox command is used to display the list of dropped files.

[3] It's actually possible to use the CommandLine function itself here instead, but doing so would make the script more cumbersome. And exactly who are you going to impress with a cumbersome script?

9.2.8. Managing Services with Scripts

Windows XP Services, such as the IIS web server service, the FTP daemon service, or the Remote Desktop service, can be managed with the Services window (services.msc). Rudimentary service control is also possible with WSH scripts. The following routine allows you to start and stop any service, or just see if a service is running:

Function Service(ServiceName, Action)   Const SERVICE_STOPPED = 1   Const SERVICE_RUNNING = 4   Set WshShell = WScript.CreateObject("WScript.Shell")   Set EnvObject = WshShell.Environment("PROCESS")   ComputerName = EnvObject("COMPUTERNAME")   Set ComputerObject = GetObject("WinNT://" & ComputerName & ",computer")   Set ServiceObject  = ComputerObject.GetObject("Service",ServiceName)   If Action = 1 and ServiceObject.Status = SERVICE_STOPPED Then     ServiceObject.Start   ElseIf Action = 2 and ServiceObject.Status = SERVICE_RUNNING Then     ServiceObject.Stop   End If   If ServiceObject.Status = SERVICE_RUNNING Then     Service = True   Else     Service = False   End If End Function

This general-purpose routine accepts two parameters: ServiceName and Action. ServiceName is a single word that represents the service you wish to start, stop, or query, and Action is just a number, representing what you want the routine to do. To find the service name for a given service, open the Services window (services.msc) and double-click the service in question. The service name is listed at the top of the General tab; for example, the service name for the IIS service is IISADMIN, the name for the FTP service is MSFTPSVC, and the name for the Remote Desktop (aka Terminal Services, discussed in Chapter 7) service is TermService.

So, to start the FTP service, you would type:

Result = Service("MSFTPSVC", 1)

or, to stop the service, you would type:

Result = Service("MSFTPSVC", 2)

Either way, the function returns true (-1) if your action resulted in the service being started, or False (0) if your action resulted in the service being stopped. To simply query the service, without starting or stopping it, specify any other number for Action, like this:

Result = Service("MSFTPSVC", 0)

Including this routine in your script allows you to start and stop a service with a single click (rather than having to wade through the Services window). Or, using these script routines in conjunction with Scheduled Tasks (explained later in "Automating Scripts with Scheduled Tasks"), for example, you could schedule your web server service to operate only during certain hours of the day.

9.2.9. Writing CGI Scripts for a Web Server

WSH scripts have the potential to produce simple, yet quite capable CGI (Common Gateway Interface) applications for use with web servers: programs that are run by web-server software to generate dynamic web content. For example, CGI programs can be used to process data entered in web-based fill-out forms or to read data from files and produce web content on the fly. Although a full discussion of web-server implementation and CGI programming is beyond the scope of this book, there are some extra steps and additional commands necessary to write CGI programs with WSH scripts.

The first step is to set up your web server software to execute WSH scripts. There is a variety of different web-server software packages (such as IIS, included with Windows XP, and Apache, freely available at http://www.apache.org), and naturally the configuration varies with each package. The following procedure shows how to set up IIS and configure it to execute WSH scripts as CGI programs.

  1. If IIS is not currently installed, go to Add or Remove Programs in Control Panel, and click Add/Remove Windows Components. Highlight Internet Information Services (IIS) from the list, and click Details. Place a checkmark next to Common Files, Internet Information Services Snap-In, World Wide Web Service, and any other components you want installed. Click OK and then click Next to complete the wizard.

  2. Start the IIS Snap-In (\Windows\system32\inetsrv\iis.msc), and then expand the branches to Internet Information Services\My Computer\Web Sites\Default Web Site. The files and folders that make up your web site are shown here (note that your setup may be different).

  3. Scripts to be executed cannot be placed in ordinary folders; otherwise, the web server will simply display their contents instead of running them. So, they must be placed in a virtual directory with executable permissions; if you've already set up such a folder, you can continue to the next step. Otherwise, go to Action Alias option is the folder name that appears in the URL when referencing the script from a browser (described subsequently), and the Directory option is the full path of the physical folder on your hard disk containing your script. Finally, when asked about Access Permissions, make sure to turn on the Execute option.

  4. Once you have a virtual directory configured, right-click the folder, click Properties, choose the Virtual Directory tab, and then click Configuration.

    For a CGI program to work, its output must be sent to the "console," a text-based display which works like the Command Prompt. For this reason, the CScript.exe script interpreter (engine), mentioned earlier in this chapter, must be used instead of the standard WScript.exe Windows-based interpreter.


  5. Click Add, and type the following:

    c:\windows\system32\cscript.exe "%s" "%s"

    in the Executable field (change the path to match your system, if necessary), and type .vbs in the Extension field (make sure to include the dot).

    Naturally, the filename extension will be different for JavaScript or Perl script files. Or, if you like, you can even make up a new filename extension for use with your VBScript CGI scripts (such as .vbsc or .vbcgi), as long as what you type doesn't conflict with another entry in the list.

  6. The All Verbs, Script engine, and Check that file exists options should all be selected. Click OK, and then OK again when you're done.

The next step is to write a CGI script and place it in your executable folder. CGI scripts can use any of the commands and routines discussed elsewhere in this chapter, except, of course, for those that create dialog windows, such as MsgBox and InputBox.

The key to a CGI script, though, is the WScript.Echo command, which is used to send your text output to the web server. Here's an example of a simple four-line script that generates a basic HTML-formatted[4] web page:

[4] A discussion of HTML (Hypertext Markup Language) is beyond the scope of this book, but there are many adequate HTML references on the web.

WScript.Echo "<html>" WScript.Echo "<body>" WScript.Echo "<h1>Here Comes the Metric System!</h1>" WScript.Echo "<body></html>"

To run the script, first save it in the executable folder you configured earlier. If the IISAdmin service is not currently running, start it now (via Services.msc). Then, open a web browser, and type this URL into the address bar:

http://localhost/foldername/script.vbs

where foldername is the Alias you chose for the executable folder, and script.vbs is the filename of the script. If all goes well, you should see our message, "Here Comes the Metric System!" right in the browser window. If it doesn't work, check the permissions of the script file and executable folder (right-click, select Properties, and choose the Security tab). See Chapter 8 for more information on user accounts, ownership, and file permissions.

Since we are talking about a web server, you can just as easily call the script from a remote computer, as long as you're connected to a network or to the Internet, and you know the IP address or URL of your machine (visit http://www.annoyances.org/ip to find out your computer's IP address). For example, if your IP address is 207.46.230.218, you'd simply type http://207.46.230.218/foldername/script.vbs.

Naturally, you'll probably want to generate dynamic (rather than static) content with your CGI script. Here's a script that displays the current date and time in the browser window:

WScript.Echo "<html><body>" WScript.Echo "Today's date is: " & Date WScript.Echo "and the current time is: " & Time WScript.Echo "<body></html>"

For those familiar with writing CGI programs, you may be confused by the handling of any HTTP headers you include in your WSH CGI scripts. Although the CGI specification requires that a CGI program produce its own HTTP headers (such as "Content-type: text/html"), IIS 5.x automatically generates the headers, based on the type of content it thinks you're sending (text/html for HTML or text/plain for plain text, for example). This not only means that any headers you include (with WScript.Echo) will simply appear as part of the generated page, but that there's no way to include your own headers.


If you need to obtain the value of a browser environment variable in your script, include this function:

Function Environment(EnviroName)   Set WshShell = Wscript.CreateObject("Wscript.Shell")   Set EnvHandle = WshShell.Environment("Process")   Environment = EnvHandle(EnviroName) End Function

For example, you can display the user's web browser version with this short script:

WScript.Echo "Your browser's signature is:" WScript.Echo Environment("HTTP_USER_AGENT")

Some other useful environment variables include QUERY_STRING (for retrieving form input or any text after a question mark in the URL) and HTTP_COOKIE (for reading HTTP cookies).

You can, of course, use other routines in your CGI scripts. For example, here's a script that displays the contents of a text file, using the ReadFromFile function (see Section 9.2.3 earlier in this chapter):

OrderNum = "234323" WScript.Echo "Here is your order (number " & OrderNum & "):" WScript.Echo "<p>" WScript.Echo "<img src="/books/1/439/1/html/2/"/pictures/smiley.jpg""><br>" WScript.Echo ReadFromFile("d:\data\orders\" & OrderNum & ".txt")

Note the use of Hypertext Markup Language (HTML) to include an image in the output. Although many HTML tags require quotation marks, adding a quotation mark in the middle of a line would cause WSH to confuse it with the beginning and trailing quotes. To tell VBScript to treat a quotation mark as a character to print, just put two of them together (as shown on the "smiley" line).



    Windows XP Annoyances For Geeks
    Fixing Windows XP Annoyances
    ISBN: 0596100531
    EAN: 2147483647
    Year: 2003
    Pages: 97
    Authors: David A. Karp

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net