DPM 2010 System State Failures

A bunch of my DPM SystemState backups were failing. The volumes would backup correctly, but system state wouldn’t. I sicked one of my junior admins on this (Robert Holbert), and he figured it out.

There were two problems:

  1. I didn’t have Windows Server Backup installed on many of my servers. This is a pre-req for doing System State backups.
  2. System State backups require 10-15GB free on the windows volume to store the system state.

After installing WSB and freeing up some space, everything backed up correctly. Woo! Way to go RH!

Advertisements

SCCM Task Sequence – Robocopy and WIM Image Backups from WinPE

This post will show you how to perform automated robocopy and WIM Image backups of all available drives (even Bitlocked!) during a task sequence in WinPE.

Requirements

The Script

Make a new SCCM package named “Scripts – Backups” and save this script as “Run-RobocopyBackup.wsf” in the package source directory.

Notes:

  • You will need to search for and change “sStateRoot” to your backup server path.
  • The script will create a folder within the sStateRoot path with the computer’s name.
  • The script will skip the Program Files, Program Files x86, Windows, and Default User directories.
  • The script will fail the TS Action if it doesn’t find at least 1 volume containing the folder “C:\Users” or “C:\Documents and Settings”.
'Run-RobocopyBackup.wsf

<script type="text/javascript" language="VBScript" src="../../wdpackage/scripts/ZTIUtility.vbs">// <![CDATA[

<script language="VBScript">

' //***************************************************************************
' // ***** Script Header *****
' //
' // Solution: Solution Accelerator for Microsoft Deployment
' // File: Z-Sample.wsf
' //
' // Purpose: Template
' //
' // Usage: cscript Z-Sample.wsf [/debug:true]
' //
' // Customer Build Version: 1.0.0
' // Customer Script Version: 1.0.0
' // Customer History:
' //
' // ***** End Header *****
' //***************************************************************************

'//----------------------------------------------------------------------------
'//
'// Global constant and variable declarations
'//
'//----------------------------------------------------------------------------

'Option Explicit

Dim iRetVal

'//----------------------------------------------------------------------------
'// End declarations
'//----------------------------------------------------------------------------

'//----------------------------------------------------------------------------
'// Main routine
'//----------------------------------------------------------------------------

On Error Resume Next
iRetVal = ZTIProcess
ProcessResults iRetVal
On Error Goto 0

'//---------------------------------------------------------------------------
'//
'// Function: ZTIProcess()
'//
'// Input: None
'//
'// Return: Success - 0
'// Failure - non-zero
'//
'// Purpose: Perform main ZTI processing
'//
'//---------------------------------------------------------------------------
Function Throw_Warning(msg)
	msg = "Run-Robocopy (WARNING): " & msg
	oLogging.CreateEntry msg, LogTypeError
	msgbox msg
End Function

Function Write_Log(msg)
	msg = "Run-Robocopy: " & msg
	oLogging.CreateEntry msg, LogTypeError
End Function

Function Test_UsersDir(aSourcePaths)

	If Right(sPath,1) = "\" Then
		sPath = Left(sPath,(Len(sPath) - 1))
	End If
	retval = False
	For Each sPath in aSourcePaths
		sFolder = sPath & "\Users\"
		sFolder2 = sPath & "\Documents and Settings\"
		'wscript.echo "searching: " & sFolder
		If oFSO.FolderExists(sFolder) = True Then
			retval = True
			Exit For
		ElseIf oFSO.FolderExists(sFolder2) = True Then
			retval = True
			Exit For
		End If
	Next

	Test_UsersDir = retval
End Function

Function Get_ComputerName
	sComputerName = oUtility.ComputerName
	Get_ComputerName = sComputerName
End Function

