The Windows Scripting Host - dFPUG-Portal
The Windows Scripting Host - dFPUG-Portal
The Windows Scripting Host - dFPUG-Portal
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Print Article<br />
Issue Date: FoxTalk January 1999<br />
<strong>The</strong> <strong>Windows</strong> <strong>Scripting</strong> <strong>Host</strong><br />
John V. Petersen<br />
Remember batch files? <strong>The</strong>y were easy to program and very<br />
productive in that many tasks could be automated. That's what<br />
<strong>Windows</strong> has been missing -- the ability to easily create and use<br />
batch files. This gap has been filled by the <strong>Windows</strong> <strong>Scripting</strong> <strong>Host</strong>,<br />
an engine that allows script code to be run by the OS. Not only is the<br />
<strong>Windows</strong> <strong>Scripting</strong> <strong>Host</strong> a powerful engine for running script code, it<br />
also (surprise!) sports a powerful object model as well. This column<br />
will introduce you to the basics of how the scripting host works and<br />
how you can incorporate its features into your VFP applications.<br />
<strong>The</strong> <strong>Windows</strong> <strong>Scripting</strong> <strong>Host</strong> (WSH) is a language-independent scripting engine. <strong>Scripting</strong> languages such as VBScript and<br />
JScript can be used to drive many processes. <strong>The</strong> same language you use to create client-side scripts in Internet Explorer (IE)<br />
or server-side scripts in Internet Information Server (IIS) can now be hosted by the <strong>Windows</strong> operating system itself.<br />
Prior to the release of the WSH, the only scripting language that existed for <strong>Windows</strong> was MS-DOS batch files. Although<br />
powerful, batch files lack the control over the <strong>Windows</strong> operating system that's really desired. <strong>The</strong> WSH provides this<br />
capability.<br />
What you need to get started<br />
Before I go much further, I should mention that all of the files required to work with the WSH can be downloaded from the<br />
Microsoft Web site at http://msdn.microsoft.com/scripting/. In addition to the core scripting engine, a series of white papers,<br />
code samples, and technical articles can be downloaded as well.<br />
Once you've downloaded the scripting files and run the installer program, you're off to the races!<br />
<strong>Scripting</strong> files<br />
Unlike scripting in Active Server Pages, where the language can be specified with tags embedded in the file itself, the same<br />
isn't true for script files used by the WSH. Rather, the WSH relies on the file extension to determine which language to use. If<br />
the script file ends in VBS, VBScript is used. If the script file ends in JS, JScript is used.<br />
<strong>The</strong> following simple "hello world" example points out the differences between VBScript and JScript:<br />
VBSscript:<br />
'hello world.vbs<br />
Dim WSHShell<br />
Set WSHShell = WScript.CreateObject("WScript.Shell")<br />
WSHShell.Popup "Hello World"<br />
JScript:<br />
// hello world.js<br />
var WSHShell = WScript.CreateObject("WScript.Shell");<br />
WSHShell.Popup("Hello World")<br />
<strong>The</strong> following is a more complex example that uses scripting to open and control Microsoft Excel:<br />
'This VBScript File opens Excel and creates a workbook<br />
Dim objXL,oWorkbook<br />
Set objXL = WScript.CreateObject("Excel.Application")<br />
objXL.Visible = TRUE<br />
Set oWorkbook = objXL.WorkBooks.Add<br />
With objXL<br />
.Cells(1,1) = oWorkbook.Sheets.Count<br />
End With<br />
Seite 1 von 6<br />
Running these script files is a very simple task. In Explorer, you can click the right mouse key over the file, and select Open.<br />
Alternatively, you can double-click the item in Explorer as well. Yet another alternative is to use the Run method of the<br />
<strong>Windows</strong> <strong>Scripting</strong> Shell object. This technique will be illustrated when the Shell Object is discussed in detail.<br />
http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=...<br />
31.01.06
Print Article<br />
A quick word about debugging and handling errors<br />
No programming environment is complete without a full-featured debugging environment. <strong>The</strong> WSH is no exception, as it also<br />
has a full-featured debugger. As far as error handling is concerned, VBScript doesn't have a global error handler. Rather,<br />
errors need to be handled on an in-line basis. <strong>The</strong> following code demonstrates how to deal with errors on an in-line basis:<br />
On Error Resume Next<br />
dim objxl<br />
Set objXL = WScript.CreateObject("Excel.Application")<br />
objxl.foo ' reference a non-existent Excel Method<br />
If Err.Number > 0 <strong>The</strong>n<br />
Call ErrorProc<br />
End If<br />
Sub ErrorProc<br />
msgbox err.description<br />
End Sub<br />
If no error trapping exists, you'll be prompted with a dialog box asking if you wish to debug the application. Figure 1 illustrates<br />
how the code will appear in the script debugger.<br />
Figure 1. <strong>The</strong> Microsoft Script Debugger uses the same IDE as Visual InterDev and Visual J++ 6.0.<br />
<strong>The</strong> WSH objects<br />
<strong>The</strong>re are two primary objects contained within the WSH. <strong>The</strong> following code illustrates how these objects can be created:<br />
WSHshell = CreateObject("Wscript.Shell")<br />
WSHNetwork = CreateObject("Wscript.Network")<br />
Both the shell and network objects are hosted by the wshom.ocx ActiveX Control.<br />
Complete documentation for the WSHShell and WSHNetwork Objects can be found by navigating to the following URLs:<br />
http://www.microsoft.com/iis/support/iishelp/iis/htm/asp/wsho7t84.htm for the WSHShell object<br />
http://www.microsoft.com/iis/support/iishelp/iis/htm/asp/wsho20qc.htm for the WSHNetwork object<br />
Seite 2 von 6<br />
Shell object properties and methods<br />
Environment<br />
This property provides access to the environment collection. Information such as number of processors, paths, OS, and so<br />
forth can be determined from this collection.<br />
http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=...<br />
31.01.06
Print Article<br />
oEnv = wshshell.environment<br />
For Each x In oEnv<br />
?oEnv<br />
Next x<br />
<strong>The</strong> following is a partial listing of some typical environmental variables:<br />
NUMBER_OF_PROCESSORS<br />
OS<br />
PROCESSOR_ARCHITECTURE<br />
PROCESSOR_IDENTIFIER<br />
WINDIR<br />
So, to find out the number of processors:<br />
Numprocessors = oEnv.Item("NUMBER_OF_PROCESSORS")<br />
Like most collections, if you want to find out how many members are contained in the collection, you can refer to the Count<br />
property:<br />
Numitems = oEnv.Count<br />
To be compliant with the Java language, collections in the WSH also support the Length property, which provides the same<br />
functionality as the Count property:<br />
Numitems = oEnv.Length<br />
SpecialFolders<br />
This property provides access to the collection of <strong>Windows</strong> Shell folders. <strong>The</strong> following is a listing of folders:<br />
AllUsersDesktop<br />
AllUsersStartMenu<br />
AllUsersPrograms<br />
AllUsersStartup<br />
Desktop<br />
Favorites<br />
Fonts<br />
MyDocuments<br />
NetHood<br />
PrintHood<br />
Programs<br />
Recent<br />
SendTo<br />
StartMenu<br />
Startup<br />
Templates<br />
To find the actual path of the desktop folder, issue this line of code:<br />
DesktopPath = WSHShell.SpecialFolders("Desktop")<br />
CreateShortcut (strPathname)<br />
This method creates and returns a shortcut object. <strong>The</strong> following block of code illustrates how to create a desktop shortcut:<br />
*/ Read desktop path using WshSpecialFolders object<br />
DesktopPath = WSHShell.SpecialFolders("Desktop")<br />
*/ Create a shortcut object on the desktop<br />
MyShortcut = ;<br />
WSHShell.CreateShortcut(DesktopPath + ;<br />
"\Shortcut to MyFile.lnk")<br />
*/ Set shortcut object properties and save it<br />
FileName = GetFile()<br />
If !Empty(FileName)<br />
FileDir = JustPath(FileName)<br />
With MyShortcut<br />
.TargetPath = Filename<br />
.WorkingDirectory = FileDir<br />
.Save<br />
EndWith<br />
Endif<br />
Seite 3 von 6<br />
<strong>The</strong> CreateShortcut method returns a WSHShortcut object. This object is only exposed through the CreateShortcut method.<br />
<strong>The</strong> WSHShortcut object has the following properties:<br />
http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=...<br />
31.01.06
Print Article<br />
Arguments Parameters to a shortcut object<br />
Description A description of a shortcut object<br />
Hotkey <strong>The</strong> hot key of a shortcut object<br />
IconLocation <strong>The</strong> icon location of a shortcut object<br />
TargetPath <strong>The</strong> target path of a shortcut object<br />
WindowStyle <strong>The</strong> window style of a shortcut object<br />
WorkingDirectory <strong>The</strong> working directory of a shortcut object<br />
<strong>The</strong> WSHShortcut object only has one method -- Save() -- which saves the shortcut object to the file system.<br />
ExpandEnvironmentSettings (strString)<br />
This method expands a process environment variable and returns the result. A typical environment variable is WINDIR. <strong>The</strong><br />
following code illustrates how this method works:<br />
Fullpath = WSHShell.ExpandEnvironmentStrings ;<br />
("%windir%\notepad.exe, 0")<br />
Popup (strText, [natSecondsToWait], [strTitle], [natType])<br />
This method displays the Window MessageBox. Unlike the existing MessageBox function, the Popup method accepts an<br />
optional argument to clear the dialog box after a specified amount of time. <strong>The</strong> following line of code illustrates how the Popup<br />
method works:<br />
WSHShell.Popup("Message",1,"Title",64)<br />
Run(strCommand, [intWindowStyle], [blnWaitOnReturn])<br />
<strong>The</strong> Run method creates a new process that executes a specified command with a specified window style. In addition to being<br />
able to specify the command and the window style, a third parameter can be used to determine whether script execution<br />
should pause until the new process has terminated.<br />
Applications windows can be started in several states. <strong>The</strong> following outlines the various options available:<br />
SW_HIDE 0<br />
SW_MINIMIZE 6<br />
SW_RESTORE 9<br />
SW_SHOW 5<br />
SW_SHOWMAXIMIZED 3<br />
SW_SHOWMINIMIZED 2<br />
SW_SHOWMINNOACTIVE 7<br />
SW_SHOWNA 8<br />
SW_SHOWNOACTIVATE 4<br />
SW_SHOWNORMAL 1<br />
<strong>The</strong> following code starts Notepad with a normal window:<br />
WSHshell.Run("notepad",1)<br />
<strong>The</strong> following code starts Notepad with a maximized window. In addition, the user must close Notepad before control will<br />
return to VFP:<br />
WSHshell.Run("notepad",3,.T.)<br />
Fully qualified paths can be used to denote a file to execute. <strong>The</strong> following code starts Visio:<br />
WSHshell.Run("D:\VISIO\VISIO32.EXE")<br />
Also, script files can be executed with the Run method as well:<br />
WSHshell.Run("hello world.vbs")<br />
WSHshell.Run("hello world.js")<br />
Network object properties and methods<br />
ComputerName<br />
This property denotes the name of the computer:<br />
ComputerName = WSHNetwork.ComputerName<br />
UserDomain<br />
http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=...<br />
Seite 4 von 6<br />
31.01.06
Print Article<br />
This property denotes the domain to which the user belongs:<br />
DomainName = WSHNetwork.UserDomain<br />
UserName<br />
This property denotes the ID of the currently logged-in user:<br />
UserName = WSHNetwork.UserName<br />
AddPrinterConnection(strLocalName, strRemoteName, [bUpdateProfile], [strUser], [strPassword] )<br />
This method maps a network printer to a local resource.<br />
WSHNetwork.AddPrinterConnection("LPT1","\\server\ ;<br />
printer_share",.T.,"UserID","Password")<br />
Of special interest here is the third parameter -- bUpdateProfile. If this parameter is set to .T., the user profile for the local<br />
machine is updated to restore the printer mapping the next time the user logs onto the machine and network.<br />
EnumNetworkDrives<br />
This method returns a collection of drive mappings. <strong>The</strong> following code loops through the collection of network drive<br />
mappings:<br />
oDrives = WSHNetwork.EnumDriveMappings<br />
item = -1<br />
For Each x In oDrives<br />
item = item + 1<br />
If Mod(item,2) = 0<br />
?"Drive Letter: ",x<br />
Else<br />
?"Network Resource: ",x<br />
Endif<br />
Next x<br />
Like other collections, the drive mapping collection supports both the Count and Length properties as well as the Item()<br />
method.<br />
EnumPrinterConnections<br />
This method works just like the EnumNetworkDrives, with the difference being that the collection returned represents printers,<br />
not drive mappings:<br />
item = -1<br />
For Each x In oPrinters<br />
item = item + 1<br />
If Mod(item,2) = 0<br />
?"Printer Name: ",x<br />
Else<br />
?"Network Resource: ",x<br />
Endif<br />
Next x<br />
MapNetworkDrive(strLocalName, strRemoteName, [bUpdateProfile], [strUser], [strPassword] )<br />
This method works just like the AddPrinterConnection Method, with the exception that a local drive to a network resource is<br />
created:<br />
WSHNetwork.MapNetworkDrive("z:","\\server\ ;<br />
server_share",.T.,"User","Password")<br />
RemoveNetworkDrive(strName, [bForce], [bUpdateProfile] )<br />
This method removes a specified network drive mapping. Optionally, you can force the removal even if the resource is being<br />
used. An optional third parameter specifies whether the user profile should be updated:<br />
WSHNetwork.RemoveNetworkDrive("z:",.T.,.T.)<br />
or<br />
WSHNetwork.RemoveNetworkDrive("\\server\ ;<br />
server_share",.T.,.T.)<br />
RemovePrinterConnection(strName, [bForce], [bUpdateProfile] )<br />
This method works just like the RemoveNetworkDrive method, with the exception that a printer resource is being removed:<br />
WSHNetwork.RemovePrinerConnection("LPT1",.T.,.T.)<br />
http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=...<br />
Seite 5 von 6<br />
31.01.06
Print Article<br />
or<br />
WSHNetwork.RemovePrinterConnection("\\server\ ;<br />
printer_share",.T.,.T.)<br />
SetDefaultPrinter(strName)<br />
This method sets the default printer:<br />
WSHNetwork.SetDefaultPrinter("\\server\printer_share")<br />
Conclusion<br />
<strong>The</strong> ability to work with the <strong>Windows</strong> Registry, create desktop shortcuts, and map and view network resources all required you<br />
to know how to use extensive <strong>Windows</strong> API functions, or a third-party DLL. <strong>The</strong> WSH provides a simple and elegant set of<br />
objects with simple interfaces that allow you to accomplish many tasks. Perhaps your application requires special Registry<br />
entries. Perhaps you've been tasked with developing a utility that modifies the default printer or dynamically maps network<br />
resources. All of these tasks can easily be accomplished with the WSH.<br />
<strong>The</strong> good news is that the WSH will be a standard part of the operating system beginning with <strong>Windows</strong> 2000. Until the<br />
release of <strong>Windows</strong> 2000, you'll need to make sure the WSH is installed on any client workstation that uses your application.<br />
One approach to this problem is to add a method to your application class that tests to see whether the WSH is installed. If it<br />
isn't, prompt the user through the process of both downloading and installing the WSH.<br />
<strong>The</strong> <strong>Windows</strong> <strong>Scripting</strong> <strong>Host</strong> -- yet another valuable tool to add to your toolbox!<br />
Sidebar: VFP Bug Alert!<br />
While the documentation states that the second argument in the Popup method specifies a timeout interval in which the<br />
MessageBox will be cleared, it doesn't work in VFP. I tested this code in Visual Basic, and the expected behavior occurred.<br />
This behavior has been reported to the VFP team and hopefully will be fixed in the next release.<br />
<strong>The</strong> WSH Shell object provides three methods for working with the <strong>Windows</strong> Registry:<br />
RegWrite(strName, anyValue, [strType] )<br />
RegDelete(strName)<br />
RegRead(strName)<br />
With these methods, entries can be created, written, read, and deleted. If you attempt to write to a key that doesn't exist, the<br />
key will be created. <strong>The</strong> code in Listing 1 illustrates how these three methods work (click on the Listing link for the<br />
code).<br />
http://foxtalknewsletter.com/ME2/Audiences/Segments/Publications/Print.asp?Module=...<br />
Seite 6 von 6<br />
31.01.06