Wiki Home

Windows Scripting Host


Namespace: Wiki
Windows Script Host, (ex Windows Scripting Host) is a Win32 application that allows scripts to be run within the Windows environment. It is akin to the old DOS Batch files, but much more powerful. It is a COM Server so you can get a reference to its object model in any Windows COM compliant language, plus Windows (and DOS under Windows) can run the scripts itself.

Beware, however: Microsoft's WSH page is at: http://msdn.microsoft.com/scripting/default.htm

The Windows Scripting Host ActiveX control is very deep and featureful, and I won't pretend to write a big topic about it, but here are things that it can do:

To create a shortcut in the current directory:
oWsh = CreateObject("WScript.Shell")
oLink = oWsh.CreateShortcut("FoxWiki Web Site.URL")  && The .URL is required 
oLink.TargetPath = "http://fox.wikis.com"
oLink.Save()

-- Steven Black

To create a shortcut in the Desktop:
oWsh = CreateObject("WScript.Shell")
cDesktopDir = oWsh.SpecialFolders("Desktop")
oLnk = oWsh.CreateShortcut(cDesktopDir + "\\Shortcut to Notepad.lnk")
oLnk.TargetPath = oWsh.ExpandEnvironmentStrings("%windir%") + "\notepad.exe"
oLnk.Save()

-- Alex Feldstein, Willson De Veas

The Special Folders you can use are:
AllUsersDesktop
AllUsersStartMenu
AllUsersPrograms
AllUsersStartup
Desktop
Favorites
Fonts
MyDocuments
NetHood
PrintHood
Programs
Recent
SendTo
StartMenu
Startup
Templates

-- Alex Feldstein

With WScript.Shell::Run(), external commands can be run much more flexibly than from the VFP RUN (!) command. - ?lc

> Not only that but it allows for synchronous execution of DOS programs avoiding the common problem when doing a standard RUN with DOS that VFP does not wait and merrily continues.
#define SW_SHOW_NORMAL 1
#define SW_SHOW_MINIMIZED 2
#define SW_SHOW_MAXIMIZED 3
oShell = createobject("WScript.Shell")
oShell.Run("notepad.exe",SW_SHOW_NORMAL,.T.)
-- Alex Feldstein

Another neat little piece of code - recurse a subtree without the vagaries of VFP3, 5 & 6 ADIR()'s improper handling of names (i.e., VFP converts names to upper case) and requirements to change directories to avoid picking up files as well:

VFP8,7 and 6 (and probably 5) allow inclusion of directory as part of the file skeleton obviating the need to change directory. Also, in 7 and 8, an additional argument allows you to specify returning file names in the case that's stored on disk, making the Windows Scripting Host unnecessary for this task.
* Procedure file FSOTree

