Microsoft Windows Registry Guide, Second Edition
Adding Multiple Settings with One Script
Rather than listing each REG or script file in the [GuiRunOnce] section, I prefer to put one command in the section that runs all of the REG and script files in a single folder. That way, I can update my distribution point by simply adding the appropriate file to the folder; I don't have to add a command to the answer file that runs the file.
Listing 14-3 shows the script runinst.vbs, which I use to run files (REG, INF, and MSI files, for example) in a given folder. The script accepts a single command-line option: the folder containing the files that you want to run. This script launches all of the files that the folder contains, and it can launch different types of files, including files with the extensions EXE, MSI, BAT, JS, VBS, REG, and INF. If Windows Installer is already running, then it waits to launch a Windows Installer setup database because you can only install one setup database at a time. These files run the gamut from setup programs and Windows Installer databases to scripts and registry settings deployed via files with the REG extension.
Listing 14-3 runinst.vbs
' runinst.vbs: run commands in the given folder ' ' USAGE ' ' runinst.vbs FOLDER ' ' FOLDER Path of folder containing installations to run ' ' NOTES ' ' This script supports files with the extensions EXE, ' MSI, BAT, CMD, JS, VBS, REG, and INF. ' ' If the folder doesn't exist, this script displays an error ' message that times out in 10 seconds, since it's for use during ' the Windows setup process and the folder doesn't always exist. ' Option Explicit Main() Sub Main() ' Check the command-line argument (which must be the path of ' a folder that contains installations to run); then, call ' LaunchInstallations to silently run each installation contained ' in the folder. ' Dim intRC Dim objArguments Dim objFileSystem Dim objShell Set objArguments = WScript.Arguments Set objFilesystem = CreateObject( "Scripting.FileSystemObject" ) Set objShell = CreateObject( "WScript.Shell" ) If objArguments.Count > 0 Then If objFileSystem.FolderExists( objArguments(0) ) Then LaunchInstallations( objArguments(0) ) Else ' The folder doesn't exist intRC = objShell.Popup( "The folder " & objArguments(0) & _ " doesn't exist.", 10, "Folder Missing", 0 ) End If Else ' No folder was given on the command line WScript.Echo "Usage: runinst.vbs FOLDER" End If End Sub Sub LaunchInstallations( strPath ) ' Execute each installation file contained in strPath silently: ' ' strPath Path of the folder containing installations ' Dim objFileSystem Dim objShell Set objFilesystem = CreateObject( "Scripting.FileSystemObject" ) Set objShell = CreateObject( "WScript.Shell" ) ' Build a list of files in the given subfolder Dim intRC Dim objFolder Dim colFiles Dim objFile Set objFolder = objFileSystem.GetFolder( strPath ) Set colFiles = objFolder.Files ' Launch each file in the list using the appropriate command For Each objFile in colFiles Select Case UCase( objFileSystem.GetExtensionName( objFile )) Case "EXE" intRC = objShell.Run( objFile, 1, True ) case "MSI" Dim objWMIService Dim strProcessName ' Wait for any current MSI processes to finish strProcessName = "msiexec.exe" Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Do While objWMIService.ExecQuery( "Select Name from _ Win32_Process where Name='" & strProcessName & "'").Count > 1 WScript.Sleep 5000 Loop intRC = objShell.Run( "msiexec.exe /qb /i " & _ objFile & " ALLUSERS=2", 1, True ) Case "BAT" intRC = objShell.Run( "cmd.exe /c " & objFile, 1, True ) Case "CMD" intRC = objShell.Run( "cmd.exe /c " & objFile, 1, True ) Case "JS" intRC = objShell.Run( "wscript.exe //e:jscript " & _ objFile, 1, True ) Case "VBS" intRC = objShell.Run( "wscript.exe //e:vbscript " & objFile, 1, True ) Case "REG" intRC = objShell.Run( "regedit.exe /s " & objFile, 1, True ) Case "INF" intRC = objShell.Run( _ "rundll32.exe setupapi,InstallHinfSection DefaultInstall 132 " _ & objFile, 1, True ) End Select Next End Sub
This script prevents you from having to edit Cmdlines.txt or the [GuiRunOnce] section of your unattended-setup answer file just to add a setting to the target computer's registry or install a Windows Installer database. Run this script from Cmdlines.txt or from [GuiRunOnce], and you'll never again have to change either just to run a batch script or install a program. Instead, you'll just drop the file into the appropriate folder, and the script will automatically run the file at the appropriate point in the installation process. For example, I can drop the files settings.reg and config.vbs into the folder, and without changing any other files, runinst.vbs automatically loads settings.reg into the registry and uses Windows Script Host to run config.vbs.
In the distribution point, I put this script into $OEM$\$$\APPS so that it's easy to access from unattended-setup answer files. (You must create the folder APPS in $OEM$\$$.) The path on the target computer is %SystemRoot%\APPS\runinst.vbs. Then I create a subfolder called GUI for the files that will run from [GuiRunOnce] and a subfolder called CMD for the files that will run from Cmdlines.txt. The following list describes each in more detail:
- Cmdlines.txt in the $OEM$ directory.
Add the following line to Cmdlines.txt. Then create the folder $OEM$\$$\APPS\CMD in your distribution point, and copy to it each file that you want runinst.vbs to launch during installation.
[Commands] "wscript.exe //e:vbscript \WINDOWS\APPS\runinst.vbs \WINDOWS\APPS\CMD"
- [GuiRunOnce] in the unattended-setup answer file.
Add the following line to the [GuiRunOnce] section of your unattended-setup answer file. Then create the folder $OEM$\$$\APPS\GUI in your distribution point, and copy to it each file that you want runinst.vbs to launch after installation is complete:
[GuiRunOnce] "%SYSTEMROOT%\APPS\runinst.vbs %SYSTEMROOT%\APPS\GUI"