Visual Basic Scripting

Basic Techniques


Control how script is run

Visual Basic scripts can be executed 'Windows style' or from a command prompt. This depends on which interpreter executes the script. Wscript.exe does it Windows style (e.g. with message boxes and other GUI stuff) and is the default : Wscript will execute the script when you double click it. Sometimes it's more convenient to run a script from a command line, e.g. when a script needs command line arguments or uses stdin and stdout (standaard input and output), or when running scripts from a batch file. In that case, you will want Cscript.exe to execute your script.

To control how the script is executed, you can use something like the following piece of code :



	If Ucase(Right((wscript.FullName),11)) <> "CSCRIPT.EXE" Then
		
		' if not using cscript, show error msg
		CRLF = chr(13)&chr(10)
		wscript.echo (	"Engine =  " & 	Right((wscript.FullName),11) & CRLF & CRLF &_
				wscript.ScriptName & " must be executed with cscript" & CRLF & _
				" eg. c:\cscript " & wscript.ScriptName & "  [arguments] " )


	Else 
		'execute script by calling subroutine main
		main
	
	End If
	wscript.quit

	'-----------------------------------------------------------------------------------------------

	'main script here
	Private Sub Main
		Wscript.echo "OK"
	End Sub


	

Force script to run with cscript

Taking this one step further, in stead of giving an error message and quit, the script could be forced to run with cscript, even if the user (explicitly or not) called wscript. To accomplisch this, the script will first check whether or not cscript is used, and if not, it will open a shell and run itself with cscript. That would look something like this :



	If Ucase(Right((wscript.FullName),11)) = "CSCRIPT.EXE" Then
		
		main
		
	Else 
		'run this script, using cscript

		set oShell = createObject ("Wscript.Shell")
		CommandLine = "cscript " & wscript.ScriptFullName
		oShell.Run CommandLine		
	End If
	wscript.quit

	'-----------------------------------------------------------------------------------------------

	'main script here
	Private Sub Main
		wscript.echo wscript.FullName & " -- OK"
		Wscript.Sleep 10000
	End Sub


	

note the 'Wscript.Sleep 10000' statement. This pauses the script for 10 seconds (10000 millisec) so you can actually see the output :-)

Some interesting Script properties

In the previous script, we needed to get properties of the script itself, such as its name, the interpreter that runs it, etc. Here's a number of interesting script properties - wrapped in a script so that you can see them in action :

	
	TAB = chr(9)
	CRLF = chr(13) & chr(10)

	wscript.echo "wscript.Name :" 		& TAB & 	wscript.Name
	wscript.echo "wscript.ScriptName :" 	& TAB & 	wscript.ScriptName
	wscript.echo "wscript.ScriptFullName :" & TAB & 	wscript.ScriptFullName



	wscript.echo	"Engine - from Fullname :"	& TAB & 	Right((wscript.FullName),11) 		& CRLF & _
 			"or in short :" 		& TAB & 	Left(Right((wscript.FullName),11),7)


	wscript.echo 	"the script's directory :" & TAB & _
		Left(Wscript.ScriptFullName, (Len(Wscript.ScriptFullName) - Len(Wscript.ScriptName)-1))


'__________________________________
	'for command line execution : allow user to read output
	wscript.Sleep 10000


	

handle script Arguments

If a script requires arguments, but none are provided, it will return an error and quit. Therefore, you need to check for arguments first, by counting them, like If WScript.Arguments.Count > 0 Then ..., or If WScript.Arguments.Count = 2 Then ....

