This is one of the main worker scripts that we use often. This script's primary purpose is to update a locally attached USB deployment disk with data from the deployment folders. There are several optional parameters that can be included to have the script do additional things:

  • -UpdateMedia
    This will utilize MDT's PowerShell interfaces to update the \DeploymentMedia1 folder, including updating the Windows PE WIM included in it. That WIM is used for image capture, so it is useful to keep it up to date. This takes about 20-30 minutes, depending on your system.
  • -UpdateBoot
    This will utilize MDT's PowerShell interfaces to update the boot Windows PE image for the main MDT deployment share (\DeploymentShare.ROOT). It will then expand that ISO into a cache folder. This is the boot image used to populate the MDTBOOT partition on the USB disk, so it is used often. Depending on the number of drivers being changed on it, this can take a while to complete.
  • -UpdateDevDisk
    This will update the DevDisk.vhdx file in \VMs with the latest bits. Be sure that a deployment disk is NOT attached via USB at the same time; behavior is unpredictable then. If the VM is running, it will be stopped automatically.

NOTE: This tool needs you to have 7-Zip installed in order to facilitate the expansion of the ISO image.

Param([switch]$UpdateMedia,[switch]$UpdateBoot,[switch]$UpdateDevDisk)

# Configuration settings
$MediaName='MEDIA001'  # Name of the media share
$ZipTool='C:\Program Files\7-Zip\7z.exe' # Path to 7-Zip executable
$SyncTool='C:\Windows\System32\Robocopy.exe' # Path to sync tool

# Intro
if ($UpdateDevDisk -eq $false) {
Write-Host 'We will be updating the USB drive for' $MediaName
}

# Stop MDT01 VM if UpdateDevDisk is included
If ($UpdateDevDisk) {
Get-Process -Name vmconnect -ErrorAction SilentlyContinue | Stop-Process -Force -Confirm:$false
Write-Host 'We will be updating the DevDisk.vhdx image for' $MediaName
If ((Get-VM -Name MDT01).State -ne 'Off') {
Write-Host 'Stopping the MDT01 VM to prevent file locks'
Stop-VM -Name MDT01 -Force -Confirm:$false
}
Write-Host 'Mounting the DevDisk.vhdx image'
Mount-VHD -Path D:\VMs\DevDisk.vhdx
}

# Import the MDT PowerShell commands
If ((Get-PSSnapin | Where { $_.Name -eq 'Microsoft.BDD.PSSnapIn' }).Count -eq 0) { Import-Module "C:\Program Files\Microsoft Deployment Toolkit\Bin\MicrosoftDeploymentToolkit.psd1" }
Write-Host 'MDT snap in loaded'

# Look for USB disk presence
$DataVolume = Get-Volume | Where { $_.FileSystemLabel -match 'MDTDEPLOY' }
If ($DataVolume.Count -eq 0) {
  Write-Host -ForegroundColor Yellow 'Could not fund USB drive.  Format a drive with two partitions:'
  Write-Host -ForegroundColor Yellow ' 1) 8192 MB, formatted FAT32, labeled MDTBOOT, made active'
  Write-Host -ForegroundColor Yellow ' 2) * MB, formatted NTFS, labeled MDTDEPLOY'
  Exit
}
$DataLetter = $DataVolume.DriveLetter
Write-Host 'MDTDEPLOY partition found on drive' $DataLetter

$BootVolume = Get-Volume | Where { $_.FileSystemLabel -match 'MDTBOOT' }
If ($BootVolume.Count -eq 0) {
  Write-Host -ForegroundColor Yellow 'Could not fund USB drive.  Format a drive with two partitions:'
  Write-Host -ForegroundColor Yellow ' 1) 8192 MB, formatted FAT32, labeled MDTBOOT, made active'
  Write-Host -ForegroundColor Yellow ' 2) * MB, formatted NTFS, labeled MDTDEPLOY'
  Exit
}
$BootLetter = $BootVolume.DriveLetter
Write-Host 'MDTBOOT partition found on drive' $BootLetter

# Mount the deployment share
Write-Host 'Mounting main deployment share...'
Restore-MDTPersistentDrive
$RealRoot = (Get-PSDrive -Name 'DS001').Root

# Optionally update boot files
if ($UpdateBoot) {
  Update-MDTDeploymentShare -Path 'DS001:' -Verbose -ErrorAction SilentlyContinue
  # Expand ISO into a cache folder for disk maintenance
  $Cmd = '"C:\Program Files\7-zip\7z.exe" e "'+$RealRoot+'\Boot\LiteTouchPE_x64.iso" -o"'+$RealRoot+'\Boot\LiteTouchPE_x64.cache" -r -y'
  Write-Host 'Expanding ISO image into cache folder...'
  $CachePath=$RealRoot+'\Boot\LiteTouchPE_x64.cache'
  Remove-Item -Path $CachePath -Force -Recurse -ErrorAction SilentlyContinue
  New-Item -Path $CachePath -ItemType directory | Out-Null
  Push-Location $RealRoot\Boot\LiteTouchPE_x64.cache
  Start-Process -FilePath $ZipTool -ArgumentList ('x ' + $RealRoot + '\Boot\LiteTouchPE_x64.iso') -Wait -ErrorAction SilentlyContinue
  Pop-Location
  Remove-PSDrive -Name 'DS001'
}