Function Test_FolderAccessOK(sTargetRoot)
	On Error Resume Next
	sTargetRoot = Trim_Slash(sTargetRoot) + "\"
	sFile = "scanstatetest_1111.txt"

	'create a scanstatetest_1111.txt file at target
	Set objFile = oFSO.CreateTextFile(sTargetRoot & sFile)
	objFile.close

	'test file existance
	bCreated = oFSO.FileExists(sTargetRoot & sFile)

	'delete file
	oFSO.DeleteFile(sTargetRoot & sFile)

	'test file existance
	bExistsAfterDelete = oFSO.FileExists(sTargetRoot & sFile)

	If bCreated = True And bExistsAfterDelete = False Then
		retval = True
	Else
		retval = False
	End If

	Test_FolderAccessOK = retval
End Function

Function Get_TargetRoot(sTargetRoot)
	sTargetRoot = Trim_Slash(sTargetRoot)

	'try path sTargetRoot & \ & "usmt-v4_capture" & i
	'return first path not found
	bFoundPath = False
	bExists = Null
	For i = 0 to 100
		sFolder = sTargetRoot & "\" & "robocopy_" & i & "\"
		bExists = oFSO.FolderExists(sFolder)
		If bExists = False Then
			bFoundPath = True
			Exit For
		End If
	Next

	If bFoundPath = False Then
		retval = False
	Else
		retval = sFolder
	End If

	Get_TargetRoot = retval
End Function

Function Make_FolderPath(strPath)
	'ref: http://www.windowsitpro.com/article/tips/jsi-tip-10441-how-can-vbscript-create-multiple-folders-in-a-path-like-the-mkdir-command-
	Dim strParentPath, objFSO
  Set objFSO = CreateObject("Scripting.FileSystemObject")
	On Error Resume Next
	strParentPath = objFSO.GetParentFolderName(strPath)

  If Not objFSO.FolderExists(strParentPath) Then MakeDir strParentPath
	If Not objFSO.FolderExists(strPath) Then objFSO.CreateFolder strPath
	On Error Goto 0
  MakeDir = objFSO.FolderExists(strPath)
End Function

Function Get_SourcePath
	sFolder = "C:\Users"
	sFolder2 = "C:\Documents and Settings"

	If oFSO.FolderExists(sFolder) = True Then
		retval = sFolder
	Else
		retval = sFolder2
	End If

	If oFSO.FolderExists(retval) = False Then
		retval = False
	End If

	Get_SourcePath = retval
End Function

Function Run_RobocopyBackup(aSourcePaths,sBackupsPath)
	bContinueRun = True

	sTargetRoot = Get_TargetRoot(sBackupsPath)
	bVarTest = False
	bVarTest = Is_Null(sTargetRoot)
	If bVarTest = True Or sTargetRoot = False Then
		bContinueRun = False
		msg = "Failed to generate a target directory."
		Throw_Warning msg
	End If

	If bContinueRun = True Then
		Dim aLines
		Redim aLines(0)
		i = 0
		For Each sSourcePath in aSourcePaths
			bFailThisPath = False
			If sSourcePath = "" Then
				bFailThisPath = True
			End If

			If bFailThisPath = False Then
				sTargetPath = Build_TargetPath(sTargetRoot,sSourcePath)
				If Right(sTargetPath,1) <> "\\" Then
					sTargetPath = sTargetPath & "\"
				End If

				'make folder path @ target
				bPathsMade = Make_FolderPath(sTargetPath)

				''write our batch file
				''write our batch file'ref: http://forums.datamation.com/intranet-journal/130-writing-text-file-using-vbscript.html
				If Ubound(aLines) < i Then
					Redim Preserve aLines(i)
				End If

				'leave this here -- something is betting passed By_Ref in Make_FolderPath and screwing it up. I should fix this...I've been assuming everything was by_val :/
				'If the slash doesn't get added, it won't copy the entire contents of the source if the source is a drive letter and the working path on that drive isn't the root!!
				If Right(sSourcePath,1) = "\" Then
					sSourcePath = sSourcePath
				Else
					sSourcePath = sSourcePath & "\"
				End If
				sExpression = "robocopy.exe " & sSourcePath & " " & sTargetPath & " /MT /XJ /DCOPY:T /R:1 /W:0 /B /E /XF pagefile.sys /XD ""C:\System Volume Information"" ""C:\Windows"" ""C:\Users\Default User"" ""c:\Program Files (x86)"" ""C:\Program Files"""
				aLines(i) = sExpression
				i = i + 1
			End If
		Next

		For Each sLine in aLines
			msg = "Running the following command: " & sLine
			Write_log msg
			sExitCode = oShell.Run(sLine,1,True)
			If sExitCode = "16" Then
				msg = "Robocopy exited with error code 16 - fatal error - no files were copied. Quitting script."
				Throw_Warning msg
				Wscript.Quit(100)
			End If
		Next

		retval = true
	End If

	Run_ScanState = retval
