VBScript and the WSH

In this chapter, you will learn about the objects, properties, and methods provided by the WSH. Later, you will learn how to use these objects to access and manipulate a host of Windows resources. This chapter will also demonstrate how to create scripts that can receive and process arguments passed at run time. Finally, you'll learn how to create a new kind of script file using XML (Extensive Markup Language) that will allow you to combine two or more separate scripts, written in different scripting languages, together into one new Windows Script File.

The WSH Object Model

At the heart of the WSH is its core object model. The objects that make up this model provide direct access to the Windows resources that they represent. In total, the WSH core object model is made up of 14 objects. These objects and their relationship to one another are depicted in Figure 9.1.

click to expand
Figure 9.1: The WSH core object model is made up of 14 individual objects

The WScript object resides at the top or root of the object model. The WScript object is implicitly instantiated by the WSH at the start of script execution, meaning that scripts can automatically access any of its properties or methods. All of the other objects in the WSH core object model must first be instantiated in order to use their properties and methods.

Public Objects

The WScript object is automatically exposed at the start of script execution. The WScript object is also referred to as a public object. The WSH core object model has three other public objects, which are the WshController, WshShell, and WshNetwork objects. In order to instantiate any of these three objects, you must use the WScript object's CreateObject() method. The remaining WSH core objects are instantiated by using one of the properties or methods of these four public objects.

  Note

The WScript object's CreateObject() method provides the means of instantiating other objects in the WSH core object model.

Table 9.1 provides a list of the other 10 objects that make up the WSH core object model and a list of object properties or methods that are required to instantiate them.

Table 9.1: Working with Lower-Level WSH Objects

Object

Method of Instantiation

WshArguments

WScript.Arguments

WshNamed

WScript.Arguments.Named

WshUnnamed

WScript.Arguments.Unnamed

WshRemote

WshController.CreateScript()

WshRemoteError

WshRemote.Error

WshShortcut

WshShell.CreateShortcut()

WshUrlShortcut

WshShell.CreateShortcut()

WshEnvironment

WshShell.Environment

WshSpecialFolders

WshShell.SpecialFolders

WshScriptExec

WshShell.Exec()

WSH Object Properties and Methods

Each object in the WSH core object model has its own unique set of properties and methods. Table 9.2 provides a brief description of the WSH core objects. In addition, it provides a list of properties and methods associated with each object.

Table 9.2: WSH Core Objects

Object

Description

WScript

This is the WSH root object. It provides access to a number of useful properties and methods. It also provides access to the rest of the objects in the WSH core object model.

Properties: Arguments, FullName, Interactive, Name, Path, ScriptFullName, ScriptName, StdErr, StdIn, StdOut, and Version

Methods: ConnectObject(), CreateObject(), DisconnectObject(), Echo(), GetObject(), Quit(), and Sleep()

WshArguments

This object allows you to access command-line arguments passed to the script at execution time.

Properties: Count, Item, and Length; Named and Unnamed

Methods: Count() and ShowUsage()

WshNamed

This object provides access to a set of named command-line arguments.

Properties: Item and Length

Methods: Count() and Exists()

WshUnnamed

This object provides access to a set of unnamed command-line arguments.

Properties: Item and Length

Methods: Count()

WshController

This object provides the ability to create a remote script process.

Properties: This object does not support any properties.

Methods: CreateScript

WshRemote

This object provides the ability to administrate remote computer systems using scripts over a network.

Properties: Status and Error

Methods: Execute() and Terminate()

WshRemoteError

This object provides access to information on errors produced by remote scripts.

Properties: Description, Line, Character, SourceText, Source, and Number

Methods: This object does not support any methods.

WshNetwork

This object provides access to a number of different network resources such as network printers and drives.

Properties: ComputerName, UserDomain, and UserName

Methods: AddWindowsPrinterConnection(), AddPrinterConnection(), EnumNetworkDrives(), EnumPrinterConnection(), MapNetworkDrive(), RemoveNetworkDrive(), RemovePrinterConnection(), and SetDefaultPrinter()

WshShell

This object provides access to the Windows registry, event log, environmental variables, shortcuts, and applications.

Properties: CurrentDirectory, Environment, and SpecialFolders

Methods: AppActivate(), CreateShortcut(), ExpandEnvironmentStrings(), LogEvent(), Popup(), RegDelete(), RegRead(), RegWrite(), Run(), SendKeys(), and Exec()