# Get info about the media deployment root
$DeploymentRoot = (Get-MDTPersistentDrive | Where { $_.Name -eq 'DS001' }).Path
[xml]$Medias = Get-Content -Path ($DeploymentRoot+'\Control\Medias.xml')
$MediaEntry = $Medias.medias.media | Where { $_.Name -eq $MediaName }

# Optionally update media folder
if ($UpdateMedia) {
  # Mount the media ISO file to block it from being updated (we don't actually use it)
  Mount-DiskImage -ImagePath ($MediaEntry.Root + '\LiteTouchMedia.iso') -StorageType ISO -NoDriveLetter
  Write-Host 'Mounted ISO image to block that step from running during update cycle'

  New-PSDrive -Name 'DSXXX' -PSProvider MDTProvider -Root $DeploymentRoot
  Write-Host -ForegroundColor Green 'NOTE: A return code of 1 for the update is normal because we block the ISO from being updated'
  Update-MDTMedia -Path ("DSXXX:\Media\" + $MediaName) -Verbose -ErrorAction SilentlyContinue
  Remove-PSDrive -Name 'DSXXX'
  Write-Host 'Update of media content completed'

  Dismount-DiskImage -ImagePath ($MediaEntry.Root + '\LiteTouchMedia.iso') -StorageType ISO
  Write-Host 'Unmounted ISO image'
}

# Merge computer settings in external drive's CustomSettings.ini into main file for future use
Start-Process -FilePath C:\Windows\System32\cscript.exe -ArgumentList ('D:\MergeCustomSettings.vbs /external:' + $DataLetter + ' /master:' + $MediaEntry.Root) -Wait -ErrorAction SilentlyContinue

# Update files for solution
Write-Host 'Updating semi-static file sources...'
Write-Host '   IntroScreen.hta...'
Copy-Item -Path .\DeploymentMedia1\WinPE.Custom\IntroScreen.hta -Destination ($MediaEntry.Root + '\Content') | Out-Null
Write-Host '   Lenovo Repository...'
Start-Process -FilePath '.\UpdateLenovo.cmd' -Wait -ErrorAction SilentlyContinue -WindowStyle Minimized
Write-Host

# Backup any Recovery Keys
Write-Host 'Saving any recovery keys...'
Copy-Item -Path ($DataLetter + ':\RecoveryKeys\*.*') -Destination ($MediaEntry.Root + '\Content\RecoveryKeys') | Out-Null
Write-Host 'Moving to central repository...'
Copy-Item -Path ($MediaEntry.Root + '\Content\RecoveryKeys\*.*') -Destination ('.\RecoveryKeys') | Out-Null
Write-Host 'Cleaning up media keys...'
Remove-Item -Path ($MediaEntry.Root + '\Content\RecoveryKeys\*.txt') | Out-Null
Write-Host

# Copy content over to USB drive
Write-Host 'Starting synchronization to the USB drive...'
Write-Host '   Boot partition '$BootLetter'...'
Start-Process -FilePath $SyncTool -ArgumentList ($RealRoot + '\Boot\LiteTouchPE_x64.cache ' + $BootLetter + ':\ /MIR') -Wait -ErrorAction SilentlyContinue -WindowStyle Minimized
Write-Host '   Data partition '$DataLetter'...'
Start-Process -FilePath $SyncTool -ArgumentList ($MediaEntry.Root + '\Content ' + $DataLetter + ':\ /MIR') -Wait -ErrorAction SilentlyContinue -WindowStyle Minimized
Write-Host '   BIOS flat files to '$BootLetter'...'
Start-Process -FilePath $SyncTool -ArgumentList ('\Source.BIOS ' + $BootLetter + ':\ /S') -Wait -ErrorAction SilentlyContinue -WindowStyle Minimized
Write-Host 'File synchronization is completed.'
if ($UpdateDevDisk -eq $false) {
Write-Host 'You may now eject the disk and use it in a computer.'
}

If ($UpdateDevDisk) {
Write-Host 'Synchronization completed'
Write-Host 'Dismounting volumes'
Start-Process -FilePath 'C:\Windows\System32\fsutil.exe' -ArgumentList ('volume dismount ' + $BootLetter + ':') -Wait -ErrorAction SilentlyContinue -WindowStyle Minimized
Start-Process -FilePath 'C:\Windows\System32\fsutil.exe' -ArgumentList ('volume dismount ' + $DataLetter + ':') -Wait -ErrorAction SilentlyContinue -WindowStyle Minimized
Write-Host 'Dismounting DevDisk.vhdx'
Dismount-VHD -Path D:\VMs\DevDisk.vhdx

Write-Host 'Changing MDT01 boot order to boot to DevDisk.vhdx'
$MainDisk = Get-VMHardDiskDrive -VMName MDT01 -ControllerLocation 0
$DevDisk = Get-VMHardDiskDrive -VMName MDT01 -ControllerLocation 1

Set-VMFirmware -VMName MDT01 -FirstBootDevice $DevDisk
Write-Host 'Booting VM MDT01'
Start-VM -Name MDT01
Start-Sleep -Seconds 3
vmconnect localhost mdt01
Write-Host 'Waiting 10 seconds for boot to complete'
Start-Sleep -Seconds 10
Write-Host 'Changing MDT01 boot order back to main VHDX file'
Set-VMFirmware -VMName MDT01 -FirstBootDevice $MainDisk
Write-Host 'All done.'
}