End Function

Function Build_TargetPath(sTargetRoot,sSourcePath)
	If Right(sTargetRoot,1) = "\" Then
		sTargetRoot = Left(sTargetRoot,(Len(sTargetRoot) - 1))
	End If
	If Right(sSourcePath,1) = "\" Then
		sSourcePath = Left(sSourcePath,(Len(sSourcePath) - 1))
	End If

	sSourceTemp = sSourcePath
	sSourceTemp = Replace(sSourceTemp,":","")
	sSourceTemp = Replace(sSourceTemp,"\","_")

	sTargetPath = sTargetRoot & "\" & sSourceTemp

	Build_TargetPath = sTargetPath
End Function

Function Is_Null(oVariable)
	If oVariable = "" Or oVariable = Null Then
		retval = True
	Else
		retval = False
	End If
	Is_Null = retval
End Function

Function Trim_Slash(sString)
	If Right(sString,1) = "\" Then
		sString = Left(sString,(Len(sString) - 1))
	End If
	trim_slash = sString
End Function

''''''''''''merged from enumerate-mountpoints.vbs
Function Get_UniqueFixedMountPoints
	strComputer = "."
	Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
	Set colItems = objWMIService.ExecQuery _
	    ("SELECT * FROM Win32_MountPoint")

	Dim MPVolumes(1000)

	Dim aMPs
	Redim aMPs(0)
	i = 0
	For Each objItem In colItems
		blnSkipMP = False
		sCurrentVolume = objItem.Volume
		For Each sStoredVolume in MPVolumes
			If sStoredVolume = sCurrentVolume Then
				blnSkipMP = True
			End If
		Next

		If blnSkipMP = False Then
			MPVolumes(i) = objItem.Volume
			If Ubound(aMPs) < i Then
				Redim Preserve aMPs(i)
			End If
			sDirName = objItem.Directory
			aDirName = Split(sDirName,"=")
			sDirectory = Replace(aDirName(1),"\\","\")
			sDirectory = Left(sDirectory,(len(sDirectory) - 1))
			sDirectory = Right(sDirectory,(len(sDirectory) - 1))
			If Right(sDirectory,1) = "\" Then
				sDirectory = Left(sDirectory,(len(sDirectory) - 1))
			End If
			'wscript.echo sDirectory
			aMPs(i) = sDirectory
			i = i + 1
		End If
	Next

	Get_UniqueFixedMountPoints = aMPs
End Function

Function Get_LogicalDisks
	strComputer = "."
	Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
	Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
	Set colItems = objWMIService.ExecQuery _
	    ("SELECT * FROM Win32_LogicalDisk")

	Dim aLDs
	Redim aLDs(0)
	i = 0
	For Each objItem In colItems
		If Ubound(aLDs) < i Then
			Redim Preserve aLDs(i)
		End If
		If objItem.DriveType = 3 Then
			sDevID = objItem.DeviceID
			aLDs(i) = sDevID
			i = i + 1
			'wscript.echo "found ld: " & sDevID
		End If
	Next
	Get_LogicalDisks = aLDs
End Function

Function Get_FixedVolumePaths(aMPs,aLDs)
	'strip any mount points that do not start with an LD
	dim aFixedVolumePaths
	Redim aFixedVolumePaths(0)
	For Each sMountPoint in aMPs
		bFoundLDforMP = False
		sMPDriveLetter = Left(sMountPoint,2)
		'wscript.echo "sMPDriveLetter: " & sMPDriveLetter

		'check that the mp has a drive letter in the ld list
		For Each sLogicalDisk in aLDs
			'sLDDriveLetter = Left(sLogicalDisk,2)
			'wscript.echo "sLogicalDisk: " & sLogicalDisk
			If sMPDriveLetter = sLogicalDisk Then
				bFoundLDforMP = True
			End If
		Next

		If bFoundLDforMP = True Then
			If Ubound(aFixedVolumePaths) < i Then
				Redim Preserve aFixedVolumePaths(i)
			End If
			aFixedVolumePaths(i) = sMountPoint
			i = i + 1
		End If
	Next

	Get_FixedVolumePaths = aFixedVolumePaths
End Function

''''''''''''MAIN
Function ZTIProcess()

		iRetVal = Success

		ZTIProcess = iRetval

		'!!!!!!!!!!!   INSERT YOUR CODE HERE   !!!!!!!!!!!!
		sStateRoot = "\\backupserver\share\robocopy"
		Set oTSEnv = WScript.CreateObject("Microsoft.SMS.TSEnvironment")

		'Get all potential source paths
		Dim aMPs
		aMPs = Get_UniqueFixedMountPoints
		Dim aLDs
		aLDs = Get_LogicalDisks
		Dim aSourcePathsTemp
		aSourcePathsTemp = Get_FixedVolumePaths(aMPs,aLDs)

		'strip out X:\ since it's always the WinPE disk
		Dim aSourcePaths
		Redim aSourcePaths(0)
		i = 0
		For Each sPath in aSourcePathsTemp
			If UBound(aSourcePaths) < i Then
				Redim Preserve aSourcePaths(i)
			End If
			If InStr(sPath,"X:") = False And sPath <> "" And sPath <> vbNull Then
					aSourcePaths(i) = sPath
					i = i + 1
			End If
		Next

		'Test all paths for C:\users or C:\documents and settings
		bUsersDirFound = False
		bUsersDirFound = Test_UsersDir(aSourcePaths)
		If bUsersDirFound <> True Then
			Throw_Warning "Failed to find the user directories."
			Wscript.Quit(100)
		End If

		sComputerName = Get_ComputerName
		If sComputerName = null Or sComputerName = "" Or sComputerName = -1 Then
			Throw_Warning "Failed to find the computer name."
			Wscript.Quit(300)
		End If

		bFolderAccess = False
		bFolderAccess = Test_FolderAccessOK(sStateRoot)
		If Is_Null(bFolderAccess) = True Or bFolderAccess = False Then
			msg = "Script doesn't have access to the target root: " & sStateRoot
			Throw_Warning msg
			bContinue = False
		Else
			sTargetPath = (Trim_Slash(sStateRoot)) + "\" + sComputerName
			Run_RobocopyBackup aSourcePaths,sTargetPath
		End If

End Function
// ]]></script>

Getting the Actions Right

We’ll need a few TS Actions to make this work.

  1. First, create a new group called “Backups”.
  2. Next, create a “Use Microsoft Deployment Toolkit Package” action.
  3. It would be a good idea to put a “Decrypt Bitlocker” action directly after the MDT action. See the blog post above under the “Requirements” header for detailed instructions.
  4. Create a “Connect to Network Folder” action with the following parameters. The account must have read\write permissions on the share and the NTFS files\folders in the share.
    Name: Connect to Backup Share
    Share: \\backupserver\sharename
    Account: domain\shareuser
  5. Create a “Set Task Sequence Variable” action with the following parameters. This only affects the WIM captures.
    Name: Set Backup Drive to All
    TS Variable: BackupDrive
    Value: ALL
  6. Create a “Set Task Sequence Variable” action with the following parameters. This is for your WIM captures.
    Name: Set Backup Location
    TS Variable: ComputerBackupLocation
    Value: \\backupserver\sharename\captures
  7. Create a “Run Command Line” action with the following parameters.
    Name: Robocopy Backup
    Command: run-robocopybackup.wsf
    Package: Scripts - Backups
  8. Create a “Run Command Line” action with the following parameters.
    Name: WIM Image Backup
    Command: cscript.exe "%SCRIPTROOT%\ZTIBackup.wsf"
    Package: Scripts - Backups
That’s it! You should now have some backups. 🙂

SCCM Task Sequence – Disable Bitlocker in WinPE

I made a task sequence action that backs up a computer using robocopy before partitioning, only to find that the system is protected by BitLocker. Here’s how to automatically unlock Bitlocker drives in WinPE in a task sequence. This script will only work if you integrated the WinPE ADSI Plug-In into your boot image. For instructions, see this post: “SCCM – Adding Active Directory Support to WinPE 3.1“.

The Script

I didn’t write the script myself; I heavily modified a script that I can’t find the source for. If part of this is yours, please let me know! I know I found it on a blog somewhere…sorry :(. Make a new SCCM package named “Scripts – DecryptDBE”, and save this script as “Auto-DecryptBDE.vbs” in the package source directory.

sUsername = "REMOVED"
sPassword = "REMOVED"
sDCfqdn = "REMOVED--DomainController"

Function Write_Log(msg)
	Wscript.Echo msg
End Function

Function Get_RecoveryKeysFromDN(dn,sDCfqdn,sUsername,sPassword)
	Set objDSO = GetObject("LDAP:")
	strPathToComputer = "LDAP://" & sDCfqdn & "/" & dn

	Const ADS_SECURE_AUTHENTICATION = 1
	Const ADS_USE_SEALING = 64 '0x40
	Const ADS_USE_SIGNING = 128 '0x80

	'--------------------------------------------------------------------------------
	'Get all BitLocker recovery information from the Active Directory computer object
	'--------------------------------------------------------------------------------
	'Get all the recovery information child objects of the computer object
	Set objFveInfos = objDSO.OpenDSObject(strPathToComputer, sUsername, sPassword, _
		ADS_SECURE_AUTHENTICATION + ADS_USE_SEALING + ADS_USE_SIGNING)
	objFveInfos.Filter = Array("msFVE-RecoveryInformation")

	'Iterate through each recovery information object and save any existing key packages
	Dim aKeys()
	Redim aKeys(0)
	i = 0
	bFoundKey = False
	For Each objFveInfo in objFveInfos
		bFoundKey = True
		If uBound(aKeys) < i Then
			Redim Preserve aKeys(i)
		End If
		strName = objFveInfo.Get("name")
		strRecoveryPassword = objFveInfo.Get("msFVE-RecoveryPassword")
		sNamePass = strName & "|" & strRecoveryPassword
		aKeys(i) = sNamePass
		i = i + 1
	Next

	If bFoundKey = True Then
		retval = aKeys
	Else
		retval = null
	End If

	Get_RecoveryKeysFromDN = retval
End Function

Function Find_ADRecoveryKey(sBDEPassword,sDCfqdn,sUsername,sPassword)
	'Search for all computer objects
	strBase = "<GC://" & sDCfqdn & ">"
	strFilter = "(&(objectCategory=computer))"
	strQuery = strBase & ";" & strFilter  & ";distinguishedName;subtree"

	''create connection
	Set oConnection = CreateObject("ADODB.Connection")
	oConnection.Provider = "ADsDSOObject"
	oConnection.Properties("User ID") = sUsername
	oConnection.Properties("Password") = sPassword
	oConnection.Properties("Encrypt Password") = True
	oConnection.Properties("ADSI Flag") = ADS_SERVER_BIND Or ADS_SECURE_AUTHENTICATION
	Set oCommand = CreateObject("ADODB.Command")
	oConnection.Open "Active Directory Provider"
	Set oCommand.ActiveConnection = oConnection
	oCommand.CommandText = strQuery
	oCommand.Properties("Page Size") = 100
	oCommand.Properties("Timeout") = 100
	oCommand.Properties("Cache Results") = False

  Set objRecordSet = oCommand.Execute
  If objRecordSet.EOF Then
    WScript.echo "The domain could not be contacted."
    WScript.Quit 1
  End If

  'For each computer object found look through it's keys for the one we want.
  bKeyFound = False
  Do Until objRecordSet.EOF
    dnFound = objRecordSet.Fields("distinguishedName")
    Dim aRecoveryKeys
    aRecoveryKeys = Get_RecoveryKeysFromDN(dnFound,sDCfqdn,sUsername,sPassword)

    If IsArray(aRecoveryKeys) = True Then
    	If Ubound(aRecoveryKeys) > 0 Then
	    	For Each sKey In aRecoveryKeys
					If instr(sKey,sBDEPassword) Then
						msg = "Matching key found under computer dn: """ & dnfound & """."
						write_log msg
						strTempString = Split(sKey,"|")
		    		sRecoveryKey = strTempString(1)
		    		bKeyFound = True
					End If
				Next
			End If

		End If

    If bKeyFound = True Then
    	Exit Do
    Else
			objRecordSet.MoveNext
		End If
  Loop
  ' Clean up.
  Set objConnection = Nothing
  Set objCommand = Nothing
  Set objRecordSet = Nothing

  If bKeyFound = True Then
  	retval = sRecoveryKey
  Else
  	retval = false
  End If

  Find_ADRecoveryKey = retval
End Function

Function Unlock_AllDrivesWithAD(sDCfqdn,sUsername,sPassword)
	On Error Resume Next
	'foreach encrypted drive
	Set oDrivesPasswords = CreateObject("Scripting.Dictionary")
	Set oWMIService = GetObject("winmgmts:\\.\root\CIMV2\Security\MicrosoftVolumeEncryption")
	Set oVolumes = oWMIService.InstancesOf("Win32_EncryptableVolume")

	For each volume In oVolumes
		bDecryptNeeded = False
		'check for encryption
		'ref: http://msdn.microsoft.com/en-us/library/windows/desktop/aa376434(v=vs.85).aspx
		volume.GetEncryptionMethod iBdeMethod
		volume.GetLockStatus iBDEStatus
		volume.GetKeyProtectors 0,VolumeKeyProtectorID
		sDriveLetter = volume.DriveLetter

		If iBDEStatus <> 0 Then
			msg = "Found locked volume. Drive letter: """ & sDriveLetter & """."
			Write_Log msg
			For Each objId in VolumeKeyProtectorID
				msg = "KeyProtector for drive letter """ & sDriveLetter & """: """ & objId & """."
				write_log msg
		  Next
				bDecryptNeeded = True
		End If

		If bDecryptNeeded = True Then
			'loop through all key protectors
			For Each BDEPassword in VolumeKeyProtectorID
				sADRecoveryKey = null
				'search AD for corresponding recovery keys
				sADRecoveryKey = Find_ADRecoveryKey(BDEPassword,sDCfqdn,sUsername,sPassword)
					'attempt unlock
				If sADRecoveryKey <> False Then
					msg = "Unlocking drive with AD key"
					write_log msg
					volume.UnlockWithNumericalPassword sADRecoveryKey
					volume.GetProtectionStatus iBDEStatus
					If iDBEstatus = 0 Then
						msg = "Drive unlocked."
						write_log msg
					Else
						msg = "Failed to unlock the drive."
						write_log msg
						Wscript.Quit(100)
					End If
				End If
			Next
		End If
	Next
End Function

Function Unlock_AllDrivesWithManualKey(sUsername,sPassword)
	On Error Resume Next
	'foreach encrypted drive
	Set oDrivesPasswords = CreateObject("Scripting.Dictionary")
	Set oWMIService = GetObject("winmgmts:\\.\root\CIMV2\Security\MicrosoftVolumeEncryption")
	Set oVolumes = oWMIService.InstancesOf("Win32_EncryptableVolume")

	For each volume In oVolumes
		bDecryptNeeded = False
		'check for encryption
		'ref: http://msdn.microsoft.com/en-us/library/windows/desktop/aa376434(v=vs.85).aspx
		volume.GetEncryptionMethod iBdeMethod
		volume.GetLockStatus iBDEStatus
		volume.GetKeyProtectors 0,VolumeKeyProtectorID
		sDriveLetter = volume.DriveLetter

		If iBDEStatus <> 0 Then
			msg = "Failed to unlock all volumes with AD recovery keys. Asking user for manual key input."
			Write_Log msg
			msg = "Found locked volume. Drive letter: """ & sDriveLetter & """."
			Write_Log msg
			For Each objId in VolumeKeyProtectorID
				msg = "KeyProtector for drive letter """ & sDriveLetter & """: """ & objId & """."
				write_log msg
		  Next
				bDecryptNeeded = True
		End If

		If bDecryptNeeded = True Then
			'loop through all key protectors
			bContinue = True
			For Each BDEPassword in VolumeKeyProtectorID
				If bContinue = False Then
					Exit For
				End If
				'Ask the user for one repeatedly until the drive unlocks or the user presses cancel.
				bContinue = True
				While bContinue = True
					msg = "No key was found in AD for volume " & sDriveLetter & " with public key " & BDEPassword & ". Please enter a password to unlock the drive. Type ""next"" to attempt skipping to the next BDEPassword (if available). Press cancel to quit."
					sUserKey = InputBox(msg)
					If sUserKey = Null Or sUserKey = "" Then
						Wscript.Quit(100)
					ElseIf LCase(sUserKey) = "next" Then
						bContinue = False
					Else
						volume.UnlockWithNumericalPassword sUserKey
						volume.GetLockStatus iBDEStatus
						If iBDEstatus = 0 Then
							msg = "Drive unlocked."
							write_log msg
							bContinue = False
						Else
							msg = "Failed to unlock the drive."
							msgbox msg
						End If
					End If
				Wend
			Next
		End If
	Next
End Function

Unlock_AllDrivesWithAD sDCfqdn,sUsername,sPassword
Unlock_AllDrivesWithManualKey sUsername,sPassword

A couple quick notes: it would be prudent for me (or you) to rewrite this script so that AD credentials were passed by argument instead of hard coded. Also, it’d be nice if it found the domain controllers via DNS SRV records instead of being hard-coded.

Task Sequence Work

Just make a “Run Command-Line” action in your task sequence with the following parameters.

Name: Decrypt Bitlocker Drives
Command: Auto-DecryptBDE.vbs
Package: Scripts - DecryptDBE

I wish you more awesome task sequences!

Using VCB to backup all VM’s

I recently heard a horror story about someone losing all of their VM’s, and decided to revisit VCB to grab a fresh copy of all my vcenter VMDK’s.  It took some remembering, so here it goes:

  1. Download and install VMWare Consolidated Backup.
  2. Open a command prompt and navigate to where you installed VCB.
  3. Make a folder to store your VMDK’s.
  4. Run the following command:
    for /f "tokens=2 delims=:" %%i in ('vcbvmname -h VCENTER.SERVER.FQDN -u USERNAME -p PASSWORD -s any ^| find "name:"') do vcbmounter -h VCENTER.SERVER.FQDN -u USERNAME -p PASSWORD -a name:"%%i" -r "DRIVELETTER:\FOLDER\%%i" -t fullvm -m nbd > "DRIVELETTER:\FOLDER\%%i.log"

References: