I decided to start the new year with a mixed bag of short, sharp, helpful scripts that you can incorporate into your scripts. All the scripts I discuss are easy to understand, and most have just two lines of code, making them good additions to your systems administration toolkit.
The Shell::Application Object
Microsoft Internet Explorer (IE) 4.0 introduced an object called Shell:: Application that can help you perform some unusual systems administration tasks. This object is native in Windows 2000, Windows Me, and Windows 98. If you use Windows NT 4.0 or Win95, you must be running IE 4.0 or later; however, if you use IE 5.0 with NT or Win95, the object might not load by default. If you experience that problem with IE 5.0 under NT 4.0, execute the command
To install the IE 5.0 object under Win95, run the command
If you use either command, be sure to type it all on one line in the command shell window.
IE 5.0 isn't strictly a requirement, but on NT 4.0 or Win95 systems running IE 4.0, the Shell object doesn't install unless you explicitly turn on the Active Desktop option. You should be able to turn on Active Desktop, install the object, then turn off Active Desktop, but if that fails, I suggest you go to IE 5.0. For background information about the Shell object, including how to install it, see Dino Esposito, "Understanding VBScript: The Windows Shell Object Model," October 2000, Instant Doc ID 15646.
When you copy a group of files on a Windows machine by dragging them, a progress window displays an animation of a piece of paper flying from one folder to another. The Shell::Application object lets you use the copy function and the animated progress window in your scripts. The code in Listing 1 displays the animated progress box while the code creates an instance of the Shell::Application object, uses that object's NameSpace method to create a Folder object (i.e., C:\my scripts), then uses the Folder object's CopyHere method to copy files from the C:\alistair folder to the C:\my scripts folder. The method copies the entire subfolder structure from C:\alistair. However, you can easily specify just one file or use a wildcard to specify a range of files.
The progress window includes a Cancel button that you can click to cancel the copy task. However, the CopyHere method provides no rollback, so if you cancel the task, you must clean up the files.
Another use of the Shell::Application object is to move a group of files. AnimatedMove.vbs, which Web exclusive Listing 1 shows, uses the Folder object's MoveHere method to move the entire C:\alistair subtree, including the alistair folder, into the C:\my scripts folder. (You can find Web exclusive listings and code by going to http://www.winscriptingsolutions.com and entering the InstantDoc ID.) You can also use the Shell:Application object to perform numerous shell functions, as Web exclusive Listing 2 shows. The Shell::Application object's MinimizeAll method minimizes all windows on a user's screen, and the object's UndoMinimizeALL method returns the windows to their unminimized state. This script is useful when you want to be sure a user knows that a script is running and prevent active windows from hiding subsequent warning boxes. Remember to perform some function between the MinimizeAll and UndoMinimizeAll functions; otherwise, they just cancel each other.
SelectFolder.vbs lets the user select a folder from a treeview window. Listing 2 shows SelectFolder.vbs, which uses the Shell::Application object's BrowseForFolder method to create a treeview window in which the user can select a folder. The code then returns the Folder object that represents that folder. You can customize how the window appears and acts by passing as many as four parameters to the method. The first parameter provides a window handle; for your scripts, the first parameter should always be zero. The second parameter is a text string to display in the window's upper left corner—in Listing 2, I've specified Please select a file. Figure 1 shows where the specified text string appears. You can use the third parameter to display only certain objects (e.g., printers). The values for this parameter are quite complex, so I won't discuss them in detail. To display all objects, use the value -1. The fourth parameter (an optional parameter that my script doesn't use) lets you restrict the user to picking a folder from a specific subtree, such as C:\ or C:\my documents. To use this parameter, enclose the path in quotation marks; the user then will be unable to access anything above the specified part of the tree.
The BrowseForFolder method returns a standard Folder object, which you can manipulate just as you manipulate folders in Windows Script Host (WSH). For example, you can access the Folder::Title property, use the Folder::CopyHere or Folder:: MoveHere method as I explained earlier, or use the Folder::Items method to retrieve the folder's contents.
Shutdown.vbs, which Listing 3 shows, automatically displays the shutdown dialog box on a machine. Other Shell object methods let you pull up a host of other dialog boxes, such as the Run dialog box and the Windows Help dialog box. You can learn more about these and other Shell object methods on the Microsoft Developer Network (MSDN) at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/objects/shell/shell.asp.
The Rundll32 Program
A nifty little application on your Windows machine lets your scripts call methods and properties inside DLLs to perform a variety of system tasks without intervention. All you need to do is call rundll32.exe from your WSH script and pass the necessary parameters.
For example, would you like your script to format a floppy disk? Create a standard WScript::Shell object, then call the Shell::Run method to run the Format command from the shell. Listing 4 shows FormatFloppy.vbs, which creates a Wscript::Shell object called objWSH, then calls rundll32 .exe. The script passes the parameters shell32.dll (the name of the DLL that will run the Format command) and SHFormatDrive (the method in the DLL that formats a drive). Because someone could modify this script to format hard disks, the usual caveats about limiting access to your crucial machines apply here.
If you need to copy a disk, use DiskCopier.vbs. Web exclusive Listing 3 shows this script. DiskCopier .vbs is similar to FormatFloppy.vbs, but DiskCopier.vbs opens diskcopy.dll and uses the DiskCopyRunDll method.
OpenAs.vbs displays the Open With What Application dialog box to let you choose the application that should open a file. Web exclusive Listing 4 shows OpenAs.vbs, which uses the OpenAs_RunDLL method call from the shell32.dll file. The script also needs to pass to the OpenAs_Run DLL method the name of the file to be opened—my code specifies the file C:\my scripts\test.txt, which you will replace with the name of your file.
Control Panel Applets
The final group of scripts I discuss lets you direct users to a specific Control Panel applet. Control Panel applets reside in Control Panel (.cpl) files, which are usually in C:\winnt\system32 on Windows XP, Win2K, and NT and in C:\windows\system on Windows Me and Win9x. A Control Panel file can contain more than one applet. For example, main .cpl holds both the Control Panel Keyboard applet and the Control Panel Mouse applet in XP and Win2K. In addition, a Control Panel applet can have several tabs—Web exclusive Figure 1 shows the Mouse applet and its five tabs. You can not only tell Rundll32 to open Control Panel applets but also specify which tab the window will display.
Using Rundll32, you call the Control_Run DLL method of shell32.dll and pass from one to three parameters. The syntax of the Rundll32 call is
where the first parameter, file.cpl, is the filename (without the path) of the Control Panel applet you want to open. The remaining parameters are optional. The first optional parameter, @X, is the at (@) symbol followed by the number of the applet you want to open within the Control Panel file (the number of the first .cpl file is 0). The second optional parameter, Y, is the number of the tab that you want to select (the number of the first tab is always 0).
If you omit the first optional parameter, the method will open the first applet in the Control Panel file; if you omit the second optional parameter, the method will open the first tab. Listing 5 shows the script MouseAndKeyb .vbs, which opens the first tab of both the Mouse and Keyboard applets (applet 0 and applet 1, respectively) from within main.cpl. If you want to open the third tab of the Mouse applet in XP, you can use one of the following commands:
rundll32.exe shell32.dll,Control_RunDLL main.cpl,,2
Web exclusive Listing 5 shows IE-CPLProps.vbs. This script opens IE's Control Panel applet (which is named Internet Properties in XP and Internet Options in Win2K) at the default tab, then again at the fifth tab. Opening specific tabs is a good way to focus users on the appropriate part of an open window. Similarly, Install.vbs, which Web exclusive Listing 6 shows, opens the Control Panel Add/Remove Programs, Windows Setup, and Startup Disk applets. All three of these applets reside in appwiz.cpl.
InstallScreenSaverAndLock.vbs is my final example. This script, which Listing 6 shows, illustrates how to combine Rundll32 functionality with opening a Control Panel applet. First, the script calls the Install-ScreenSaver method from the desktop Control Panel file (desk.cpl), which activates an existing installed screen saver—SSStars.scr in the sample code—in the C:\windows\system or C:\windows\system32 directory. Next, the script calls the LockWorkStation method from the user32.dll file to lock the workstation. I like to run a script such as InstallScreenSaverAndLock.vbs on all machines overnight to set the company screen saver and lock the workstations. However, be aware that this script can have unusual results with certain screen savers, and I haven't managed to determine why. In some cases, instead of activating the screen saver, the first Install-ScreenSaver line will only open the Display Properties applet with the Screen Saver tab selected. If that happens, the user will need to either click OK or select the screen saver, then click OK. This behavior is a bit nonsensical, so I recommend that before deploying this script, you make sure it works correctly with your screen saver.
I hope that you find these scripts useful. If you create some short, sharp scripts that you think other readers would like to see, please send them to me.