Scripted VHD-to-Physical Disk Restoration: Automated Drive Cloning Techniques for Windows


2 views

While creating VHD backups is straightforward using tools like Disk2vhd or Windows Image Backup, restoring these images to physical disks presents unique technical hurdles. The primary limitation stems from Windows' inability to directly overwrite the system disk during operation due to file locking mechanisms.

Here are three viable methods for scripted VHD restoration:

1. Using DISM in Windows PE

This method requires booting into Windows PE but can be fully automated:


@echo off
:: This script runs in WinPE after assigning drive letters
dism /apply-image /imagefile:D:\backup.vhd /index:1 /applydir:C:
bcdboot C:\Windows /s S:

2. Virtual Disk Service API

For non-system disks, PowerShell enables direct VHD operations:


# Mount VHD and clone contents
Mount-VHD -Path "D:\backup.vhd" -ReadOnly
robocopy "X:\" "E:\" /MIR /COPYALL /R:1 /W:1
Dismount-VHD -Path "D:\backup.vhd"

3. Third-party Tools with Scripting Support

Tools like Clonezilla offer automated restoration:


# Clonezilla auto-restore config
ocs-sr -e1 auto -e2 -batch -r -j2 -p true restoredisk sda backup.vhd

For daily cloning operations, consider these architectural elements:

  • Scheduled task triggering during maintenance windows
  • Pre-execution validation of target disk capacity
  • Post-restoration verification hashes
  • Email notification upon completion/failure

Here's a complete PowerShell module for automated VHD restoration:


function Restore-VHDToDisk {
    param(
        [string]$VHDPath,
        [string]$TargetDisk,
        [switch]$Force
    )
    
    # Validation checks
    if (-not (Test-Path $VHDPath)) {
        throw "VHD file not found"
    }
    
    # Mount VHD temporarily
    $mount = Mount-VHD -Path $VHDPath -PassThru -ReadOnly
    
    try {
        # Get partition information
        $partitions = Get-Partition -DiskNumber $mount.DiskNumber
        
        foreach ($partition in $partitions) {
            $sourcePath = "$($partition.DriveLetter):"
            $destinationPath = "$TargetDisk$($partition.PartitionNumber)"
            
            # Robocopy implementation
            Start-Process robocopy -ArgumentList 
                """$sourcePath"" ""$destinationPath"" /MIR /COPYALL /R:1 /W:1" -Wait
        }
    }
    finally {
        Dismount-VHD -Path $VHDPath
    }
}

For large-scale deployments:

  • Implement differential VHDs using PowerShell's Export-VHD
  • Consider hardware write acceleration features
  • Benchmark different block sizes for your storage subsystem

For scripting VHD restoration without boot media, start by mounting the VHD file programmatically. Windows PowerShell provides native cmdlets:

# Mount VHD read-only to prevent accidental writes
Mount-VHD -Path "C:\backups\system.vhd" -ReadOnly

# Get the mounted disk number
$disk = Get-Disk | Where-Object { $_.Location -match "C:\\backups\\system.vhd" }
$diskNumber = $disk.Number

# Verify partition layout
Get-Partition -DiskNumber $diskNumber | Format-Table

The critical operation requires raw disk copying while maintaining partition structure. Two reliable approaches:

1. Using DISKPART and ROBOCOPY

# Create DISKPART script
@"
select vdisk file="C:\backups\system.vhd"
attach vdisk readonly
select disk 1 (target physical disk)
clean
convert gpt
"@ | Out-File "clone_script.txt"

diskpart /s clone_script.txt

# Copy partitions (adjust source/target accordingly)
robocopy "\\?\GLOBALROOT\Device\Harddisk2\Partition1\" "\\?\GLOBALROOT\Device\Harddisk1\Partition1\" /MIR /COPYALL /R:1 /W:1

2. dd for Windows

The Unix dd utility has Windows ports that handle block-level copies:

dd if=\\.\PhysicalDrive2 of=\\.\PhysicalDrive1 bs=1M --size --progress

For daily cloning operations, implement these safeguards:

  • Verify checksums pre/post operation
  • Use Volume Shadow Copy for consistency
  • Implement email notifications

Example monitoring wrapper:

try {
    $vhdHash = Get-FileHash "C:\backups\system.vhd" -Algorithm SHA256
    # Execute cloning process...
    $targetHash = Get-DiskSignature -DiskNumber 1
    if ($vhdHash.Hash -ne $targetHash) {
        throw "Verification failed"
    }
    Send-MailMessage -To "admin@example.com" -Subject "Clone Success" -Body "Daily clone completed"
}
catch {
    Write-EventLog -LogName Application -Source "DiskClone" -EntryType Error -Message $_.Exception.Message
}
Tool Scriptable Speed Compression
Disk2vhd Partial Medium No
Clonezilla Yes Fast Yes
Storage Migration Service Yes Slow Yes

For enterprise environments, consider Windows Server Storage Replica or Storage Migration Service for more robust solutions.