Microsoft Steady State. How to remotely remove and retain changes on lab computers.

NOTE: April 11, 2009- This information was updated for Steady State 2.5. However, if anyone copies and pastes the VB script code from here, it may throw up errors on execution because the ‘quote’ marks get screwed up. You would have to redo ALL the quotes manually in notepad to fix it. Instead, I have packaged all the files into a Steady State Remote management KIT you can download. (Password for zip file = steveleeignacio). This KIT was tested and worked fine on XP pro. I have not tested it on Vista or Windows 7.


Microsoft Steady State 2.5 offers disk protection that can return your lab computer’s operating system to its original condition by merely rebooting the system. Steady State is similar to commercial disk protection programs like Faronics Deep Freeze.

One big problem with Steady State is that there is currently no Microsoft tool with an interface to configure the Windows Disk Protection settings centrally for multiple computers in the computer lab.

However, there are ways to change the Steady State disk protection settings remotely using a few simple VBS scripts.

We’ll use 2 scripts on our client machines and 3 scripts and a simple text file list of the lab computers on our admin machine.

These scripts will allow you to remotely “remove all changes at restart” and “retain all changes permanently” on lab computers.

Step ONE: These 2 simple VBS scripts are needed for the client machines:

Usage: copy and paste the code for each one to notepad. Name the the first one retain.vbs. Name the second one remove.vbs. Create a folder in the root of C:\ called VBscripts on the clients. Should look like this: C:\VBscripts. Put retain.vbs and remove.vbs inside that folder.

VBscripts folder on client machines

RETAIN changes:

‘ *** ——————————————————————————
‘ *** Version: 1.0
‘ *** Author: Daniel Reis
‘ *** Email: daniel@fe.up.pt
‘ *** ——————————————————————————
‘ *** Date: 12/06/2008
‘ *** ——————————————————————————

dim objNet
On Error Resume Next

‘ Identify the computer to manage
Const strComputer= “.”

Const WDP_MODE_COMMIT = 2

Const SUCCESS = 0
Const FAILURE = 1

set objWbemServices = GetObject (”winmgmts:\\” & strComputer & “\root\wmi”)
set setWdpObjects = objWbemServices.ExecQuery (”SELECT * FROM WDP_Control”)

For Each objWdp In setWdpObjects
objWdp.CurrentMode = WDP_MODE_COMMIT
objWdp.Put_
Next

If Err.Number <> 0 Then
Wscript.echo “FAILURE”
Return FAILURE
Else
Wscript.echo “SUCCESS”
Return SUCCESS
End If

REMOVE changes:

‘ *** ——————————————————————————
‘ *** Version: 1.0
‘ *** Author: Daniel Reis
‘ *** Email: daniel@fe.up.pt
‘ *** ——————————————————————————
‘ *** Date: 12/06/2008
‘ *** ——————————————————————————

dim objNet
On Error Resume Next

‘ Identify the computer to manage
Const strComputer= “.”

Const WDP_MODE_DISCARD = 0

Const SUCCESS = 0
Const FAILURE = 1

set objWbemServices = GetObject (”winmgmts:\\” & strComputer & “\root\wmi”)
set setWdpObjects = objWbemServices.ExecQuery (”SELECT * FROM WDP_Control”)

For Each objWdp In setWdpObjects
objWdp.CurrentMode = WDP_MODE_DISCARD
objWdp.Put_
Next

If Err.Number <> 0 Then
Wscript.echo “FAILURE”
Return FAILURE
Else
Wscript.echo “SUCCESS”
Return SUCCESS
End If

At this point you can test to see if the scripts work. With Steady State installed and disk protection set to “ON”, click the scripts and test the results for SUCCESS or FAILURE.


Step TWO: This 1 script and 1 text file are needed on the administrator’s machine at C:\VBscripts.

Usage: copy and paste the code for each one to notepad. Name the first one RunProgram.vbs. Name the second one computers.txt. Create a folder in the root of C:\ called VBscripts on the administrator’s computer. Should look like this: C:\VBscripts. Put RunProgram.vbs and computers.txt inside that folder.

Admin computer files for Steady State

RunProgram.vbs

‘ RunProgram.vbs - Written by Bill Stewart (bill.stewart@frenchmortuary.com)

‘ Uses WMI to run a program on the local or a remote computer. It can also wait
‘ for the program to finish and optionally display an elapsed time. For
‘ security reasons, running a program on a remote computer always executes in a
‘ hidden window on Windows 2000 SP3 and later.

