Introduction to the Windows Script Host’s
scriptable controls
Scripts are also useful for non-repetitive tasks as well. If a
task requires you to do many things in sequence, you can turn that
sequence of tasks into just one task by scripting it. The WSH
libraries (Comctl32.dll, Shell32.dll,
Shlwapi.dll, all under the System directory) are the
components of WSH, and they allow the various script controls to be
exposed via different forms of scripts. For example, in the case of
a script embedded in an ASP page, the engine that interprets and
runs the script code is built into Internet Information Services
(IIS). If it is standalone, then the WSH itself takes care of it. In
our case the script is embedded in an HTML page, so the engine
component that interprets and runs the script code is loaded by the
Web browser, such as Internet Explorer. i.e. from the point of view
of the web programmer, this is identical to programming an ASP page
– only the objects used are different. Let’s look at them in summary
– the ones that we will use in this article are indicated with a red
border:
- WScript Object: Provides access
to most of the objects, methods, and properties in the WSH object
model.
- WshArguments Object: Gives
access to the entire collection of command-line parameters in the
order in which they were originally entered.
- WshController Object: Exposes
the method CreateScript() that
creates a remote script process. This allows the execution of a
script file at a remote server.
- WshEnvironment Object: Gives you
access to the collection of Microsoft Windows system environment
variables.
- WshNamed Object: Provides access
to the named command-line script arguments within the WshArguments object.
- WshNetwork Object: Gives you
access to the shared resources on the network to which your
computer is connected.
- WshRemote Object: Provides
access to the remote script process.
- WshRemoteError Object: Exposes
the error information available when a remote script (a WshRemote object) terminates as a result
of a script error.
- WshScriptExec Object: Provides
status and error information about a script run with Exec, along with access to the stdIn, stdOut, and stdErr channels.
- WshShell Object: Gives you
access to the native Windows shell functionality.
- WshShortcut Object: Allows you
to create a shortcut programmatically.
- WshSpecialFolders Object: Allows
you to access the Windows Special Folders. This provides
convenient access to OS folders using standard names, regardless
of the exact Windows OS version. For example, "Favorites" will be
under WINNT or WINDOWS depending on the OS, but in code it need
only be referred to as SpecialFolders("Favorites").
- WshUnnamed Object: Provides
access to the unnamed command-line script arguments within the
WshArguments object.
- WshUrlShortcut Object: Allows
you to create a shortcut to an Internet resource,
programmatically.
- Shell Object: Represents the
objects in the Windows Shell. Methods are provided to control the
Shell and to execute commands within the Shell. There are also
methods to obtain other Shell-related objects.
- Folder Object: The Folder object represents a folder. It
contains properties and methods that allow you to retrieve
information about the folder.
- FolderItem Object: The FolderItem object represents an item in a
Shell folder (which could also be a folder). It contains
properties and methods that allow you to retrieve information
about the item.
Before we dive into the details of this technology let’s define a
scope for our HTML Installer application.
Application definition
Our application’s aim is to supply our users with a set of HTML
pages that demonstrate the usage of the various WSH objects, in a
relevant manner to web programmers. The intention is to demonstrate
that by writing simple scripts, as would be the case for HTML or ASP
pages, many complicated operating system tasks can be performed. Our
choice of an installation application aims to demonstrate that an
area traditionally served by compiled executables can instead be
reached over the web via script-containing HTML pages.
Requirements
For the download code to work you simply need to be working
with:
- Windows 2000, Windows 98, Windows XP, regardless of IE
version. Or
- Windows NT 4.0 with Internet Explorer 4.0+, Windows 95 with
Internet Explorer 4.0+
If you are executing the pages locally, i.e. not over a web
server, then the default security settings of IE are fine. It will
display warnings for the ActiveX controls, prompting the user to
allow them to run. This is similar to other executable installation
programs. However, if you are serving the pages over the Net and
users will be using them directly (i.e. without saving them locally
first) then you will need to explain that their security settings
should be modified as shown below.
No web site should ask this level of trust from its users
without properly explaining what the downloaded web page will
do.
The security settings that need to be modified are in Tools:Internet Options:Security tab. Having
the Internet zone selected, click on
the Custom Settings button. In the
screen that appears you will need to set the "Initialize and script ActiveX Controls not marked
as safe" option to "Enable"
("Prompt" will not work):
The Interface
The main HTML page is installer.html. It divides the
screen in two frames, the leftmost one called menu displays the page
installermenu.html, and the other called steps displays the pages to be called from
links inside installermenu.html. Each step in the fictitious
installation process (nothing actually gets installed) is displayed
in a separate HTML page, called step1.html, step2.html
etc.. Here is what the application looks like upon opening:
The first step helps the user modify his PC settings if the page
is not entirely visible. Installation programs commonly ask the user
to perform various tasks without giving any express guidance on how
to do that. On our page, simply clicking on the Desktop control panel item hyperlink we get
the appropriate system screen, without having to necessarily know
how to open it:
The code that achieved this is very simple. Firstly, in
installermenu.html we create an instance of the WSH using the
<OBJECT> tag and the WSH root
Shell object class ID: <OBJECT ID="oShell"
CLASSID="clsid:13709620-C279-11CE-A49E-444553540000">
</OBJECT>
A list of other class IDs for other Shell objects, like Folder and FolderItem, can be viewed at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_programming/objectmap.asp&WROXEMPTOKEN=2300906Z2lL370fkoc0nzZKS6q.
We will be creating them programmatically, not via declarative
HTML.
Although the Shell object could be
instantiated by using a JavaScript command like the one below: var oShell = new ActiveXObject("Shell.Application");
it is preferable to use the <OBJECT> tag so that we can refer to
this oShell object from within the
other screen frame. Otherwise, we would have to recreate a Shell object for every installation step
that we take.
The rest of the code is inside the page step1.html. The
anchor link is actually defined as: <a href="javascript:ChangeScreen()" >Desktop control panel item</a>
which calls the JavaScript function ChangeScreen() containing a one-liner: function ChangeScreen() {
window.parent.menu.oShell.ControlPanelItem("desk.cpl");
}
It is really that simple. The ControlPanelItem method of the Shell object takes one argument: the
filename of the control panel item to be opened. If an instance is
already open it activates it. You can see a list of your PC’s
control panel items in your Windows System directory – look for the
.cpl extension. A second control panel item example is
presented in Step 2. The text presented to the user is this:
The first link calls the ControlPanelItem method with the appwiz.cpl parameter. Try it on any Windows
OS, it works with the same code.
The second link demonstrates the use of file copying and the
special Windows folders enumeration. Clicking it calls the function
CopyThis() whose code is shown
below: function CopyThis() {
//copy to Desktop, represented by number 0
var objFolderTo = window.parent.menu.oShell.NameSpace(0);
//copy from Favorites, represented by number 6
var objFolderFrom = window.parent.menu.oShell.NameSpace(6);
//fill a variable with all the contained items
var objFolderItems = objFolderFrom.Items();
//choose to copy the first one - it is also possible to
//search by name, test whether it is a file or a folder etc.
document.all.cache.value = objFolderItems.Item(0).Name;
if (objFolderItems.Item(0) != null)
{
//copy the file, with Yes to All to any dialog box and
//ability to rename if file exists already at destination
objFolderTo.CopyHere(objFolderItems.Item(0), 16 + 8);
}
}
As the comments in the code explain, we use the Namespace method with a number designating a
special Windows folder. For a list of these special folders’ numbers
see here. In this example the folder to copy from is the
Favorites folder (6) and we are copying to the Desktop (0). The
Namespace method can also take a string with the full path to a
folder, e.g. C:\\Windows\\Favorites on Windows 98. However,
using a string has the disadvantage of needing to specify a
different one for each OS to be supported.
The actual copying is performed by the CopyHere function, which takes a FolderItem object as the first argument and
an optional second argument specifying various options. A full list
of the options can be found here. In our case, if any messages appear during the
operation we answer with "Yes to All" (16) and if the item already
exists the copying proceeds by giving the file an alternative name
(8). If you try this on your system you will most probably see the
folder Channels copied onto your Desktop. You can easily
delete it but I apologize in advance for the inconvenience – I hope
you find it’s worth it for the sake of demonstrating the technology
:o). The function can be used in a commercial installation
application for copying files to their final destination, especially
if the destination is a SpecialFolder
member.
Onto Step 3, where we will actually execute a file on the user’s
system:
By clicking on the browse to the
folder link a browsing dialog is displayed:
Browse to the directory where you have unzipped the article’s
download and click OK. You will see
that a file specified by the code is opened – in this case it's a
simple text file, but one could easily start up an executable or a
registry entries file etc.:
The code to achieve this involves the familiar Folder and FolderItems, and a new function InvokeVerb(): function FindSetup() {
//call method for browsing dialog, returning a Folder object
var myFolder = window.parent.menu.oShell.BrowseForFolder(0,
"Find setup folder", 0, "C:\\");
if (myFolder!=null) {
//fill an array with the contained FolderItems
var objFolderItems = myFolder.Items();
if (objFolderItems!=null) {
//loop through the FolderItems checking for the
//name we are searching for
for (var i=0;i<objFolderItems.Count;i++) {
var objFolderItem = objFolderItems.Item(i);
if (objFolderItem.Name == "THEPLAN.TXT") {
//invoke the default verb for this file, Open
objFolderItem.InvokeVerb();
break;
}
}
}
}
}
This time we create a Folder object
via the user’s browsing action. The BrowseForFolder method takes 3 required
parameters and one optional. The first is the handle to the dialog
window, which can be left as 0. The
second is a title to display, and the third is a list of browsing
options described in the BrowseForFolder page on MSDN. The fourth optional
parameter specifies the highest browsing level that the user can
browse to. In our case, the user cannot go higher than the root
C: drive. You can also specify a special folders integer, as
described before.
We then examine the Name property
of each contained FolderItem and when
a known name is found (THEPLAN.TXT) we
invoke the default verb on the file. This is equivalent to
double-clicking it, or right-clicking it and selecting the action
displayed in bold:
You can choose other verbs by either typing their name, e.g.
objFolderItem.InvokeVerb("edit"); or
supplying an ordinal number. A list of the ordinals and available
verbs is given via the FolderItemVerbs
object (Verbs method of a FolderItem). You can see the usefulness in
executing any file that the user has downloaded on the machine, in
this user-friendly way of not requiring to switch windows and
contexts.
So far we have dealt with the right-most column of the WSH Object
Model diagram at the beginning of the article, namely the Shell, Folder
and FolderItem objects and their
methods. We will now create the WSH Shell object, which supplies the programmer
with some more liberal permissions in accessing the local system.
Step 4 in the HTML installation program demonstrates this by
creating a file. In this occasion it is a shortcut to a web URL,
placed on the Desktop:
The first link calls the following function: function MakeShortcut() {
var WshShell = new ActiveXObject("WScript.Shell");
strDesktop = WshShell.SpecialFolders("Desktop");
var oUrlLink = WshShell.CreateShortcut(strDesktop + "\\Link to Help Page.url");
oUrlLink.TargetPath = "http://www.someurl.com";
oUrlLink.Save();
}
Because the WScript.Shell object
has more capabilities, a warning is displayed asking us whether we
want to allow the object to carry out its functions. We can alert
our users that this is safe to say yes to – it is no more unsafe
than executing an executable installation program. However, as
mentioned in the Requirements section,
no website should ask this level of trust from its users without
properly explaining what the downloaded web page will do. This is
true of any type of installation program.
The MakeShortcut() function creates
the WSH Shell object and then uses the SpecialFolders method to get a reference to
the Desktop path. Don’t confuse this method, which creates a WSH
Special Folders object, with the Shell’s special folders constants
enumeration – see these two links for a detailed explanation: Shell Special folders constants; WSH Special Folders object. We then use the Desktop
reference to create a WshUrlShortcut
object via the CreateShortcut
function. Finally, we set the TargetPath attribute to our imaginary help
page and save the link.
The second hyperlink in Step 4 uses the scripting Shell object to minimize all the windows, so
that we can check that the URL shortcut was indeed created: function MinAll() {
window.parent.menu.oShell.MinimizeAll();
}
The shortcut should be on your PC’s Desktop – delete it as it is
just a sample:
Now, Step 5 is getting really daring as far as web pages are
concerned: we will add values to the machine’s registry… and then
delete them of course! This is what Step 5 consists of:
The function WriteReg() carries out
the writing of values using the RegWrite() method of the WSH Shell
object: function WriteReg() {
var WshShell = new ActiveXObject("WScript.Shell");
WshShell.RegWrite ("HKCU\\Software\\ACME\\ASPToday\\", 1,
"REG_DWORD");
WshShell.RegWrite ("HKCU\\Software\\ACME\\ASPToday\\Installer",
"CostasH", "REG_SZ");
//assign the values to the page’s textboxes
document.all.dword.value = WshShell.RegRead
("HKCU\\Software\\ACME\\ASPToday\\").toString();
document.all.sz.value = WshShell.RegRead
("HKCU\\Software\\ACME\\ASPToday\\Installer");
}
When the function runs (say "Yes" to the ActiveX warning dialog),
the textboxes display the values that have been registered:
To confirm that they have been written, click on the last
hyperlink on the page – you will get the Run file dialog, as if you
had pressed Start:Run … from the
Windows interface. The function opening the dialog uses the RunFile method of the Shell object: function RunComm() {
window.parent.menu.oShell.FileRun();
}
Type regedit in the Run
dialog and click OK :
The registry editor program opens up. You can browse to the
HKEY_CURRENT_USER\Software directory and confirm that the
values have been inserted:
To delete them we simply run the following function by clicking
on the second hyperlink: function DelReg() {
var WshShell = new ActiveXObject("WScript.Shell");
WshShell.RegDelete ("HKCU\\Software\\ACME\\ASPToday\\Installer");
WshShell.RegDelete ("HKCU\\Software\\ACME\\ASPToday\\");
WshShell.RegDelete ("HKCU\\Software\\ACME\\");
}
The registry entries should be completely deleted. Again, a very
useful way of delivering a complete installation process via a
humble HTML page.
Finally, Step 6 simply presents the Shutdown dialog box, asking
the user to reboot: function CloseSystem() {
window.parent.menu.oShell.ShutdownWindows();
}
Conclusion
We have seen only some of the capabilities of the scriptable
Windows shell functions. As you can see from the documentation
links, they can be very powerful in performing a wide range of
administration tasks. In our example, we are assisting the user to
perform a fictitious installation, demonstrating the ability to
present a customized HTML interface that can function on most
Windows platforms. Easy delivery, familiar interface, and
single-source code are just some of the advantages. |