SET PROC TO FSOTree ADDITIVE
CLEAR
DECLARE aSubDirs[1]
? GetTreeUsingFSO(@aSubDirs,'C:\')
disp memo like aSubDirs
RETURN


FUNCTION GetTreeUsingFSO
   LPARAMETER taReturnArray, tcBaseFolder
   EXTERNAL ARRAY taReturnArray
   IF VARTYPE(tcBaseFolder) # 'C' OR ! DIRECTORY(FULLPATH(tcBaseFolder))
      tcBaseFolder = FULLPATH(CURDIR())
   ENDIF

   LOCAL oFSO
   oFSO = CREATEOBJ('Scripting.FileSystemObject')
   DIMENSION taReturnArray[1]
   taReturnArray = NULL
   RecurseSubFoldersUsingFSO(oFSO.GetFolder(tcBaseFolder),@taReturnArray)
   RETURN ALEN(taReturnArray)
ENDFUNC


FUNCTION RecurseSubFoldersUsingFSO
   LPARAMETERS toFolderObj, taReturnArray
   EXTERNAL ARRAY taReturnArray
   LOCAL nSizeOfArray
   nSizeOfArray = ALEN(taReturnArray) + IIF(ISNULL(taReturnArray[1]),0,1)
   DIMENSION taReturnArray[nSizeOfArray]
   taReturnArray[nSizeOfArray] = toFolderObj.path
   FOR Each oFolder IN toFolderObj.SubFolders
      RecurseSubFoldersUsingFSO(oFolder,@taReturnArray)
   ENDFOR
   RETURN
ENDFUNC

Ed Rauh

Interesting OLE error under Windows 2000 OLE error code 0x800a0046: Unknown COM status code. Further investigation reveals that the OLE error occurs when accessing the folder objects for c:\system volume information -- Paul Borowicz
Change a file's attributes:
#define READONLY 1
#define HIDDEN 2
#define SYSTEM 4
#define DIRECTORY 16      && folder's attribute
#define ARCHIVE 32
oFSO = CreateObject("Scripting.FileSystemObject")
oFile = oFSO.GetFile("c:\dummy.txt")
lnOldAttribute = oFile.Attributes      && saves current attributes (numeric)
oFile.Attributes = READONLY      && changes to RO

-- Alex Feldstein
Check if a floppy is inserted in drive:
oFSO = CREATEOBJECT("Scripting.FileSystemObject")
? oFSO.FolderExists("A:\")

-- Alex Feldstein
Disk Space() is not reliable on big disks or NTFS (pre VFP7)
You can use WSH instead:
oFSO = CREATEOBJ('Scripting.FileSystemObject')
oDrive = oFSO.GetDrive("C:")
? TRANSFORM(oDrive.AvailableSpace,"999,999,999,999")

-- Alex Feldstein
To rename a folder:
oFSO = CreateObject("Scripting.FileSystemObject")
oFSO.MoveFolder("c:\Folder1","c:\Folder2")

-- Alex Feldstein
And yet another example - map a drive letter on the fly, specifying a distinctly different userid and password for the attachment:

The Wscript.Network's MapNetworkDrive will take optional user name and password parameters, for example:

oWSHNet = CREATEOBJECT('Wscript.Network')
oWSHNet.MapNetworkDrive('Q:','\\SomeServer\AppShare',.f.,'Foo','Bar')


maps drive Q: to \\SomeServer\AppShare share, does not update the user profile data to auto-map the drive again, using the user id "Foo" and the password "Bar", and this functionality exists in even the version 1 WSH implementation. The first two parameters -m the local device and the share name as a UNC are mandatory. The third parameters is optional, when true, it updates the currently logged-in user profile to auto-map this drive again when logging in. The fourth and fifth parameters are optional user name and password; the Windows Login username and password will be passed if not specified.

The Win32 API's WNetAddConnection3() is more capable, but is a bit of a PITA to implement in VFP - there's sample code showing one approach in my NETRESOURCE class on UT, and Christof Wollenhaupt wrote a STRUCT class which makes the implementation easier if you don't want to use CLSHEAP for managing the structure memory yourself. -- Ed Rauh

For anyone out there who didn't hear about it yet: a network worm is using WSH's MapNetworkDrive to poke around at random IP addresses for un-password protected shares named "C" and then copying itself to "\\\c\windows\start menu\programs\startup" (where it automatically runs the next time the computer is started). For more details, look at: http://pc-help.org/news/scriptworm.htm (and yes.. I was caught carelessly with my pants down... fortunately it's not malicious)
Help files useful for the Windows Scripting Host: vbscrip5.chm and wsh.chm, both on ?MSDN.

Sorry, I meant on the MSDN Library, which in October is a single DVD disk, and these files are in the \MSDN directory. You'll need to copy them to a read-write disk and take the read-only flag off the file in order to search within the files. -- Steven Black (who never actually installs MSDN and who thinks this one DVD MSDN Library disk is the cat's meow).

Steven - the Universal Subscription Content can be had on DVD starting January! And VFP6 Pro Owners or VS6/VB6 Pro or Enterprise can sign up for a free 1 year MSDN Library subscription, too! -- Ed Rauh
And some Web sites that deal in detail with WSH and scripting issues:

The WSH FAQ Site
devhead script library site
I'm a big advocate of the WSH; not only the three main automation objects (Wscript.Shell, as mentioned above provides lots of shell API automation, Wscript.Network, which provides access to much of the WNet API family, and Scripting.FileSystemObject, which does horrid, nasty (and incredibly useful) things to files and folders, and can retrieve a good deal of information about them as well), but generating and firing VBScript and JScript throught the WSCRIPT.EXE or CSCRIPT.EXE from inside a VFP application.
I guess the first thing to address is - where do I get it and how do I know if it's present? The Windows Scripting Host is incorporated into both Win98 and Win 2 K as a part of their base operating system, and is also added to the other Win32 platforms in any of several ways:

(1) Install IE 4 or later, and you get the WSH
(2) Install it from NT Option Pack 4
(3) Install IIS (this means that it's there with a full install of BackOffice or Small Business Server)
(4) Go out to MS WSH Site and download the self-installing executable for the WSH from there - it's updated fairly frequently, so I'll assume that people can navigate to the download from the home page. The self-installing executable is fully redistributable

Win95 retail editions need at least Win95 SP1 installed, and some foreign language versions require the foreign equivalent of OSR 2, which is not a free download, to install the WSH. OSR 2 and later have the necessary shell components to make it work. If the version of Win95 can install IE 4, it'll accept the WSH from the self-installing executable.

NT 4.0 needs at least NT 4.0 SP3 installed. I'm afraid the NT 3.51 users are out of luck unless there's a way to update through installing IE.

Win98, the Option Pack and IE4 have the WSH version 1 engine, the current IE5 and Win 2 K versions, and the beta WSH 2.0 engine have WSH version 2, which has lots of added features, mostly added methods to the Wscript.Shell and Wscript.Network objects. Even though it's still a beta, the WSH 2.0 platform is very stable and reliable, and is what's documented in the MSDN as of the October release.

The WSH version 2 requires the VBScript version 5 update - this is installed automagically if you use the self-installing executable.

IOW, load the WSH from the self-installing executable, preferably the beta WSH 2.0 version.

More later as I get the time...

Ed Rauh
Is it possible (from within VFP through COM) to execute some arbitrary lines of javascript or vbscript code? I'm looking, in essence, to be able to instantiate CSCRIPT.EXE as a COM object, then hand it either a .js file or the code from a .js file and have it execute it. (sort of like having within VFP in addition to EXEC( cCode ) another command JSEXEC( cJsCode ) and VBEXEC( cVbCode ) )? The only way I could figure out to do this is:

y='whatever multiple lines of javascript code you want'
=StrToFile(y,'myfile.js')
x=CREATEOBJECT('wscript.shell')
x.Run( 'cscript.exe myfile.js' )
but what I'd really like is something like:

y='whatever multiple lines of javascript code you want'
x=CREATEOBJECT('wscript.wscript')
x.exec( y, 'javascript' )

-- ?wgcs

You can do that with the Microsoft Script ActiveX control. Search MSDN for it - you'd have to create a wrapper for it though, because it takes some setup and event driven code to deal with the running code.

-- Rick Strahl

Thanks Rick! (for anyone else interested) Here's the address in MSDN: mk:@MSITStore:C:\Program%20Files\Microsoft%20Visual%20Studio\MSDN\2001JAN\1033\period00.chm::/html/visualprog0600.htm
On the MSDN web: http://www.microsoft.com/downloads/details.aspx?FamilyId=D7E31492-2595-49E6-8C02-1426FEC693AC&displaylang=en

I'm having a hard time with the concept/purpose of this... Best I can see is that the Script ActiveX control allows your application to execute VBScript "internally". How is that any different than creating a VFP COM server with methods that can be called from an external VBScript? And what's the big deal when you can do what wgcs posted above? -- William Fields

For what it's worth to this discussion, here is an example I created a while back for running vbscript and javascript within VFP. -- Craig SBoyd

Have to admit, that's cool. -- William Fields
See Also: Access Control Lists, Removing Windows Scripting Host
Contributors: Steven Black, Sergey Berezniker, Ed Rauh, Rick Strahl, Alex Feldstein, Willson De Veas, wgcs
Category ActiveX Category 3 Star Topics Category Code Samples
( Topic last updated: 2006.08.09 11:30:00 AM )