WshShortcut

This object provides scripts with methods and properties for creating and manipulating Windows shortcuts.

Properties: Arguments, Description, FullName, Hotkey, IconLocation, TargetPath, WindowStyle, and WorkingDirectory

Method: Save()

WshUrlShortcut

This object provides scripts with methods and properties for creating and manipulating URL shortcuts.

Properties: FullName and TargetPath

Methods: Save()

WshEnvironment

This object provides access to Windows environmental variables.

Properties: Item and Length

Methods: Remove() and Count()

WshSpecialFolders

This object provides access to special Windows folders that allow scripts to configure the Start menu, desktop, Quick Launch toolbar, and other special Windows folders.

Properties: Item

Methods: Count()

WshScriptExec

This object provides access to error information from scripts run using the Exec method.

Properties: Status, StdOut, StdIn, and StdErr

Methods: Terminate()

There are too many WSH objects to cover them all in a single chapter. Therefore, this chapter will be limited to providing you with a WSH object reference, while offering a few examples of how to work with some of the WSH objects. The remaining chapters of this book will give you the opportunity to work with many of the properties and methods belonging to the objects shown in Table 9.2.

Core Object Properties

Object properties store information about the resources that they represent. By referencing object properties, VBScript can collect information about the environment in which they execute. Further, by modifying object properties, VBScripts can make direct changes to this environment and the Windows resources that reside within it.

The WSH core objects provide access to dozens of different properties. Table 9.3 lists each of these properties.

Table 9.3: WSH Object Properties

Property

Description

Arguments

Sets a pointer reference to the WshArguments collection

AtEndOfLine

Returns either True or False depending on whether the end-of-line maker has been reached in the stream

AtEndOfStream

Returns either True or False depending on whether the end of the input stream has been reached

Character

Identifies the specific character in a line of code where an error occurs

Column

Returns the current column position in the input stream

ComputerName

Retrieves a computer's name

CurrentDirectory

Sets or retrieves a script's current working directory

Description

Retrieves the description for a specified shortcut

Environment

Sets a pointer reference to the WshEnvironment

Error

Provides the ability to expose a WshRemoteError object

ExitCode

Returns the exit code from a script started using Exec()

FullName

Retrieves a shortcut or executable program's path

HotKey

Retrieves the hotkey associated with the specified shortcut

IconLocation

Retrieves an icon's location

Interactive

Provides the ability to programmatically set script mode

Item

Retrieves the specified item from a collection or provides access to items stored in the WshNamed object

Length

Retrieves a count of enumerated items

Line

Returns the line number for the current line in the input stream or identifies the line number within a script where an error occurred

Name

Returns a string representing the name of the WScript object

Number

Provides access to an error number

Path

Returns the location of the folder where the CScript or WScript execution hosts reside

ProcessID

Retrieves the PID (process ID) for a process started using the WshScriptExec object

ScriptFullName

Returns an executing script's path

ScriptName

Returns the name of the executing script

Source

Retrieves the identity of the object that caused a script error

SourceText

Retrieves the source code that created the error

SpecialFolders

Provides access to the Windows Start menu and desktop folders

Status

Provides status information about a remotely executing script or a script started with Exec()

StdErr

Enables a script to write to the error output stream or provides access to read-only error output from an Exec object

StdIn

Enables read access to the input stream or provides access to the write-only input scream for the Exec object

StdOut

Enables write access to the output stream or provides access to the write-only output stream of the Exec object

TargetPath

Retrieves a shortcut's path to its associated object

UserDomain

Retrieves the domain name

UserName

Retrieves the currently logged on user's name

Version

Retrieves the WSH version number

WindowStyle

Retrieves a shortcut's window style

WorkingDirectory

Returns the working directory associated with the specified shortcut

  Note

In some cases, the same property may be shared by more than one object. Use Table 9.2 to determine which properties are associated with which objects.

Using WSH Object Properties

As an example of how to work with WSH object properties, review the following VBScript. In this script, the properties belonging to the WshNetwork object are referenced in order to collect network information.

'*************************************************************************
'Script Name: Script 9.1.vbs
'Author: Jerry Ford
'Created: 02/12/03
'Description: This script demonstrates how to use properties belonging to
'the WshNetwork object in order to obtain network information
'*************************************************************************
'Initialization Section

