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.
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 otepad.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.
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_MACHINESoftwareMy Key", "", "", "")
To assign data to a Registry value:
Call RegistryWrite("HKEY_LOCAL_MACHINESoftwareMy 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_MACHINESoftwareMy Key", "My Value
")
Leave "My
Value
" blank to read the (default
) value. To delete a key:
Call RegistryDelete("HKEY_LOCAL_MACHINESoftwareMy Key", "")
To delete a value:
Call RegistryDelete("HKEY_LOCAL_MACHINESoftwareMy Key", "My Value
")
To delete the (default
) value
in a key, we just set the value to nothing:
Call RegistryWrite("HKEY_LOCAL_MACHINESoftwareMy 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.
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 drives—whether 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 SettingsAll
UsersDesktop"). 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
otepad.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.
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 SettingsAll UsersSendToNotepad.lnk", _ "Notepad.exe")
To create a shortcut to an Internet address:
Call Shortcut("D:PrjectsImportantAnnoyances.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.
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 = "\serverc" 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.
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.
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.
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.
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.
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.
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.
Start the IIS Snap-In (Windowssystem32inetsrviis.msc), and
then expand the branches to Internet
Information ServicesMy ComputerWeb SitesDefault Web
Site
. The files and folders that make up your web site
are shown here (note that your setup may be different).
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 → New → Virtual Directory, and follow the prompts. The 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.
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.
Click Add, and type the following:
c:windowssystem32cscript.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.
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:
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=""/pictures/smiley.jpg""><br>" WScript.Echo ReadFromFile("d:dataorders" & 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).
[2] You can have as many or as few parameters as you like.
[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?
[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.
3.145.98.239