MDT Backups with Virtual (VHD) Disk format

Full Disk Backup – MDT 2012

Microsoft’s Deployment Toolkit continues to surprise me with what a flexible product it is.  One area that can be enhanced is with a full machine backup. 

I’ve been forced to change my mind over the past 18 months in regard to User State Migration.  For many years IT has been battling to ensure staff don’t leave important files on their local drives – after all, if there was a fire or machines were stolen local disks aren’t backed up and that represents a problem.  User State Migration isn’t primarily a backup tool, its purpose is to preserve user session related settings and customisations to help staff in their transition to a new machine.  That said, in a managed environment where staff are restricted to user rights, USMT has shown itself to be extremely effective in protecting the accidental deletion of files.

Environments that aren’t as strongly controlled may still require a full disk backup to minimise risk that production data will be accidentally lost.  By default, MDT 2010 and 2012 utilise ImageX.exe to create WIM format images as part of their machine backup process.  Recent versions of ImageX.exe and its replacement DISM.exe have shown themselves to have comparatively poor performance in the creation of disk images.

P2V Migration for Software Assurance

With MDT 2010, Microsoft released the solution accelerator P2V Migration for Software Assurance.  The solution was specifically targeted at organisations moving from 32bit Windows XP whom wished to use an installation of Virtual PC on their new Windows 7 machines.  The solution was quite neat.  It would patch the XP machine and ensure that when the Windows 7 build completed, MDT would copy the VHD image back to the local computer and mount it (and its legacy applications) within the new Windows 7 environment as a separate, legacy machine.

Although it was a neat idea, when a new Operating System is rolled out we often need to completely get rid of the old system while we have the chance.  Using a VHD format disk image (created with the Disk2VHD utility) does show a considerable performance improvement over the inbuilt ImageX.exe utility within MDT.

P2V Migration for Software Assurance was only released by Microsoft for MDT 2010 (which loses support itself shortly) and can only be used with 32bit Windows XP.  The solution was limited as its goal was to produce a working virtual machine, not just a backup using VHD format.

MDT 2012 and using VHD format for full disk backup.

The script responsible for a system disk backup within MDT is ZTIBackup.wsf, which is found in the “DeploymentShare\Scripts” folder.

Amending ZTIBackup.wsf allows the bulk-standard MDT wizard dialogues to be used with standard task sequences.  This is a major bonus if an organisation has a USB based upgrade approach for machines.

In addition to modifying ZTIBackup.wsf, a copy of the utility Disk2vhd.exe needs to be copied to the “Deploymentshare\Tools” directory.

Amending ZTIBackup.wsf

The MDT 2012 Version of ZTIBackup.wsf must be altered in 3 locations.

1.  The default file extension needs to be changed to ".vhd" instead of the Windows Image based ".wim"

On line 336

  sBackupFile = oUtility.ComputerName & ".wim"

 sBackupFile = oUtility.ComputerName & ".VHD"

 2. From line 451, Delete the lines that called ImageX.exe and replace them with Disk2VHD lines such as:

449         ' Execute it
450         ' #####################################
451         '
453         oLogging.CreateEvent 41035, LogTypeInfo, "Beginning backup of drive " & oDrive.Path, Array(oDrive.Path)
455        sCmd = AllDrivesFromSysPart & " """ & sBackupPath & """ -h -accepteula"
457        iRc = oUtility.FindExeAndRunWithLogging( "Disk2vhd.exe", sCmd )    
458        If iRC <> 0 then
459            oLogging.CreateEvent 41036, LogTypeError, "Error creating an image of drive " & sBackupPath & ", rc = " & iRc, Array(sBackupPath, iRC)
460        Else
461            oLogging.CreateEvent 41037, LogTypeInfo, "Successfully created image of drive " & sBackupPath, Array(sBackupPath, iRC)
462        End if      
463        TestAndFail  oFSO.FileExists(sBackupPath) or oFSO.FileExists(sBackupPath & ".VHD"),  35024,  "VHD Backup file not created (found)! File: " & sBackupPath
464        oLogging.CreateEntry oUtility.ScriptName & " COMPLETED.  Return Value = " & iRC, LogTypeInfo

    '                iRc = oUtility.FindExeAndRunWithLogging( "imagex.exe", sCmd )            
    '                If iRc <> 0 then
    '                    oLogging.CreateEvent 41036, LogTypeError, "Error creating an image of drive " & oDrive.Path & ", rc = " & iRc, Array(oDrive.Path, iRc)
    '                    iRetVal = iRc
    '                    Exit For
    '                Else
    '                    oLogging.CreateEvent 41037, LogTypeInfo, "Successfully created image of drive " & oDrive.Path, Array(oDrive.Path, iRc)
    '                End if


3.  Insert Microsoft's "All Drives from Sys Partiton" function.  This will be used to identify which drives are backed up with the Disk2VHD utility.

Function AllDrivesFromSysPart

        Dim oSysPart
        Dim oDiskPart
        Dim oLogical
        DIm oLogicals
        Dim sTempFile

        AllDrivesFromSysPart = left(UCase(oEnv("SystemDrive")),2)

        for each oSysPart in objWMI.ExecQuery("Associators of {Win32_LogicalDisk.DeviceID='" & AllDrivesFromSysPart & "'} where ResultClass = Win32_DiskPartition")
            oLogging.CreateEntry "WMI path to System Partition: " & oSysPart.Path_, LogTypeInfo

            If oSysPart.Index = 0 and oSysPart.Bootable then
                oLogging.CreateEntry "System Partition is Bootable, other partitions are unintresting.", LogTypeInfo
                exit For


                for each oDiskPart in objWMI.ExecQuery("SELECT * FROM Win32_diskPartition WHERE DiskIndex = " & oSysPart.DiskIndex & " AND DeviceID <> '" & oSysPart.DeviceID & "'  and Bootable = True" )
                    oLogging.CreateEntry "WMI Path to Other Partitions: " & oDiskPart.Path_, LogTypeInfo

                    Set oLogicals = objWMI.ExecQuery("Associators of {" & oDiskPart.Path_ & "} where ResultClass = Win32_LogicalDisk")
                    If oLogicals.Count = 0 then

                        oLogging.CreateEntry "Assign Drive letter to partition: " & oDiskPart.Path_, LogTypeInfo

                        sTempFile = oFSO.GetSpecialFolder(2).Path & "\" & oFSO.GetTempName
                        With oFSO.CreateTextFile( sTempFile , True, false )
                            .WriteLine "Select disk " & oDiskPart.DiskIndex
                            .WriteLine "Select partition " & ( oDiskPart.Index + 1 )
                            .WriteLine "assign"
                        end with

                        oUtility.RunWithHeartbeat "diskpart.exe /s " & sTempFile

                        oLogging.CreateEntry "   Rescan Logical Disks: " & oDiskPart.Path_, LogTypeInfo
                        Set oLogicals = objWMI.ExecQuery("Associators of {" & oDiskPart.Path_ & "} where ResultClass = Win32_LogicalDisk")

                        If oLogicals.Count = 0 then
                            oLogging.CreateEntry "ERROR, unable to map partition!", LogTypeInfo
                            exit function
                        End if 

                    End if

                    For each oLogical in oLogicals
                        oLogging.CreateEntry "Found other Logical Disk: " & oLogical.Path_, LogTypeInfo
                        AllDrivesFromSysPart = AllDrivesFromSysPart & " " & oLogical.DeviceID

            End if 

    End function