Shell Operations
The WSH shell object provides the ability to create Windows shortcuts, read environment variables, manipulate registry settings, and run external programs.
To create an instance of the WSH Shell object, pass the argument "WScript.Shell" to the CreateObject method:
Set objShell =CreateObject("WScript.Shell")
Reading the Command Line Arguments
Problem
You want to read the command-line arguments.
Solution
All versions of WSH support the WScript object's Arguments property to get the command-line arguments. The following script attempts to set the read-only attribute for a file that is specified by a command-line argument:
'hidefile.vbs Dim objFileSystem, objFile 'check if the parameter count is a single parameter. ' If not then show the command syntax If WScript.Arguments.Count<>1 Then WScript.Echo "Syntax: "& WScript.ScriptName & _ " FileName " & vbCrLf & _ " Filename: the path of the file you wish to hide" WScript.Quit End If 'create FileSystem object Set objFileSystem = CreateObject("Scripting.FileSystemObject") On Error Resume Next 'get the file specified in command line Set objFile = objFileSystem.GetFile(WScript.Arguments(0)) 'check if error occured - file not found If Err Then WScript.Echo "Error:File:'" & WScript.Arguments(0) & "' not found" Else objFile.Attributes = 2 End If
WSH 5.6 introduces new elements to the WSF file format that allow for greater control in argument creation as well as a consistent method of script documentation. The following script performs the same operation as the first solution script using these new elements:
The hidefile.wsf filename script sets the hidden attribute for a specified file This is an example of how to use this script: Hidefile.wsf Filename:data.doc
Discussion
The Arguments collection contains the parameters that are passed to the script.
The Arguments collection is returned from the WScript object, which is a root WSH object and does not need to be created using CreateObject. The collection has a Count property that returns the number of items in the collection. The argument count is also accessible through the length property, which is included for JScript compatibility.
The Arguments collection is represented as an array with a 0 offset. The first argument would be stored as element 0, the second as 1, and so on. In the following command line, Fred is the first argument and Smith is the second:
Test.vbs Fred Smith
The following snippet represents the test.vbs script:
'test.vbs WScript.Echo "Argument 1 is " & WScript.Arguments(0) WScript.Echo "Argument 2 is " & WScript.Arguments(1)
If you want Fred Smith to be read as a single argument, it must be surrounded by double quotes (" "):
test.vbs "Fred Smith"
If you attempt to obtain an argument from the collection that has not been passed in the command line, an error will occur. In the previous example, passing "Fred Smith" to the test.vbs script will generate an error because the script attempts to display a second argument and "Fred Smith" is considered to be one argument.
The following example lists all parameters passed to the script:
'get a reference to the arguments collection 'output the first argument WScript.Echo WScript.Arguments(0) 'show each command line argument For Each arg in WScript.Arguments WScript.Echo arg Next
WSH version 2.0 and later supports drag-and-drop argument passing. Any files dragged onto a script file using Explorer can be obtained through the Arguments collection.
WSH version 5.6 (the version after 2.0) provides a more sophisticated command-line parameter handling using XML constructs in WSF files. This is provided through the XML element.
The advantage of this new element is that it provides a consistent method of documenting WSH scripts, as well as easier parsing of command-line arguments, which leads to less code.
The element appears at the beginning of a WSF file, inside the body of the job element. It can contain a number of elements that describe the script's arguments and provide examples.
The first element is the element. Any text between the beginning and end element is used for a script description, or whatever you want to put there. This is much easier than attempting to format a large block using WScript Echo statements.
Anything that appears between the description elements will appear as a script description.
Following the element is the element. There can be one or more occurrences of this element, and it is used to describe parameters that can be passed to the script.
The element contains a number of attributes, as listed in Table 2-1.
CONSTANT |
TYPE |
DESCRIPTION |
---|---|---|
Name |
String |
Argument name |
Helpstring |
String |
Argument description |
Type |
String |
Argument type: string, Boolean, or simple |
Required |
Boolean |
Indicates whether parameter is required or not |
The name attribute identifies the command-line parameter, while the helpstring attribute describes the parameter's function.
The type attribute identifies the parameter type. If the type is a string, the argument is expected to appear as /argumentname:stringvalue in the command line, where the argumentname represents the name of the argument as described with the name attribute and stringvalue is the argument value.
The following element defines the parameter user, which is a string type and is required:
In the following command-line sample, FredS is passed as the user argument:
Deluser.wsf /user:FredS
If the string argument contains spaces, surround the argument in double quotes:
Deluser.wsf /user:" Fred Smith"
If the argument is Boolean, it is toggled using /argumentname+ to indicate True, or /argumentname- to indicate a False argument value:
Deluser.wsf /Update+
Setting the type to simple indicates that no value is required for the argument.
Once all arguments have been defined, an element can be added to provide script usage samples. The element is similar to the element, where text can flow over multiple lines.
The following code snippet contains a complete sequence of argument elements that provides a script description, defines three command-line arguments, and displays example text on how to use the script:
This script is a sample script that demonstrates how to define command line arguments. This is an example of how to use this script: Argex.wsf StringArg:testing /SimpleArg BooleanArg+
Note |
No validation is performed against the arguments defined using the named and unnamed elements. No error message is returned if a "required" argument is not passed or an invalid data type is passed for an argument. Checking if an argument is passed and is the correct data type should be performed in code. The element is intended more for documentation than data validation purposes. |
The named arguments are accessed through the WScript.Arguments.Named object. Use this object's Exists method to determine if an argument has been passed. The syntax is as follows:
bExists WScript.Arguments.Named.Exists(strArgument)
strArgument is the argument you want to check. It is not case-sensitive. The function returns True if the argument has been passed and False if not:
'check if name user argument has been passed If Not WScript.Arguments.Named.Exists("User") Then WScript.Echo "You must specify a user name" WScript.Quit End If
Named arguments are accessed through the WScript.Arguments.Named object's collection:
Value =WScript.Arguments.Named(strArgument)
strArgument is the argument you want to reference and it is not case-sensitive. If the argument does not exist, an empty string is returned and no error is generated.
Tip |
Any argument prefixed with a forward slash (/) can be referenced using the Named object, regardless if it has been defined in the elements using the tags. |
Information defined in the elements makes the script self-documenting, but it can also be displayed at script execution. If a script containing the element is executed and /? is passed as a command-line parameter, the script information is displayed.
This information can be displayed by calling the WScript.Arguments.ShowUsage method from within a script. The solution script demonstrates this by executing this method if the argument count is 0.
WSH 5.6 also allows for "unnamed" arguments to be defined. An unnamed argument is an argument that does not have a corresponding named argument. In the following command line, the arguments joeb and 123456 are considered unnamed:
/name:freds joeb /flag+ /phone:5551234 123456
Any argument that does not have an associated argument name is stored in the Unnamed collection.
Unnamed arguments are useful when you have a mixture of arguments that might take an unknown number of values. To access unnamed arguments, reference the WScript.Arguments.Unnamed collection using a numeric value:
Value =WScript.Arguments.Unnamed(nArgument)
nArgument represents the argument position in the command line with a 0 offset.
Attempting to access the Unnamed collection when no unnamed arguments have been passed will generate an error. To determine if any unnamed arguments have been passed, use the WScript.Arguments.Unnamed.Count property, which returns the number of unnamed arguments in the command line.
Reading an Environment Variable
Problem
You need to be able to read an environment variable.
Solution
Use the Shell object's ExpandEnvironmentStrings method:
Dim objShell Set objShell = WScript.CreateObject("WScript.shell") WScript.Echo _ objShell.ExpandEnvironmentStrings("Your temp directory is %TEMP%")
Discussion
Environment variables are information stored by the Windows operating system. You can enumerate and create environment variables currently by executing the Set command from the command prompt. You can read their values using the Shell object's ExpandEnvironmentVariables method. The syntax is as follows:
strValue = objShell.ExpandEnvironmentStrings(strString)
Any strings in the strString argument that are enclosed between percent symbols (%) will be expanded with the corresponding environment variable value.
Whenever a new process is created, it is assigned a copy of the parent environment variables, which are known as the process environment variables. The ExpandEnvironmentStrings method looks in the process environment variable "block" when expanding the strString parameter.
Under Windows NT/2000/XP, environment variables can be system, user, or volatile. These are copied to the process environment block for each new process-when you are reading a variable using ExpandEnvironmentStrings it might be System, Volatile, or User.
Changes made to environment variables outside of the process to which they are referenced are not reflected in the process environment because it is only a copy.
Environment variables with the same name may exist in system, user, or volatile. One example is the temp environment variable, which usually exists for each user profile as well as the system.
If you read a Process environment variable that has duplicate values, such as existing in the system and user environment, it will return the User variable.
Use the Shell object's Environment collection to access variables of specific environment types. The syntax is as follows:
objCollection = objShell.Environment([strType])
The optional strType parameter can be system, user, process, or volatile. Under Windows NT/2000/XP, it defaults to system. Windows 9x/ME defaults to Process, but it can also be User or Volatile, although these operating systems don't normally use these environments.
Any changes made to the System, Volatile, or User variables outside the running script will be reflected using the Environment collection for the appropriate environment type. The following code outputs the User and System temp environment variables:
Dim objShell Set objShell = CreateObject("WScript.shell") WScript.Echo "Temp variable for user is : "& _ objShell.ExpandEnvironmentStrings(objShell.Environment("User")("Temp")) WScript.Echo "Temp variable for system is : "& _ objShell.ExpandEnvironmentStrings(objShell.Environment("System")("Temp"))
Environment variables returned from the Environment collection are not "expanded." Some environment variables are a combination of other environment variables. For example, the system Temp environment variable may be stored as %SystemRoot%TEMP. This is why in the previous example the ExpandEnvironmentStrings method is used to expand any environment variables.
Under Windows NT, you may be limited to what keys you can access. If you are logged on as a nonadministrative user account, you will not be able to access System environment variables.
'this runs on Windows NT only Dim objShell, objEnv, strEnv Set objShell = WScriptCreateObject("WScript.shell") 'get the user environment variables Set objEnv = objShell.Environment("User") For Each strEnv In objEnv WScript.Echo strEnv Next
Creating or Updating an Environment Variable
Problem
You want to create an environment variable.
Solution
Use the WScript.Shell object's Environment collection to create a new environment variable in this way:
Dim objShell, objEnv Set objShell = WScript.CreateObject("WScript.shell") 'get the User environment variables Set objEnv = objShell.Environment("User") objEnv("username") = "Fred Smith"
Discussion
The Environment collection that is described in Problem 2.3 can be used to update or create environment variables. The example script sets the value for the environment variable user name for the User environment.
This method works fine for Windows NT/2000/XP. You can update the Process, User, or Volatile environments. You can also update the system environment if you have the appropriate security access. If you want the changes to take effect globally, apply the changes to the appropriate environment type. Any changes made to the process environment block are lost when the script exits.
If you are using Windows 9x or ME, it's not so straightforward.
If you set the environment variable using this method under Windows 9x/ME, the variable will be set under the process environment block and exist during the execution of the script, but once the script terminates the environment variable will disappear.
There are a couple of ways to get past this problem. Under Windows 9x/ME, you can set an environment variable User or Volatile, even though the WSH documentation specifies that this works under Windows NT/2000/XP only:
'this works under Windows 9x Dim objShell, objEnv Set objShell = WScript.CreateObject("WScript.shell") 'get the User environment variables Set objEnv = objShell.Environment("User") objEnv("username") = "Fred Smith"
The problem with this is that it is not available to the Windows environment. If you execute a SET statement from the command prompt, the variable will not appear. Furthermore, it will not be available to applications that read environment variables.
Using Volatile or User under Windows 9x/ME can be appropriate if you require a place to store values to be read by WSH scripts only; that is, you don't need to read the values from other applications.
The User environment variables are stored under the HKEY_CURRENT_USER Environment registry key. The Volatile variables are stored under HKEY_CURRENT_USERVolatile Environment.
If you require the variables to be visible to the Windows environment under Windows 9x/ME, you can use the Winset.exe application to set the variable. Winset.exe is available from the Windows 9x/ME CD. It is a command-line utility that sets an environment variable. The syntax is as follows:
winset.exe variable=value
Use the Shell object's Run method to execute Winset:
Set objShell = CreateObject("WScript.Shell") objShell.Run "c:winset datapath=d:data", WshHide, True
Even Winset isn't perfect, though. Winset will set the environment variable for the duration of your Windows 9x/ME session. Once you shut down or log off your Windows 9x/ME machine, you will lose any environment variables set using Winset.
The only real way to solve this problem is to manipulate the Autoexec.bat command file. Autoexec.bat is executed upon start-up of Windows 9x/ME, and any SET statements will assign an environment variable with a value.
The following script updates the global environment using Winset and updates the Autoexec.bat file with the environment variable using a SET statement. If the SET statement for the specified environment variable doesn't exist, it will add it to the file:
'UpdateEnvironment 'Description 'updates autoexec.bat file with environment variables and sets 'the environment variable 'Parameters: 'strVariablename of environment variable 'varValue value to set Sub UpdateEnvironment(strVariable, varValue) Const ForWriting = 2 Const WshHide = 0 Dim objFSO, objTextFile, strFileText, aDataFile, nF Dim bFoundSet 'open autoexec.bat Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.OpenTextFile("C:autoexec.bat") strFileText = objTextFile.ReadAll 'read the file into an array aDataFile = Split(strFileText, vbCrLf) bFoundUser = False 'search for the SET statement for the specified variable For nF = 0 To UBound(aDataFile) 'if it's found, then update line If InStr(1, aDataFile(nF), "set " & strVariable, vbTextCompare) >0 Then bFoundSet = True aDataFile(nF) = "SET " & strVariable & "=" & varValue Exit For End If Next objTextFile.Close 'open autoexec.bat for writing Set objTextFile = objFSO.OpenTextFile("C:autoexec.bat", ForWriting) strFileText = Join(aDataFile, vbCrLf) 'write back contents of file objTextFile.Write strFileText 'if set statement not found, then If Not bFoundSet Then objTextFile.WriteLine objTextFile.WriteLine "SET " & strVariable & "=" & varValue End If objTextFile.Close Set objShell = CreateObject("WScript.Shell") 'run Winset. This assumes it is in the path objShell.Run "winset " & strVariable & "=" & varValue, WshHide, True End Sub
Deleting an Environment Variable
Problem
You want to delete an environment variable.
Solution
Use the Environment collection's Remove method to delete an environment variable:
Dim objShell, objEnv Set objShell = CreateObject("WScript.shell") Set objEnv = objShell.Environment("User") objEnv.Remove "username"
Discussion
The Shell object's Environment object has a Remove method that removes environment variables. The syntax is as follows:
objEnvironment.Remove(strEnvironmentVariable)
The strEnvironmentVariable parameter represents the environment variable to remove.
Under Windows NT/2000/XP, invoking the Remove method deletes the specified environment variable. Under Windows 9x/ME it removes User and Volatile environment variables, which are stored under registry locations like NT/2000/XP but do not appear as standard Process environment variables that are accessible by MS-DOS and Windows applications.
Process environment variables, such as TEMP, PATH, and COMSPEC, are only removed from the script process. They are not removed from the global environment. To permanently remove a Windows 9x/ME environment variable, the SET statement that creates the variable must be removed from the appropriate location (autoexec.bat, config.sys, and so on). The location may vary depending on the variable.
Running Applications
Problem
You want to run an application.
Solution
You can create an instance of the WScript.Shell object and invoke the Run method. All versions of WSH support the WScript.Shell object's Run method:
'notepad.vbs Const WshNormalFocus = 1 Dim objShell Set objShell = WScript.CreateObject("WScript.shell") objShell.Run "Notepad.exe", WshNormalFocus ,True
Discussion
The Run method executes applications. These can be any Windows or command-line applications. The syntax is as follows:
objShell.Run(strCommand, [nStyle], [nWaitOnReturn])
The strCommand parameter contains the name of the application you want to execute. If the application is not found in the current directory, the directory path specified in the PATH environment variable is searched.
The nStyle parameter determines what type of window to run the program in. Table 2-2 lists the Window-style values.
CONSTANT |
VALUE |
DESCRIPTION |
---|---|---|
WshHide |
0 |
Hide window |
WshNormalFocus |
1 |
Create normal window with normal focus |
WshMinimizedFocus |
2 |
Create minimized window with focus |
WshMaximizedFocus |
3 |
Create maximized window with focus |
WshNormalNoFocus |
4 |
Create normal window with no focus |
WshMinimizedNoFocus |
6 |
Create minimized window with no focus |
If the nWaitOnReturn parameter is set to True, the script will not continue execution until the executed program has completed execution. The default is False.
The Run command does not provide the ability to return the results of the application that is being executed. You cannot add a redirection symbol (>) in the statement you are executing:
objShell.Run "dir > dir.txt",1 , True
To redirect output from a console application, you must execute the command shell and specify the command line together with any redirection. The command shell for Windows NT/2000/XP is CMD.EXE, while for Windows 9x/ME it is COMMAND.COM.
The path to the command shell is stored in the COMSPEC environment variable in all Windows operating systems. For both shells, a /C parameter specifies that you want the shell to execute a command.
The Run method automatically expands any environment variables, so you do not have to use the ExpandEnvironmentStrings method to expand the string:
Const WshHide = 0 'run an application and redirect the output to a text file Dim objShell Set objShell = CreateObject("WScript.shell") objShell.Run "%Comspec% /c tree > c: ree.txt", WshHide, True
WSH 5.6 introduces the Exec method, which functionally is the same as the Run method except that it allows full access to the standard input and output, which is the data entered and generated by the executed program. The Exec method also passes a copy of the process environment variables to the new program.
The Exec method is a WScript.Shell object method and takes one parameter, which is the command to execute. This is the same as the command parameter for the Run method. The Exec method does not support the optional windowstyle argument like the Run method.
This functionality allows the results of the executed program to be retrieved within the script. An example of this is the previous sample script that executes the MS-DOS tree command and redirects the results to the file tree.txt. Instead of redirecting to a separate file, the Exec command allows the output to be referenced directly from within the script:
'extree.vbs Set objShell = CreateObject("WScript.shell") 'execute the DOS tree command Set objRun = objShell.Exec ("%Comspec% /c tree e:") 'loop while application executes 'build output text with results of tree command strText = strText & objRun.StdOut.ReadAll 'output results WScript.Echo strText Set objShell = Nothing
The Exec method returns a WshScriptExec object. This object exposes Stdin, Stdout, and StdErr streams. Chapter 6 contains information on how to manipulate these streams.
The application executed using the Exec method runs asynchronously, which means the application the Exec method used continues running and doesn't wait for the executed application to finish.
To determine if the spawned application is still running, query the Status property. This property returns 0 if the application is still running, and it returns 1 if the application has completed running.
The Exec method provides the ability to terminate a spawned application by invoking the Terminate method, although using this method can result in the loss of data.
WSH 5.6 provides support for executing scripts on remote computers. This offers you the ability to run scripts on client computers that perform administrative tasks, such as housecleaning or system inventory.
WSH 2.0 has the ability to create remote components (see the Introduction); WSH 5.6 can execute whole command-line scripts, not just individual components on a remote machine. Like remote components, WSH uses the Distributed Component Object Model (DCOM) to execute scripts on remote machines.
Running scripts on remote computers poses a number of issues: What about security? Could a malicious script be executed on a remote computer? To limit the possibility of such activity occurring, by default remote scripts can only be run from a computer where the user is logged in as a member of the Administrators group.
Because Windows 9x and Windows ME provide limited domain user authentication capabilities in their DCOM implementation, remote scripting does not work on these platforms-it works only on Windows NT 4, Windows 2000, and Windows XP.
And to further limit any malicious activity, by default remote scripting is disabled. To enable the ability to run scripts sent from another machine, the Remote registry value (which can be found under the HKLMSOFTWAREMicrosoftWindows Script HostSettings key in the registry) must be set to 1. By default this value is 0.
To create a remote script, create an instance of an object using the ProgID WshController. This returns an instance of a WSHController object, which is used to create instances of remote scripts.
Use the WSHController object's CreateScript method to execute the remote script. This method can take two parameters.
The first parameter is the path to the script. The file executed must be a WSH script, such as a VBS, JS, or WSF file. The path points to the locally stored script. This is not the location on the remote computer, but the location on the computer that's invoking the remote script. The script is uploaded from the local computer to the remote computer for execution, which saves having to have the script stored on all clients. An error will not occur if the script is not found in the specified location.
The CreateScript method's second parameter is the name of the remote computer where the script is to be executed. This can be passed as the computer name or IP address. The computer name can be passed in UNC format-that is, prefixed with two back slashes (\).
The remote computer parameter is optional. If it is not specified, the script is executed on the local computer similar to the Run method. This is useful for testing remote scripts.
The CreateScript method does not execute the script. Rather, it attempts to connect and load a specified script on a remote computer. It returns a WshRemote object, which represents the remote instance of the script. To execute the script, invoke the remote object's Execute method.
Remotely executed scripts function similarly to scripts executed using the Exec method described earlier. The script runs asynchronously and you must query the Remote object's Status property to determine if the remote script is running.
The Status property will return 0 if no remote script is running, 1 if the script is running, and 2 when the script finishes execution on the remote computer.
The following script executes a remote script called inv.vbs on the remote computer Odin:
The script assumes the remote script executed successfully, which might not always be the case (only in a perfect world). The Remote object exposes an Error property, which returns a WshRemoteError object. This object details information on any errors that occurred in the remote script. Table 2-3 lists the WshRemoteError object properties.
PROPERTY |
DESCRIPTION |
---|---|
Description |
Short description of error |
Line |
Line error occurred on |
Character |
Column error occurred at |
SourceText |
Line of source code that caused the error |
Source |
Name of COM object that caused error (if applicable) |
Number |
Error number |
Not all properties may be set for a given WshRemoteError object when an error occurs.
To effectively trap errors, you can "sink" WshRemote object events that are fired during the execution of the remote script. When an error occurs in the remote script, an Error event is fired. In order to trap this event you must "connect" to the WshRemote object. This can be done using the WScript object's ConnectObject method, which sinks any events fired by a specific object. In order to uniquely identify the events within the script, a prefix is passed with the ConnectObject method. This prefix is added to the event name.
The WshRemote object can fire a Start and End event as well as the Error event. These events fire when the remote script starts and ends execution.
The following script demonstrates these events:
The script creates a remote script using the inv.vbs script and attempts to execute it on the remote computer Odin.
The ConnectObject method is used to synch events from the remote script object to the local script. Any events called from the remote script are identified in the local script by the event name prefixed with "rem_."
Accessing Windows Related Folders
Problem
You need to access the paths of Windows-related folders.
Solution
You can use the WScript.Shell object's SpecialFolders collection:
Set objShell = WScript.CreateObject("WScript.Shell") strDesktop = objShell.SpecialFolders("Desktop")
Discussion
The SpecialFolders collection returns the path to a specified Windows folder. The syntax is as follows:
strPath = objShell.SpecialFolders(strFolderName)
The strFolderName parameter identifies the folder to return. This parameter is not case-sensitive. Table 2-4 lists valid SpecialFolders parameters.
PARAMETER |
DESCRIPTION |
---|---|
AppData |
Location of user application data. |
Desktop |
Location of desktop folders. |
Favorites |
Internet Favorites folder. |
Fonts |
Folder where system fonts are stored. |
MyDocuments |
Default documents/personal folder. |
NetHood |
Location of Network Neighborhood folder. |
PrintHood |
Location of Printer Neighborhood folder. |
Programs |
Location of shortcuts that appear on the Programs menu under the Start menu. |
Recent |
Location of folder containing shortcuts for recently accessed resources. |
SendTo |
Send to menu folder location. |
StartMenu |
Location of shortcuts that appear on Start menu. |
Startup |
Location of start-up folder under Start menu. |
Templates |
Default template folder. |
AllUsersStartMenu |
All Users Start menu folder. Contains shortcuts that appear for all users under the Start menu. Only available under Windows NT/2000/XP. |
AllUsersDesktop |
All Users desktop folder. Contains desktop shortcuts that appear for all users. Only available under Windows NT/2000/XP. |
AllUsersPrograms |
All Users Start menu Programs folder. Contains shortcuts that appear for all users under the Start menu's Programs folder. Only available under Windows NT/2000/XP. |
AllUsersStartup |
All Users Startup folder. Shortcuts in this folder are executed upon start-up. Only available under Windows NT/2000/XP. |
If the folder name is not found, SpecialFolders will return an empty string.
Creating a Windows Shortcut
Problem
You want to create a Windows shortcut.
Solution
Use the WScript.Shell object's CreateShortcut method:
'create a shortcut on desktop linked to hello script Set objShell = CreateObject("WScript.Shell") strDesktop = objShell.SpecialFolders("Desktop") 'get the path to desktop Set objShortcut = objShell.CreateShortcut(strDesktop & "Hello World.lnk") objShortcut.TargetPath = "D:hello.vbs" 'script to execute objShortcut.Save ' save shortcut
Discussion
The WScript.Shell object can create shortcuts using the CreateShortcut method. The syntax is as follows:
objShortCut = objShell.CreateShortcut(strPath)
The strPath parameter represents the path to the shortcut. The shortcut must end in either a .lnk or .url extension. Specifying .lnk indicates you are creating a Windows shortcut, while .url will create a URL shortcut. A different Shortcut object is returned depending on the extension that you use.
The method returns a WshShortCut object.
The object provides the same settings that are available when creating shortcuts using Explorer. Table 2-5 lists the properties that can be set for the Shortcut object.
PARAMETER |
TYPE |
DESCRIPTION |
---|---|---|
Arguments |
String |
Arguments to pass the application specified in TargetPath. |
Description |
String |
Shortcut description. Doesn't work. |
Hotkey |
String |
Keyboard combination used to execute shortcut (e.g., Alt+Ctrl+F). |
IconLocation |
String |
Sets the icon based on an existing application or library. The format is the path to the application or library followed by a comma and the icon number. The icon number starts at 0. For example, objShortCut.IconLocation = "c:winnt40system32SHELL32.dll,9" would set the tenth icon of the SHELL32.dll resource DLL as the icon that would appear associated with the shortcut. |
TargetPath |
String |
Path of the application to execute or document to open. |
WindowStyle |
Integer |
Window type to display application or document. Valid values are 1 for a normal, 2 for a minimized, and 3 for a maximized window. |
WorkingDirectory |
String |
Default application working directory. |
FullName |
String |
Read-only property. The location of the shortcut. |
It can be easier to determine certain settings such as shortcut hot key key-strokes and icons by reading the properties of existing shortcuts using Windows Explorer. The following sample creates a shortcut on the desktop that points to the Autoexec.bat file:
'create a shortcut on desktop that starts Notepad with Autoexec.bat 'as parameter Dim objShell, strDesktop, objShortCut 'create a shortcut on desktop Set objShell = CreateObject("WScript.Shell") strDesktop = objShell.SpecialFolders("Desktop") 'get the path to desktop Set objShortCut = objShell.CreateShortCut(strDesktop & "Show AutoExec.lnk") objShortCut.IconLocation = "c:winntsystem32SHELL32.dll,9" objShortCut.TargetPath = "notepad.exe" 'script to execute objShortCut.Arguments = "c:autoexec.bat" 'argument to pass objShortCut.HotKey = "ALT+CTRL+N" 'hotkey to start objShortCut.Save ' save and update shortcut
Once you have set the parameters for the shortcut, invoke the Save method to save and update the shortcut.
If you call the CreateShortCut method with a path to a shortcut that already exists, the settings for the shortcut are loaded into the Shortcut object. This allows you to modify existing shortcuts without needing to reapply the existing properties.
WSH also supports the creation of URL shortcuts. These shortcuts are similar to file shortcuts except they point to an Internet URL.
Dim objShell, strDesktop, objURLShortCut 'create a URL shortcut on desktop linked to company homepage Set objShell = CreateObject("WScript.Shell") strDesktop = objShell.SpecialFolders("Desktop") 'get the path to desktop Set objURLShortCut = _ objShell.CreateShortcut(strDesktop & "Company Home Page.url") objURLShortCut.TargetPath = "www.acompany.com" objURLShortCut.Save ' save and update shortcut
The URL shortcut supports the TargetPath and FullName properties. TargetPath is the URL to point to, and FullName returns the path to the shortcut and is read-only.
Displaying a Message Prompt
Problem
You need to display a message that prompts a user to choose Yes or No, which results in an action being performed that is based on the user's choice.
Solution
You can use the following script to display a pop-up window that prompts the user to choose Yes or No:
Const YesButton = 6 Const QuestionMark = 32 Const YesNo = 4 'display a pop-up with yes/no buttons and question mark icon Set objShell = CreateObject("WScript.Shell") intValue = objShell.Popup("Do you wish to continue?", _ , , QuestionMark + YesNo) 'test if the Yes button was selected If intValue = YesButton Then 'do something End If
The result of the Solution script is shown in Figure 2-1.
Figure 2-1: Pop-up window that prompts the user to choose Yes or No
Discussion
The Popup method displays a Windows pop-up message and then returns a value depending on the button that was selected. The syntax is as follows:
intButton = objShell.Popup(strMessage, [nSecondsWait], [strTitle], [nType])
Table 2-6 details the Popup method's parameters.
PARAMETER |
DESCRIPTION |
---|---|
strMessage |
Message to display. |
nSecondsWait |
Optional parameter. If passed, the pop-up waits a specified number of seconds and then closes. |
strTitle |
Optional title for pop-up window. |
nType |
Optional numeric value that determines the number of buttons to show and icon. This is determined by combining a value from Table 2-7 and Table 2-8. For example, the value 65 would display an OK button and the Information icon. |
VALUE |
BUTTONS SHOWN |
---|---|
0 |
OK |
1 |
OK and Cancel |
2 |
Abort, Retry, and Ignore |
3 |
Yes, No, and Cancel |
4 |
Yes and No |
5 |
Retry and Cancel |
VALUE |
ICON TO SHOW |
---|---|
16 |
Stop Mark |
32 |
Question Mark |
48 |
Exclamation Mark |
64 |
Information |
Popup returns an integer value depending on what button was selected. Table 2-7 lists the button selection values.
Table 2-8 lists the icon types.
Table 2-9 lists the Popup return values.
VALUE |
DESCRIPTION |
---|---|
1 |
OK button |
2 |
Cancel button |
3 |
Abort button |
4 |
Retry button |
5 |
Ignore button |
6 |
Yes button |
7 |
No button |
Sending Keystrokes to Applications
Problem
You need to automate the process of creating text button images for Web pages. To accomplish this, you want to write a routine that enables you to drag a selection of files into a script, which results in creating text images automatically.
Solution
You can use the WScript.Shell object's SendKeys method to send keystrokes to an application. For example, the following script uses Microsoft PhotoDraw to create text buttons:
Dim objShell Dim strText, strFontSize, strFont, strFileName strFont = "Arial" strFontSize = 12 If Not Wscript.Arguments.Count = 2 Then WScript.Echo "mkbutton creates text image buttons" & vbCrLf & _ "Syntax:" & vbCrLf & _ "mkimage.vbs buttontext filename" & vbCrLf & _ "buttontext Text forcreate button" & vbCrLf & _ "filename File name for text button image" & vbCrLf & _ "Example:" & vbCrLf & _ "mkbutton Home d:dataimageshomebutton" WScript.Quit End If strText = Wscript.Arguments(0) strFileName = Wscript.Arguments(1) Set objShell = CreateObject("WScript.Shell") objShell.Run "Photodrw.exe" Wscript.Sleep 100 objShell.AppActivate "Microsoft Photodraw" Wscript.Sleep 1000 'wait for PhotoDraw to start objShell.SendKeys "{ESC}^n" 'new document Wscript.Sleep 100 objShell.SendKeys "^t" 'text mode objShell.SendKeys strText objShell.SendKeys "{tab}" objShell.SendKeys strFont objShell.SendKeys "~{tab}" objShell.SendKeys strFontSize objShell.SendKeys "{tab}" objShell.SendKeys "%oes" Format menu - Effects - Shadow objShell.SendKeys "{tab}{down 3 }{right}&" objShell.SendKeys "%oes" Format menu - Effects - Designer Text objShell.SendKeys "{tab}{down 3 }{right}" objShell.SendKeys "~" objShell.SendKeys "%vf" 'fit picture to selection objShell.SendKeys "s" objShell.SendKeys strFileName objShell.SendKeys "{tab}" objShell.SendKeys "j~~" objShell.SendKeys "%fx" 'close objShell.SendKeys "%fx" 'quit
The result of the Solution script appears in Figure 2-2.
Figure 2-2: New button
Discussion
WSH 2.0 provides a SendKeys method to send keystrokes to other applications. The SendKeys method sends keystrokes to the current active application.
To assure the correct application is set to send keystrokes to, use the AppActivate method. The syntax is as follows:
objShell.AppActivate strTitle
strTitle identifies the window that you want to activate. If more than one occurrence of the application is running, one of the occurrences is activated.
The keystrokes are sent using the SendKeys method. The syntax is as follows:
objShell.SendKeys strKeys
The strKeys parameter represents the keystrokes sent to the application. This can be any combination of characters.
objShell.SendKeys "Fred" '
Noncharacter keys, such as function keys, directional keys, and the Enter key, are represented by keystroke codes surrounded by curly braces ({}).
objShell.SendKeys "{F2}test~" '
Table 2-10 lists the keystroke codes.
KEYSTROKE |
SENDKEYS CODE |
---|---|
Backspace |
{BACKSPACE}, {BS}, or {BKSP} |
Break |
{BREAK} |
Caps Lock |
{CAPSLOCK} |
Del or Delete |
{DELETE} {DEL} |
Down/up/left/right arrows |
{DOWN} {UP} {LEFT} {RIGHT} |
Home or End |
{END} {HOME} |
Enter |
{ENTER} or ~ |
Esc |
{ESC} |
Help |
{HELP} |
Insert |
{INSERT} or {INS} |
Num Lock |
{NUMLOCK} |
Page Up and Page Down |
{PGUP} {PGDN} |
Print Screen |
{PRTSC} |
Scroll Lock |
{SCROLLLOCK} |
Tab |
{TAB} |
Function keys F1-F16 |
{F1} – {F16} |
To repeat keystrokes a set number of times, enclose the keystroke followed by the repetition count in braces.
objShell.SendKeys strKeys "{a 10}" 'press the a key 10 times objShell.SendKeys strKeys "{Down 10}" 'press the down arrow key 10 times
To perform keystroke combinations with the Ctrl, Alt, or Shift keys, prefix the keystroke with ^, %, or +.
objShell.SendKeys strKeys "%fs" 'press Alt-F then S (File - Save) objShell.SendKeys strKeys "^s" 'press Ctrl-S
If you want to press Ctrl, Shift, or Alt with a multiple combination of key-strokes, surround the keystrokes with brackets.
objShell.SendKeys strKeys "^(%f)" 'press Ctrl-Alt-F
Note that you can't use SendKeys to send keystrokes to an application that is not designed to run in Microsoft Windows. Furthermore, SendKeys can't send the Print Screen key {PRTSC} to any application.