Option Explicit

Dim WshNtwk, strDisplayText

'Instantiate the WshNetwork object
Set WshNtwk = WScript.CreateObject("WScript.Network")


'Main Processing Section

'Call the procedure that collects and displays network information
DisplayNetInfo()

'Terminate script execution
WScript.Quit()


'Procedure Section

'This subroutine Display network information
Sub DisplayNetInfo()

 strDisplayText = "This computer is " & WshNtwk.ComputerName & ". " & _
 "It is connected to the following domain:" & vbCrLf & vbCrLf & _
 WshNtwk.UserDomain & vbCrLf & vbCrLf & vbCrLf

 MsgBox strDisplayText, , "Network Information"

End Sub

This script begins by defining two variables, WshNtwk and strDisplayText. WshNtwk is then used to instantiate the WshNetwork object, as shown below.

Dim WshNtwk, strDisplayText
Set WshNtwk = WScript.CreateObject("WScript.Network")

As you can see, both the Set statement and the WScript object's Create-Object() method are required to set up an instance of the WshNetwork object. Once instantiated, you can reference any of the object's properties and methods. Next, the script executes a procedure called DisplayNetInfo(). This subroutine contains two statements. The first statement creates a display string using the strDisplayText variable and the following WshNetwork properties:

  • ComputerName. Retrieves the network name assigned to the computer where the script executes
  • UserDomain. Retrieves the domain name of the Windows domain to which the computer belongs, or if the computer is a member of a workgroup-based network, retrieves the name of the workgroup to which the computer has been assigned

The second statement in the DisplayNetInfo() subroutine displays the display string as demonstrated in Figure 9.2. Finally, control returns to the Main Processing Section, where the WScript object's Quit() method is used to terminate the script's execution.

click to expand
Figure 9.2: Displaying network information collected from properties belonging to the WshNetwork object

Core Object Methods

WSH object methods provide the ability to interact with and manipulate the resources that they represent. These resources include desktop shortcuts, the Windows file systems, printers, and the Windows registry. Table 9.4 provides a list of WSH core object methods.

Table 9.4: WSH Object Methods

Method

Description

AddPrinterConnection()

Creates printer mappings

AddWindowsPrinterConnection()

Creates a new printer connection

AppActivate()

Activates the targeted application Window

Close()

Terminates or ends an open data stream

ConnectObject()

Establishes a connection to an object

Count

Retrieves the number of switches found in the WshNamed and WshUnnamed objects

CreateObject()

Creates a new instance of an object

CreateScript()

Instantiates a WshRemote object representing a script that is running remotely

CreateShortcut()

Creates a Windows shortcut

DisconnectObject()

Terminates a connection with an object

Echo()

Displays a text message

EnumNetworkDrives()

Enables access to network drives

EnumPrinterConnections()

Enables access to network printers

Exec()

Executes an application in a child command shell and provides access to the environment variables

Execute()

Initiates the execution of a remote script object

Exists()

Determines a specified key exists within the WshNamed object

ExpandEnvironmentStrings()

Retrieves a string representing the contents of the Process environmental variable

GetObject()

Retrieves an Automation object

GetResource()

Retrieves a resource's value as specified by the tag

LogEvent()

Writes a message in the Windows event log

MapNetworkDrive()

Creates a network drive mapping

Popup()

Displays a text message in a pop-up dialog box

Quit()

Terminates or ends a script

Read()

Retrieves a string of characters from the input stream

ReadAll()

Retrieves the s string that is made up of the characters in the input stream

ReadLine()

Retrieves a string containing an entire line of data from the input stream

RegDelete()

Deletes a registry key or value

RegRead()

Retrieves a registry key or value

RegWrite()

Creates a registry key or value

Remove()

Deletes the specified environmental variable

RemoveNetworkDrive()

Deletes the connection to the specified network drive

RemovePrinterConnection()

Deletes the connection to the specified network printer

Run()

Starts a new process

Save()

Saves a shortcut

SendKeys()

Emulates keystrokes and sends typed data to a specified Window

SetDefaultPrinter()

Establishes a default Windows printer

ShowUsage()

Retrieves information regarding the way that a script is supposed to be executed

Skip()

Skips x number of characters when reading from the input stream

SkipLine()

