Making a major change—such as installing a new program or changing the registry—on your Windows XP Professional Edition client systems always involves an element of risk. Fortunately, XP Pro includes the System Restore feature, which lets you return the OS to an earlier state (called a restore point or system checkpoint). Furthermore, System Restore lets you maintain changes that have taken place or personal files that have been created since the restore point, and any restore that you perform through System Restore is completely reversible.
XP Pro automatically creates a restore point every 24 hours, and many installation processes request the creation of restore points immediately before and after application installations. You can also create restore points at any time by using the System Restore wizard or a Windows Management Instrumentation (WMI) script. Let's examine the WMI features that support System Restore and a script that creates and manages restore points from the command line.
System Restore 101
When a restore point is created, System Restore takes a full snapshot of the registry and certain dynamic system files to archive the current state of a core set of system and application files. System Restore compresses the registry and makes any necessary file copies when it detects that the XP system isn't in use. The list of files that System Restore monitors and excludes is stored in a hidden XML file called filelist.xml (in the %windir%\system32\restore folder).
To function properly, System Restore requires a minimum of 200MB of free disk space on the system drive. If the free disk space falls below 50MB on any drive, System Restore switches to standby mode and stops creating restore points. When you recover at least 200MB of free disk space, System Restore resumes. For more details about the underlying System Restore architecture, read the Microsoft article "Windows System Restore" (http://msdn.microsoft.com/library/en-us/dnsetup/html/winmesr.asp).
The System Restore WMI Provider
You can use the System Restore wizard, which you access through Start, All Programs, Accessories, System Tools, to create or restore system checkpoints on the local system. You can also script these processes by exploiting the System Restore WMI provider. This provider resides in the Common Information Model (CIM) repository under the root\default namespace and supports two WMI classes: the SystemRestore class and the SystemRestoreConfig class. The SystemRestore class exposes five methods that implement the typical System Restore operations (i.e., creating restore points, disabling and enabling System Restore, retrieving the status of the most recent restore, and restoring a system). The SystemRestoreConfig class provides properties for controlling the frequency of restore-point creation and the amount of disk space that each disk dedicates to System Restore. (See "System Restore WMI Classes" at http://msdn.microsoft.com/library/en-us/sr/sr/system_restore_wmi_classes.asp for more information about the classes and the methods and properties that they expose.)
Scripting System Restore
To illustrate how to work with the SystemRestore and SystemRestoreConfig classes, I'll walk you through a script I wrote that executes most of the features that come with the WMI System Restore provider. This script, written in JScript and called WMISystemRestore.wsf, exposes a set of command-line parameters that correspond to the methods and properties exposed by the provider's classes. When you launch the script from the command line, you use the /Action switch in combination with a mandatory keyword to tell the script which action you want to perform. The supported keywords are List, Disable, Enable, CreateRestorePoint, LastRestoreStatus, and Update. Before digging into the code, I'll explain the various command-line parameters you can use to execute the script.
The simplest operation uses the List keyword to view existing restore points:
Web Figure 1 shows sample output from this command. The output displays three restore points and five properties for each restore point.
The first two properties, CreationTime and Description, are self-explanatory. The EventType property, which System Restore records as an integer, defines the type of event that prompted the creation of the restore point and can help you determine, for example, whether the restore point corresponds to the system's state before or after a change took place. (Web Table 1 lists the possible values for this property.) The RestorePointType property, which System Restore also records as an integer, defines the restore point's type, letting you determine, for example, whether the restore point corresponds to an application installation, a system modification, or a device-driver installation. (Web Table 2 describes the possible values.) The SequenceNumber property is an integer that defines the restore point's sequence number in the index of all existing restore points.
Use the Disable or Enable keyword to disable or enable System Restore. To perform these operations on a specific volume, you must specify a drive letter. For example, to disable System Restore on volume D, use the command
WMISystemRestore.wsf /Action: Disable /Volume:D:\
To disable or enable System Restore on all disks, replace the drive letter with the wildcard (*) character.
To create a restore point, use the CreateRestorePoint keyword, followed by the /Description switch combined with a descriptive name for the restore point (enclosed within quotation marks):
WMISystemRestore.wsf /Action: CreateRestorePoint /Description: "My System Restore"
The name you provide will be displayed in the restore point's Description property.
To request the status of the most recent restore operation, use the LastRestoreStatus keyword. The script doesn't require any parameters in combination with this keyword:
WMISystemRestore.wsf /Action: LastRestoreStatus
To restore a system checkpoint, use the Restore keyword, followed by the /RestoreSequence switch and the sequence number of the checkpoint you want to restore. You can locate the correct sequence number by using the List keyword to list all restore points, then examining each restore point's SequenceNumber property. For example, to restore system checkpoint 28, use the command
WMISystemRestore.wsf /Action: Restore /RestoreSequence:28
To change the System Restore property that defines the percentage of disk space dedicated to System Restore information, use the Update keyword, followed by the /DiskPercentage switch and a value that represents the percentage of disk space you want to dedicate. For example, to dedicate 12 percent total disk space, use the command
WMISystemRestore.wsf /Action: Update /DiskPercentage:12
To modify the schedule for creating restore points, use the Update keyword, followed by a series of switches—the /GlobalInterval switch, the /LifeInterval switch, and the /SessionInterval switch—each of which is combined with a value that specifies a time interval. The /GlobalInterval switch corresponds to the SystemRestoreConfig class's RPGlobalInterval property and determines the absolute time interval (in seconds) at which System Restore will create scheduled system checkpoints. The default value is 86,400 seconds (i.e., 24 hours). The /LifeInterval switch corresponds to the SystemRestoreConfig class's RPLifeInterval property and defines the length of time (in seconds) for which System Restore will preserve restore points. When a restore point becomes older than the specified interval, System Restore deletes the restore point. The default value is 7,776,000 seconds (i.e., 90 days). The /SessionInterval switch corresponds to the SystemRestoreConfig class's RPSessionInterval property and determines the time interval (in seconds) at which System Restore creates scheduled system checkpoints during an interactive session. The default value is 0, meaning that no checkpoints are created during interactive sessions. Note that although the SystemRestoreConfig class exposes these properties in seconds, the script accepts the scheduling parameters in hours, as the following command shows:
WMISystemRestore.wsf /Action: Update /GlobalInterval:72 /LifeInterval:120 /SessionInterval:120
Now that you understand the various command-line parameters and the methods or properties that they relate to, let's look at the script. To download the full version of WMISystemRestore.wsf and its related subfunctions, go to http://www.winnet mag.com/windowsscripting, enter 42738 in the InstantDoc ID text box, then click the 42738.zip hotlink. (You must have Administrative privileges to execute the script.) For purposes of explaining the code, I'll highlight code excerpts that carry out the script's primary purposes.
Exploiting System Restore
The script begins by defining command-line parameters, then prepares to exploit System Restore. The code in Listing 1 shows the latter process.
First, the code at callout A in Listing 1 includes several external helper functions. DecodeSystemRestoreFunction.vbs contains two functions—DecodeRestorePointType() and DecodeEventType()—to decipher the RestorePointType and EventType properties, respectively. DisplayFormattedPropertyFunction.vbs contains the DisplayFormattedProperty() function, which the script uses to display class properties and their values. TinyErrorHandler.vbs contains the ErrorHandler() function, which the script uses to handle execution errors.
Next, the code at callout B in Listing 1 creates two objects: the SWbemLocator object, which the script uses to perform the WMI connection, and the SWbemDateTime object, which the DisplayFormattedProperty() function uses to manipulate WMI date and time properties. The code at callout C defines two constants: cComputerName, which defines the name of the computer to which to connect, and cWMINameSpace, which defines the WMI CIM repository namespace (i.e., root\default) to which to connect. The code goes on to perform command-line parsing by using the Windows Script Host (WSH) 5.6 XML command-line parsing feature. (See "Secure Script Execution with WSH 5.6," August 2002, InstantDoc ID 25644, for information about this feature.) The code at callout D then establishes the WMI connection.
Viewing Restore Points
The code in Listing 2 displays existing restore points. The code at callout A in Listing 2 retrieves all instances of the SystemRestore class, then the code at callout B enumerates all retrieved SystemRestore instances and their properties. The script calls the DecodeRestorePointType() or DecodeEventType() function to decipher EventType and RestorePointType property values and, with the help of the previously created SWbemDateTime object, converts the CreationTime property's Distributed Management Task Force (DMTF) date and time string to a readable property.
Enabling and Disabling Disk Monitoring
The script uses a simple technique to enable or disable System Restore disk monitoring. The code in Listing 3 uses the Enable method to enable monitoring; the Disable method follows the same technique to disable monitoring. First, the code at callout A in Listing 3 retrieves a SystemRestore class instance. The Enable and Disable methods don't relate to a particular restore point instance but rather have a global effect on the System Restore subsystem. Therefore, the script retrieves an instance of the Restore class instead of retrieving an instance of a specific restore point.
As I explained earlier, you can invoke the Enable or Disable method against a specific disk or against all disks. When the script invokes the methods against all disks, the code at callout B in Listing 3 passes an empty string to the Enable method. The Enable method also accepts a second parameter in the form of a Boolean value to determine whether the method execution must wait until System Restore is fully enabled for the specified disk or disks before returning to the script execution. In the sample script, I've set this parameter to true.
Creating a Restore Point
The code in Listing 4 creates a restore point by invoking the CreateRestorePoint method, similar to the way in which the script invokes the Enable method. The code first retrieves an instance of the SystemRestore class. Then, the code at callout A in Listing 4 invokes the CreateRestorePoint method, which requires three parameters. The first parameter is a description of the restore point, which the script reads from the /Description switch, as I explained earlier. The second parameter corresponds to the RestorePointType property and must be one of the values listed in Web Table 2. The third parameter corresponds to the EventType property and must be one of the values listed in Web Table 1.
To keep the script short and simple, I hard-coded the RestorePointType property's APPLICATION_INSTALL value and the EventType property's BEGIN_SYSTEM_CHANGE value into the code to have the script create a restore point at the beginning of a new application installation. Usually, software-installation programs such as Windows Installer or InstallShield Software's InstallShield automatically create restore points before and after executing an installation. In such a case, you don't need to create your own restore point before you install an application.
When you run scripts that execute system changes or perform changes to the registry, however, you can use WMISystemRestore.wsf in conjunction with the /Action:CreateRestorePoint switch to manually create a preinstallation restore point. After completing an installation, you should edit the script to specify the END_SYSTEM_CHANGE value for the EventType property, which will create a postinstallation restore point. If you decide to cancel the system changes and want to remove that restore point, edit the script to specify the CANCELLED_OPERATION and END_SYSTEM_CHANGE values for the RestorePointType and EventType properties, respectively, to create a new restore point. (The RestorePointType and EventType labels are defined as constants in the DecodeSystemRestoreFunction.vbs file.)
Retrieving Restore Status
Getting the status of the most recent restore is a simple operation. The code in Listing 5 executes the GetLastRestoreStatus method, which is global to the System Restore subsystem, from an instance of the SystemRestore class (similar to the execution of the Enable and CreateRestorePoint methods). The method returns a value of 0, 1, or 2. A value of 0 means that the most recent restore operation was a failure, a value of 1 means that the restore was successful, and a value of 2 means that the restore was interrupted.
Restoring a System Checkpoint
Listing 6 shows the code to restore a system checkpoint. This operation is no more complicated than retrieving restore status. The Restore method must be executed from an instance of the SystemRestore class, and the only required input parameter is the restore- point sequence number, which you can determine by executing WMISystemRestore.wsf in conjunction with the /Action:List command-line parameter.
The code in Listing 7 lets you manage the properties that control the frequency of scheduled restore-point creations and the amount of disk space that System Restore consumes on each disk. To do this, the code at callout A in Listing 7 must retrieve an instance of the SystemRestoreConfig class. Only one instance of this class—the SR instance—exists. In the code at callout B, that instance exposes the disk percentage stored in the DiskPercent property and the three frequency properties stored in the RPGlobalInterval, RPLifeInterval, and RPSessionInterval properties. As I mentioned earlier, the script accepts the scheduling parameters in hours. Because the SystemRestoreConfig class exposes the corresponding properties in seconds, the script multiplies the values by 3600 during the property assignment. Because you can update one or several properties from the command line, the script tests which property has an assigned value. If the value differs from -1 (which is the default value when no new value assignment has been made from the command line), the script must update the property. The code at callout C saves the updated property or properties back to the CIM repository by invoking the Put_ method of the SWbemObject that represents the SystemRestoreConfig class instance.
Relax and Restore
Although many installation programs automatically create restore points before proceeding with an installation, the need to manually create a restore point does arise from time to time, such as when you must perform scripted system changes simultaneously on many XP Pro systems. In such situations, customized scripts can speed up and ease the process, but performing large-scale changes without first making a copy of each computer's system settings can be risky. To minimize the risk, you can script the creation of restore points as the first action of your custom script. Doing so guarantees a recovery path for your XP Pro systems in case you experience problems and is a great way to keep managed systems operational.