‘ Limitations:

‘ * A program started on a remote computer will not have network access.
‘ * The /wait option imposes some amount of processor overhead because it
‘ repeatedly executes a WMI query to determine if the process exists.
‘ * Embedding double quotes in the command line is awkward because the WSH
‘ runtime doesn’t provide an escape mechanism (like \” to represent “, etc.)
‘ As a workaround, the script uses VBScript’s Unescape() function, so you
‘ can type %22 (hex 22 = dec 34 = ” character). Naturally, this won’t work
‘ if the command line actually contains %xx sequences, but this should be
‘ pretty rare.

‘ Version history:
‘ * 1.0: Initial version.

Option Explicit

Const SCRIPT_NAME = “RunProgram.vbs”

‘ This constant defines the number of mulliseconds
‘ to wait between each WMI query when using /wait
Const PROCESS_CHECK_INTERVAL = 500

Main

‘ Displays the script’s usage message
Sub ShowUsage()
WScript.Echo “Runs a program on the local or a remote computer.” & vbNewLine _
& vbNewLine _
& “Usage: ” & SCRIPT_NAME & ” “”“” [/startin: ] [/window:]” & vbNewLine _
& ” [/computer: [/username:] [/password: ]]” & vbNewLine _
& ” [/wait [/elapsed]]” & vbNewLine _
& vbNewLine _
& “: The command line to run (must start with an executable).” & vbNewLine _
& “/startin: Sets the starting directory for the program.” & vbNewLine _
& “/window: Number that sets the program’s initial window state. (Note: for” & vbNewLine _
& ” security reasons, a program run on a remote computer always starts in a” & vbNewLine _
& ” hidden window on Windows 2000 SP3 and later.)” & vbNewLine _
& “/computer: The computer on which to run the program.” & vbNewLine _
& “/username: Connects with the specified username (requires /computer).” & vbNewLine _
& “/password: Use the specified password (requires /computer).” & vbNewLine _
& “/wait: Waits for the program to end.” & vbNewLine _
& “/elapsed: Displays the program’s elapsed time (requires /wait).” & vbNewLine _
& vbNewLine _
& “Enclose the command line in double-quotes (”"). To embed double quotes in the” & vbNewLine _
& “command line, use the string “”%22″”.” & vbNewLine _
& vbNewLine _
& “Example: ” & SCRIPT_NAME & ” “”cmd /c dir %22C:\Program Files%22 > C:\List.txt”"”

WScript.Quit 0
End Sub

‘ Returns the script host (cscript.exe or wscript.exe) in lowercase
Function ScriptHost()
ScriptHost = LCase(Mid(WScript.FullName, Len(WScript.Path) + 2))
End Function

‘ Displays the elapsed time in hour(s), minute(s), and second(s) based
‘ on the Secs parameter
Function GetElapsed(ByVal Secs)
Dim Result, Hrs, Mins

Result = “”

Hrs = Secs \ 3600
If Hrs > 0 Then
Result = CStr(Hrs) & ” hour(s), “
Secs = Secs - (3600 * Hrs)
End If

Mins = Secs \ 60
If Mins > 0 Then
Result = Result & CStr(Mins) & ” minute(s), “
Secs = Secs - (60 * Mins)
End If

GetElapsed = Result & CStr(Secs) & ” second(s)”
End Function

‘ Main subroutine
Sub Main()
Dim Args
Dim Command, StartIn, Computer, UserName, Password
Dim Wait, Elapsed
Dim ShowWindow, Result
Dim StartTime, EndTime
Dim Output, TimeInfo
Dim WMIRun

Set Args = WScript.Arguments

‘ If there are no unnamed arguments, or if the /? argument
‘ is present, show the usage message
If (Args.Unnamed.Count = 0) Or Args.Named.Exists(”?”) Then _
ShowUsage

‘ CALLOUT A
Command = Unescape(Args.Unnamed(0))
‘ END CALLOUT A

StartIn = Args.Named(”startin”)

ShowWindow = Args.Named(”window”)
If Not IsNumeric(ShowWindow) Then ShowUsage
If (ShowWindow < 0) Or (ShowWindow > 65535) Then ShowUsage

Computer = Args.Named(”computer”)
UserName = Args.Named(”username”)
Password = Args.Named(”password”)

Wait = Args.Named.Exists(”wait”)
Elapsed = Args.Named.Exists(”elapsed”)

‘ Create instance of class
‘ CALLOUT B
Set WMIRun = New WMIExec
‘ END CALLOUT B

Result = WMIRun.ConnectServer(Computer, UserName, Password)
If Result <> 0 Then
‘WScript.Echo “Error 0x” & Hex(Result) & ” connecting to ‘” _
‘& Computer & “‘”
WScript.Quit Result
End If

If Elapsed Then StartTime = Now()

Result = WMIRun.RunProgram(Command, StartIn, ShowWindow)
If Result <> 0 Then
‘WScript.Echo “Error 0x” & Hex(Result) & ” starting ‘” _
‘& Command & “‘”
WScript.Quit Result
End If

‘ Output initial status message
‘WScript.Echo WMIRun.Status

If Wait Then
‘ Suspend script while process is running
Do While WMIRun.ProcessExists()
WScript.Sleep PROCESS_CHECK_INTERVAL
Loop
If Elapsed Then
EndTime = Now()
TimeInfo = “Started: ” & CStr(StartTime) & vbNewLine _
& “Ended: ” & CStr(EndTime) & vbNewLine _
& “Elapsed: ” & GetElapsed(DateDiff(”s”, StartTime, EndTime))
‘ Output full status if running from wscript.exe
If ScriptHost() = “wscript.exe” Then
Output = WMIRun.Status & vbNewLine & TimeInfo
Else
Output = TimeInfo
End If
‘WScript.Echo Output
End If
End If
End Sub

‘ WMIExec class definition
Class WMIExec
‘ The c_ prefix denotes variables global to the class
Private c_SWbemServices
Private c_Server, c_Command, c_StartIn
Private c_ProcID

‘ Connects to the specified computer; returns 0 for success
Public Function ConnectServer(ByVal Server, ByVal User, _
ByVal Password)
Dim SWbemLocator

‘ Update the class variable
c_Server = Server

‘ Assume the local computer if not specified
If c_Server = “” Then c_Server = “.”

‘ Ignore user and password if connecting
‘ to the local computer
If c_Server = “.” Then
User = “”
Password = “”
End If

Set SWbemLocator = CreateObject(”WbemScripting.SWbemLocator”)
SWbemLocator.Security_.ImpersonationLevel = 3 ‘ impersonate

On Error Resume Next
Set c_SWbemServices = SWbemLocator.ConnectServer(c_Server, _
“root/cimv2″, User, Password)

ConnectServer = Err.Number
End Function

‘ Run the specified command line, starting in the specified
‘ directory, with the specified initial window state; returns
‘ 0 for success
Public Function RunProgram(ByVal Command, ByVal StartIn, _
ByVal ShowWindow)
Dim Startup, Process

‘ Update the class variables
c_Command = Command
c_StartIn = StartIn

‘ Create a Win32_ProcessStartup object and configure
‘ its ShowWindow property
Set Startup = _
c_SWbemServices.Get(”Win32_ProcessStartup”).SpawnInstance_()
Startup.ShowWindow = ShowWindow

Set Process = c_SWbemServices.Get(”Win32_Process”)
RunProgram = Process.Create(c_Command, c_StartIn, Startup, c_ProcID)
End Function

‘ Returns True if the process exists
Public Function ProcessExists()
ProcessExists = c_SWbemServices.ExecQuery(”SELECT ProcessID FROM ” _
& “Win32_Process WHERE ProcessID=” & c_ProcID).Count > 0
End Function

‘ Returns a status message using the class variables
Public Function Status()
Dim Server, StartIn

If c_Server = “.” Then Server = “(LocalSystem)”
If c_StartIn = “” Then StartIn = “(Default)” Else StartIn = c_StartIn

Status = “Computer: ” & Server & vbNewLine _
& “Command line: ” & c_Command & vbNewLine _
& “Starting directory: ” & StartIn & vbNewLine _
& “Process ID: ” & CStr(c_ProcID)
End Function
End Class

computers.txt

computer-lab-01
computer-lab-02
computer-lab-03
computer-lab-04
computer-lab-05
computer-lab-06
computer-lab-07
and so on…………..put your own computer names in this file

Step THREE: These 2 scripts are needed on the administrator’s machine on the desktop.


Usage: copy and paste the code for each one to notepad. Name the first one remove_all_changes_at_restart.vbs. Name the second one retain_all_changes_permanently.vbs. Create a folder called Steady State Management on the desktop. Put remove_all_changes_at_restart.vbs and retain_all_changes_permanently.vbs in that folder.

Don’t forget to enter your own username and password details in the scripts.

Steady State remote management scripts

Remove all changes at restart

‘ Remove all changes at restart for Steady State modified by MAI 9/2/2007

‘ This script will set Public machines running Microsoft Steady State to Remove all changes at restart.
‘ This script requires RunProgram.vbs to execute remote commands on systems



‘ Variables to modify (all others shouldnt be modified):
‘ INPUT_FILE_PATH = Path to text file that has system names
‘ INPUT_FILE_NAME = Name of text file with system names
‘ USERNAME = local username needed for remote system
‘ PASSWORD = password needed for remote system
‘ PATH_TO_RUNPROGRAM = Path to the RunProgram.vbs script

INPUT_FILE_PATH = “c:\VBScripts\”
INPUT_FILE_NAME = “computers.txt”
PATH_TO_RUNPROGRAM = “c:\VBScripts\RunProgram.vbs”
USERNAME = “username”
PASSWORD = “password”

‘ Set various variables for use within the script. Should not need to be modified.
INPUT_DATA = INPUT_FILE_PATH + INPUT_FILE_NAME
Const FOR_READING = 1
Dim WshShell, strCommand, objFSO, systems
Set objFSO = CreateObject(”Scripting.FileSystemObject”)
Set WshShell = WScript.CreateObject(”WScript.Shell”)
‘This section reads the systems text file and stores into strComputers.
‘It then splits the carriage return from the system name
Set objFile = objFSO.OpenTextFile(INPUT_DATA, FOR_READING)
strComputers = objFile.ReadAll
objFile.Close
arrComputers = Split(strComputers, vbCrLf)

‘Loop through names in systems text file
For Each strComputer In arrComputers

‘ Setup command to execute on remote system and then execute
strCommand = PATH_TO_RUNPROGRAM & ” ” & chr(34) & “cscript.exe %22c:\VBScripts\remove.vbs%22″ & chr(34) & ” /username:local\” & USERNAME & ” /password:” & PASSWORD & ” /computer:” & strComputer

wshShell.Run strCommand, 0

Next

Retain all changes permanently

‘ Retain all changes permanently for Steady State by MAI 9/02/2007

‘ This script will set Public machines running Microsoft Steady State to Retain all changes permanently.
‘ This script requires RunProgram.vbs to execute remote commands on systems



‘ Variables to modify (all others shouldnt be modified):
‘ INPUT_FILE_PATH = Path to text file that has system names
‘ INPUT_FILE_NAME = Name of text file with system names
‘ USERNAME = local username needed for remote system
‘ PASSWORD = password needed for remote system
‘ PATH_TO_RUNPROGRAM = Path to the RunProgram.vbs script

INPUT_FILE_PATH = “c:\VBScripts\”
INPUT_FILE_NAME = “computers.txt”
PATH_TO_RUNPROGRAM = “c:\VBScripts\RunProgram.vbs”
USERNAME = “username”
PASSWORD = “password”

‘ Set various variables for use within the script. Should not need to be modified.
INPUT_DATA = INPUT_FILE_PATH + INPUT_FILE_NAME
Const FOR_READING = 1
Dim WshShell, strCommand, objFSO, systems
Set objFSO = CreateObject(”Scripting.FileSystemObject”)
Set WshShell = WScript.CreateObject(”WScript.Shell”)
‘This section reads the systems text file and stores into strComputers.
‘It then splits the carriage return from the system name
Set objFile = objFSO.OpenTextFile(INPUT_DATA, FOR_READING)
strComputers = objFile.ReadAll
objFile.Close
arrComputers = Split(strComputers, vbCrLf)

‘Loop through names in systems text file
For Each strComputer In arrComputers

‘ Setup command to execute on remote system and then execute
strCommand = PATH_TO_RUNPROGRAM & ” ” & chr(34) & “cscript.exe %22c:\VBScripts\retain.vbs%22″ & chr(34) & ” /username:local\” & USERNAME & ” /password:” & PASSWORD & ” /computer:” & strComputer

wshShell.Run strCommand, 0

Next

Usage of scripts to configure Steady State remotely on lab computers

Make sure Steady State disk protection is installed “On” on the client machines. Double click the scripts on the admin desktop to make changes to the Steady State disk protection on the clients.

Steady State is ON

DONE!

Steady State Remote management KIT (Password for zip file = steveleeignacio)