Skips an entire line when reading from the input stream

Sleep()

Pauses script execution for x number of seconds

Terminate()

Stops a process started by Exec()

Write()

Places a string in the output stream

WriteBlankLines()

Places a blank in the output stream

WriteLine()

Places a string in the output stream

Using WSH Object Methods

As an example of how to work with WSH object methods, examine the following VBScript. In this VBScript, methods belonging to the WshShell object are used to set up a mapped drive connection to a network folder.

'*************************************************************************
'Script Name: Script 9.2.vbs
'Author: Jerry Ford
'Created: 02/12/03
'Description: This script demonstrates how to use methods belonging to
'the WshNetwork object in order to map a network drive
'*************************************************************************


'Initialization Section

Option Explicit

Dim WshNtwk, strDriveLetter, strDrivePath

strDriveLetter = "z:"
strDrivePath = "\FamilyPCD"

'Instantiate the WshNetwork object
Set WshNtwk = WScript.CreateObject("WScript.Network")


'Main Processing Section

'Call the procedure that maps network drives
MapDrive strDriveLetter, strDrivePath

'Terminate script execution
WScript.Quit()


'Procedure Section
'This subroutine creates a network drive mapping

Sub MapDrive(strLetter, strPath)

 'Create a mapping to the specified network drive
 WshNtwk.MapNetworkDrive strLetter, strPath

End Sub

The script's Initialization Section contains statements that perform the following tasks:

  • Define variables to represent the WshNetwork object, a drive letter, and the address of a network folder
  • Assign a drive letter and the address of the network folder
  • Instantiate the WshNetwork object

Next, the Main Processing Section executes the MapDrive() procedure, passing the drive letter and the address of the network folder, as shown below.

MapDrive strDriveLetter, strDrivePath

The MapDrive() subroutine receives the arguments passed to it and assigns them to two new variables. It then uses the WshNetwork object's MapNetwork-Drive() method to establish the drive mapping. Finally, control returns to the Main Processing Section, where the WScript object's Quit() method is used to terminate the script's execution. Figure 9.3 shows how the mapped network drive appears in the My Computer dialog box.

click to expand
Figure 9.3: Mapping a network drive using the WshNetwork object's MapNetworkDrive() method


Passing Arguments to Scripts

In all the scripts that you have seen thus far, data has been either hard coded into the scripts as constants, variables, and arrays or collected interactively from the user via pop-up dialog boxes. Scripts also frequently receive data to process by having that data passed to them as arguments at run time. For example, you might set up one script to call another script and use the output produced by the first script as input for the second script.

Alternatively, you might pass arguments to a script from the Windows command prompt. For example, the following command would execute a script name TestScript.vbs and pass it three arguments:

WScript TestScript.vbs log txt doc

What happens next depends on the script. For example, a script receiving log, txt, and doc as input might use these arguments to build a list of files that should be processed in some manner.

  Note

You can also pass arguments to scripts that include a blank space, but to do so, you must enclose the argument inside a pair of matching quotation marks, as demonstrated below.

 CScript TestScript.vbs reports, "log files", documents

Scripts have to be designed to process any argument input that may be passed to them. This can be accomplished using the properties belonging to the WshArguments object, as demonstrated in the following example.

'*************************************************************************
'Script Name: Script 9.3.vbs
'Author: Jerry Ford
'Created: 02/12/03
'Description: This script demonstrates how to process arguments passed to
'a VBScript
'*************************************************************************

'Initialization Section

Option Explicit

Dim WshArgs
Set WshArgs = WScript.Arguments


'Main Processing Section

If WshArgs.Count < 1 Then
 MsgBox "Error: No arguments were passed to this script."
 WScript.Quit()
Else
 ProcessArguments()
End If
WScript.Quit()


'Procedure Section

Sub ProcessArguments()

 Dim i, strDisplayString

 strDisplayString = "Total number of arguments passed to this " & _
 script: " & vbTab & WshArgs.Count & vbCrLf & vbCrLf

 For i = 0 to (WshArgs.Count - 1)
 strDisplayString = strDisplayString & WshArgs.Item(i) & vbCrLf
 Next

 MsgBox strDisplayString

End Sub

The first thing that this VBScript does is to define a variable and use it to instantiate an instance of the WshArguments object, as shown below.