If the .Count is OK, you can use the values. The simpliest way to get the values in to your script is like this :

		If lcase(WScript.Arguments.Item(0)) = "default" Then

		(...)

		theVariable = lcase(WScript.Arguments.Item(5)

		(...)
	

This clearly assumes that the arguments are given in a certain order, else you won't know which argument is 'item 5'. That's OK for simple scripts / commands with a limited number of arguments, or where the order is relevant. Compare with the 'copy' command :
copy source destination

For more elaborate scripts with lots of arguments, and where not all arguments are required, you could use a function that checks all parameters, and saves the value of each in the appropriate variable that you can then use in the rest of the script. This allows you to create scripts that take parameters like so :
doSomething.vbs -s source -d destination -m 666 -v .
You can collect these into your script and use the given values somewhat like this :

	
	'ArgHandler

	set Args = wscript.arguments

	For i = 0 to (Args.count -1)

		select case Args.item(i)

			case "-v": boolVerbose = True
			case "-s": strSourcePath = Args.item (i + 1)
			case "-d": strDestinationPath = Args.item (i + 1)
			case "-m": intModus = Cint(Args.item (i + 1))

		end select
	Next

	'show / use input :

		wscript.echo "the input was :" & chr(10)

		wscript.echo "v: " & boolVerbose
		wscript.echo "s: " & strSourcePath
		wscript.echo "d: " & strDestinationPath
		wscript.echo "m: " & intModus

		wscript.echo chr(10)

	

prompt for input

The obvious way to prompt for input in a script is to use an InputBox :
theValue = InputBox ("give a value : ", Wscript.ScriptName, "yes").
We can use this to prompt the user for input in case a required value is missing form the arguments list :


		If WScript.Arguments.Count < 4 Then

			'argument #5 is missing, ask for it :

			theValue5 = InputBox ("where do you want to go today ?", Wscript.ScriptName)
		Else
		
			theValue5 = WScript.Arguments.Item(5)
		End If
		


	

InputBox produces a GUI dialogue box - even when the script is running with cscript. To remain in text mode when prompting for input, vbs provides access to StdIn and StdOut (standard In/Output : keyboard and text on screen - or redirected with     <  ). This can be used like this :


	Set ConsoleInput = WScript.StdIn
	Set ConsoleOutput = WScript.StdOut

	ConsoleOutput.WriteLine "enter path to destination file : "		'or use wscript.echo
	theInput = ConsoleInput.ReadLine


	'can be put in a loop with 
	'	Do While Not ConsoleInput.AtEndOfStream
	'
	'to handle input that consists of multiple lines, eg. when reading redirected or piped input

	'show that input is saved in variable :
	wscript.echo "you have entered : " & theInput

	

To combine this with the Argument Handler routine, you wouldn't check the argument itself, but the variable that is supposed to get its value :


	'initialise : make sure you start with an empty var
	strSourcePath = ""
	
	set Args = wscript.arguments
	For i = 0 to (Args.count -1)
		select case Args.item(i)

			case "-s": strSourcePath = Args.item (i + 1)

		end select
	Next


	'if the variable is still empty, the -s argument was not given, 
	' so promt for input, and don't give up till you get it
	
	If strSourcePath = "" Then
		wscript.echo "the source path is required. Please enter the source path : "
		
		Set cin = WScript.StdIn
		
		Do While strSourcePath = "" 
	
			strSourcePath = cin.ReadLine
		
		Loop
	End If

	'prove
	wscript.echo strSourcePath

	



Clean up strings

When you need to handle 'dirty' output, e.g. from StdOut (output of commands run at the command prompt), you often end up with strings that are full of tabs, newlines, carriage return, lots of spaces for formatting, etc. These characters bevome a pain in the lower part of the back when you want a clean string (an ip address from ipconfig, a FQDN from nslookup, ...). The trim() function only deals with spaces - on CR/LF or tab and you're out. The following function handles all whitespace / Line feed characters that may be surrounding the string you actually want :

Function cleanupString (theString)
	' clean up a string from StdOut etc : remove spaces, tabs and newlines / carriage returns
	
	theString = Trim (theString)

	Do While  (	ASC(Right(theString,1)) < 33  OR _
			ASC(Right(theString,1)) > 127 		)

		theString = Left (TheString, Len(TheString)-1)
	Loop

	Do While  (	ASC(Left(theString,1)) < 33  OR _
			ASC(Left(theString,1)) > 127 		)

		theString = Right (TheString, Len(TheString)-1)
		theString= Trim (TheString)
	Loop

	cleanupString = theString
End Function