Dim WshArgs
Set WshArgs = WScript.Arguments

In the script's Main Processing Section, the script then uses the WshArguments object's Count property to ensure that at least one argument was passed to the script, in which case the ProcessArguments() function is called. Otherwise an error message is displayed and the WScript object's Quit() method is executed, terminating the script's execution.

The ProcessArguments() function starts by adding a heading to a display string, as shown below.

strDisplayString = "Total number of arguments passed to this script: " & _
 vbTab & WshArgs.Count & vbCrLf & vbCrLf

Next it uses a For…Next loop to iterate through the list of arguments passed to the script. The WshArguments object stores arguments in an indexed list beginning at zero. The loop begins at zero and spins until WshArgs.Count – 1 (for example, if five arguments are passed, the index will begin at position 0 and end at position 4). The contents of the display string are modified upon each iteration of the loop by adding the value of each argument to the string based on its index number as specified by the variable i (for example, WshArgs.Item(i)).

Figure 9.4 demonstrates the output produced by this script if it is passed an argument list of SalesReport.doc, MarketReport.doc, Forecast.xls, MonthlyStats.xls, and LogReports.log.

click to expand
Figure 9.4: Processing arguments passed to a VBScript at run time


Using XML to Create Windows Script Files

The WSH provides programmers with a robust scripting environment that includes access to a common set of objects. These objects provide access to the Windows resources that they represent by means of the properties and methods. One of the strengths of the WSH is that it provides this same level of access regardless of the scripting language being used by the programmer.

Microsoft ships the WSH with VBScript and JScript, but third-party WSH-compatible scripting languages have been made available that include Perl, Python, and Rexx. The WSH does not stop there. In addition to allowing you to use the scripting language of your choice, it provides you with the ability to combine two or more scripts, including scripts written using different languages, into a single script known as a Windows Script File. Windows Script Files are plain text files that are saved with an .wsf file extension.

The WSH uses a subset of XML to create Windows Script Files. XML is a markup language that is syntactically similar to HTML. XML tags are used in Windows Script Files to identify or mark the components that make up the file. For example, every script contained in a Windows Script File is enclosed within a pair of tags. The WSH currently provides support for version XML 1.0.

XML is a case-sensitive markup language. It has a strict set of rules that must be followed when formatting tags. Unlike the HTML markup languages, you cannot get away with excluding required closing tags. The remainder of this chapter is dedicated to demonstrating a number of commonly used XML tags, as outlined in Table 9.5.

Table 9.5: XML Tags Commonly Used in Windows Script Files

Tag

Description

This tag specifies the Windows Script File's XML level.

This tag is used to enable or disable error handling and debugging for a specified job.

This tag provides the ability to embed comments within Windows Script Files.

This tag identifies the beginning and ending of a script within a Windows Script File.

This tag identifies the beginning and ending of a job inside a Windows Script File.

This tag allows multiple jobs to be defined within a single Windows Script File.

This tag defines static data (constants) that can be referenced by a script within a Windows Script File.

  Tip

XML version 1.0 allows the use of both uppercase and lowercase spelling in tags. However, the use of uppercase spelling is generally considered to be bad form. You should, therefore, use all lowercase spelling. This will also save you a lot of recoding work in the event that a future release of XML incorporates an all-lowercase requirement.

The Tag

The tag is an optional tag that specifies the XML version that a Windows Script File requires in order to execute. If used, the tag must be the first statement in the Windows Script File. Its syntax is shown below.

X.X" standalone="dtdflag" ?>

version specifies the required XML version. As of the writing of this book, the current version of XML is version 1.0. standalone specifies a Boolean value indicating whether or not the script includes a reference to an external DTD (Document Type Definition). The DTD is currently an unsupported WSH feature. However, if you wish, you may include it. If you choose to do so, then you must specify its value as Yes. The tag does not have a closing tag.

The purpose of the tag is to allow the programmer to enforce a stricter interpretation of XML statements within Windows Script Files. For example, this tag strictly enforces case sensitivity. In addition, it requires all attribute values to be enclosed within single or double quotes.

The following example demonstrates the use of the tag within a Windows Script File.



 

The Tag

The tag is an optional tag that allows you to enable or disable error reporting and debugging. The tag does not have a closing tag. Its syntax is shown below.

errorflag" debug="debugflag" ?>

errorflag is a Boolean value. When set equal to True, error reporting is enabled. If omitted, Windows Script Files automatically disable error reporting. debugflag is also a Boolean value that controls whether or not the occurrence of an error will start the Windows Script Debugger.

  Note

The Microsoft Windows Script Debugger is a utility provided by Microsoft that helps programmers in debugging script errors. Visit http://msdn.microsoft.com/scripting to learn more about this utility.

The following example demonstrates how to enable both error reporting and script debugging within a Windows Script File.


 
 

The and < comment> Tags

The and tags provide the ability to place comments within Windows Script Files. The and tags can also be used to spread comments out over multiple lines. The syntax for the and tags is shown below.

 comment text 

The following example demonstrates the use of the and tags.


 Place your comment here
 

The tags are used to identify the beginning and the ending of individual scripts within a Windows Script File. Their syntax is shown below.


 

language is used to specify the scripting language used to develop the script. src is optional and can be used to specify the location of an external script.

The following example demonstrates the use of the tags to embed a VBScript inside a Windows Script File.


 

 

The next example demonstrates how to set up a reference to an external VBScript that is located in the same folder as the Windows Script File.


 

 


As you can see, this job executes three scripts, two written in VBScript and one written using JScript. The second VBScript defined within the job represents an external script.

The and < package> Tags

In order to place more than one job within a Windows Script File, you must first specify and tags and then embed the jobs within these tags. The syntax for the and tags is shown below.



 . . .

The following example demonstrates how to use the and tags to add three jobs to a Windows Script File.




 
 
 

 

 
 

 
 
 


The first job is named Job_A. It contains a single VBScript. The second and third jobs are named Job_B and Job_C, respectively.

The and < resource> Tags

The XML and tags allow you to define constants that can be accessed by any scripts defined within the same job in a Windows Script File. Using these tags, you can define one or more constants that individual scripts within the Windows Script Files may need to use. This saves you the trouble of having to redefine constants over and over again for every script in the Windows Script File. This also helps to make your scripts easier to support. It allows you to store and manage constants by limiting the number of locations where constants are defined (for example, once per job).

When specified, the and tags must be placed within the and tags. The syntax for these tags is shown below.


resourceid">
 . . .

id is used to specify the name of a constant. The value assigned to the constant is specified by typing it between the opening and closing tags, as shown in the following example.




 Windows Script File Demo
 


In this example, the value of the constant cTitleBarMsg is displayed by a MsgBox() function using the WSH getResource() method. This built-in WSH method is designed to retrieve the value of constants defined within and tags.


Running Your Windows Script Files

You can run any Windows Script File by double-clicking on its icon. If the Windows Script File contains one job, that job and all the scripts that it is made of will execute. However, if the Windows Script File consists of more than one job, the first job that is defined will execute. In order to run other jobs that reside within the Windows Script File, you must execute the Windows Script File from the Windows command prompt and tell it which job you wish to execute by specifying the job's ID.

For example, the following statement could be used to run the first job defined in a Windows Script File called SampleScript.wsh using the WScript execution host.


WScript SampleScript.wsf

Since the first job defined in the script is to be executed, there is no need to specify its assigned job ID. If the Windows Script File contained a second job that was assigned a job ID of Job_B, then you could run it using the following command:


WScript SampleScript.wsf //job:Job_B


Summary

In this chapter, you learned about the objects that comprise the WSH object model. In addition, you were presented with a complete listing of the properties and methods associated with these objects and examples that demonstrated how to incorporate the use of WSH objects into your VBScripts. You also learned how to create and execute scripts that can accept and process arguments passed at run time. Finally, you learned how to develop Windows Script Files using XML. This included a review of commonly used XML tags.


Part II Professional Project 1 Desktop Administration Using VBScript and the WSH

Part I - Introducing Microsoft VBScriptBasics

Part II - Professional Project 1 Desktop Administration Using VBScript and the WSH

Part III - Professional Project 2 Analyzing Application Logs

Part IV - Professional Project 3 Creating a Centralized Report Management Station

Part V - Professional Project 4 Reporting Application Summary Data via the Web

Part VI - Introducing Microsoft VBScriptBasics



Microsoft VBScript Professional Projects
Microsoft VBScript Professional Projects
ISBN: 1592000568
EAN: 2147483647
Year: 2005
Pages: 366

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