Merge pull request #3 from rbalsleyMSFT/v_next

2309.2
This commit is contained in:
rbalsleyMSFT
2023-09-15 10:32:48 -07:00
committed by GitHub
3 changed files with 168 additions and 65 deletions
+165 -60
View File
@@ -202,7 +202,7 @@ param(
[ValidateSet(512, 4096)] [ValidateSet(512, 4096)]
[uint32]$LogicalSectorSizeBytes = 512 [uint32]$LogicalSectorSizeBytes = 512
) )
$version = '2309.1' $version = '2309.2'
#Check if Hyper-V feature is installed (requires only checks the module) #Check if Hyper-V feature is installed (requires only checks the module)
$osInfo = Get-WmiObject -Class Win32_OperatingSystem $osInfo = Get-WmiObject -Class Win32_OperatingSystem
@@ -1149,8 +1149,8 @@ Function Get-WindowsVersionInfo {
WriteLog "Unloading registry" WriteLog "Unloading registry"
Invoke-Process reg "unload HKLM\FFU" Invoke-Process reg "unload HKLM\FFU"
#This prevents Critical Process Died errors you can have during deployment of the FFU. Capturing from very fast disks (NVME) can cause the capture to happen faster than Windows is ready for. #This prevents Critical Process Died errors you can have during deployment of the FFU. Capturing from very fast disks (NVME) can cause the capture to happen faster than Windows is ready for.
WriteLog 'Sleep 15 seconds to allow registry to completely unload' WriteLog 'Sleep 60 seconds to allow registry to completely unload'
Start-sleep 15 Start-sleep 60
@@ -1167,91 +1167,186 @@ Function New-DeploymentUSB {
[switch]$CopyFFU [switch]$CopyFFU
) )
WriteLog "CopyFFU is set to $CopyFFU" WriteLog "CopyFFU is set to $CopyFFU"
# Set your FFUDevelopmentPath here $BuildUSBPath = $PSScriptRoot
$BuildUSBPath = $FFUDevelopmentPath WriteLog "BuildUSBPath is $BuildUSBPath"
$counter = 0
# Get the first removable USB drive $USBDrives = (Get-WmiObject -Class Win32_DiskDrive -Filter "MediaType='Removable Media'")
$USBDrive = (Get-WmiObject -Class Win32_DiskDrive -Filter "MediaType='Removable Media'") If ($USBDrives -and ($null -eq $USBDrives.count)) {
$USBDrivesCount = 1
}
else {
$USBDrivesCount = $USBDrives.Count
}
WriteLog "Found $USBDrivesCount USB drives"
if ($null -eq $USBDrive) { if ($null -eq $USBDrives) {
Writelog "No USB drive found" WriteLog "No removable USB drive found."
exit 1 exit 1
} }
# Format the USB drive $SelectedFFUFile = $null
$DiskNumber = $USBDrive.DeviceID.Replace("\\.\PHYSICALDRIVE", "")
$ScriptBlock = {
param($DiskNumber)
Clear-Disk -Number $DiskNumber -RemoveData -Confirm:$false
Clear-Disk -Number $DiskNumber -RemoveData -RemoveOEM -Confirm:$false
#Check for other partitions since, apparently, Clear-Disk doesn't remove all of them
Get-Disk $disknumber | Get-Partition | Remove-Partition -Confirm:$false
$Disk = Get-Disk -Number $DiskNumber
$Disk | Set-Disk -PartitionStyle MBR
$BootPartition = $Disk | New-Partition -Size 2GB -IsActive -AssignDriveLetter
$DeployPartition = $Disk | New-Partition -UseMaximumSize -AssignDriveLetter
Format-Volume -Partition $BootPartition -FileSystem FAT32 -NewFileSystemLabel "Boot" -Confirm:$false
Format-Volume -Partition $DeployPartition -FileSystem NTFS -NewFileSystemLabel "Deploy" -Confirm:$false
}
WriteLog 'Partitioning USB Drive'
Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $DiskNumber | Out-null
WriteLog 'Done'
# Mount the ISO and copy the contents to the boot partition
$BootPartitionDriveLetter = (get-volume -FileSystemLabel Boot).DriveLetter + ":\"
$ISOMountPoint = (Mount-DiskImage -ImagePath "$BuildUSBPath\WinPE_FFU_Deploy.iso" -PassThru | Get-Volume).DriveLetter + ":\"
WriteLog "Copying WinPE files to $BootPartitionDriveLetter"
Copy-Item -Path "$ISOMountPoint\*" -Destination $BootPartitionDriveLetter -Recurse -Force | Out-Null
Dismount-DiskImage -ImagePath "$BuildUSBPath\WinPE_FFU_Deploy.iso" | Out-Null
# Copy FFU files if switch is provided
if ($CopyFFU.IsPresent) { if ($CopyFFU.IsPresent) {
WriteLog 'Copying FFU files'
$DeployPartitionDriveLetter = (get-volume -FileSystemLabel Deploy).DriveLetter + ":\"
$FFUFiles = Get-ChildItem -Path "$BuildUSBPath\FFU" -Filter "*.ffu" $FFUFiles = Get-ChildItem -Path "$BuildUSBPath\FFU" -Filter "*.ffu"
if ($FFUFiles.Count -eq 1) { if ($FFUFiles.Count -eq 1) {
WriteLog "Copying $($FFUFiles.FullName) to $DeployPartitionDriveLetter this could take a few minutes" $SelectedFFUFile = $FFUFiles.FullName
Copy-Item -Path $FFUFiles.FullName -Destination $DeployPartitionDriveLetter -Force | Out-Null
Writelog 'Copy complete'
} }
elseif ($FFUFiles.Count -gt 1) { elseif ($FFUFiles.Count -gt 1) {
WriteLog "Multiple FFU files found:" WriteLog 'Found multiple FFU files'
Write-Host "Multiple FFU files found:"
for ($i = 0; $i -lt $FFUFiles.Count; $i++) { for ($i = 0; $i -lt $FFUFiles.Count; $i++) {
WriteLog ("{0}: {1}" -f ($i + 1), $FFUFiles[$i].Name) WriteLog ("{0}: {1}" -f ($i + 1), $FFUFiles[$i].Name)
Write-Host ("{0}: {1}" -f ($i + 1), $FFUFiles[$i].Name)
} }
WriteLog "A: Copy all FFU files"
Write-Host "A: Copy all FFU files"
$inputChoice = Read-Host "Enter the number corresponding to the FFU file you want to copy or 'A' to copy all FFU files" $inputChoice = Read-Host "Enter the number corresponding to the FFU file you want to copy or 'A' to copy all FFU files"
if ($inputChoice -eq 'A') { if ($inputChoice -eq 'A') {
WriteLog "Copying All FFU files to $DeployPartitionDriveLetter this could take a few minutes" $SelectedFFUFile = $FFUFiles.FullName
Write-Host "Copying All FFU files to $DeployPartitionDriveLetter this could take a few minutes"
Copy-Item -Path $FFUFiles.FullName -Destination $DeployPartitionDriveLetter -Force | Out-Null
Writelog 'Copy complete'
Write-Host 'Copy complete'
} }
elseif ($inputChoice -ge 1 -and $inputChoice -le $FFUFiles.Count) { elseif ($inputChoice -ge 1 -and $inputChoice -le $FFUFiles.Count) {
$selectedIndex = $inputChoice - 1 $selectedIndex = $inputChoice - 1
WriteLog "Copying $($FFUFiles[$selectedIndex].FullName) to $DeployPartitionDriveLetter this could take a few minutes" $SelectedFFUFile = $FFUFiles[$selectedIndex].FullName
Write-Host "Copying $($FFUFiles[$selectedIndex].FullName) to $DeployPartitionDriveLetter this could take a few minutes"
Copy-Item -Path $FFUFiles[$selectedIndex].FullName -Destination $DeployPartitionDriveLetter -Force | Out-Null
Writelog 'Copy complete'
Write-Host 'Copy complete'
}
else {
WriteLog "Invalid choice. No FFU file copied"
Write-Host 'Invalid choice. No FFU file copied'
} }
WriteLog "$SelectedFFUFile was selected"
} }
else { else {
WriteLog "No FFU files found in the current directory." WriteLog "No FFU files found in the current directory."
} }
} }
WriteLog "USB drive prepared successfully." foreach ($USBDrive in $USBDrives) {
$Counter++
WriteLog "Formatting USB drive $Counter out of $USBDrivesCount"
$DiskNumber = $USBDrive.DeviceID.Replace("\\.\PHYSICALDRIVE", "")
WriteLog "Physical Disk number is $DiskNumber for USB drive $Counter out of $USBDrivesCount"
$ScriptBlock = {
param($DiskNumber)
Clear-Disk -Number $DiskNumber -RemoveData -RemoveOEM -Confirm:$false
Get-Disk $DiskNumber | Get-Partition | Remove-Partition
$Disk = Get-Disk -Number $DiskNumber
$Disk | Set-Disk -PartitionStyle MBR
$BootPartition = $Disk | New-Partition -Size 2GB -IsActive -AssignDriveLetter
$DeployPartition = $Disk | New-Partition -UseMaximumSize -AssignDriveLetter
Format-Volume -Partition $BootPartition -FileSystem FAT32 -NewFileSystemLabel "TempBoot" -Confirm:$false
Format-Volume -Partition $DeployPartition -FileSystem NTFS -NewFileSystemLabel "TempDeploy" -Confirm:$false
}
WriteLog 'Partitioning USB Drive'
Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $DiskNumber | Out-null
WriteLog 'Done'
$BootPartitionDriveLetter = (Get-WmiObject -Class win32_volume -Filter "Label='TempBoot' AND DriveType=2 AND DriveLetter IS NOT NULL").Name
$ISOMountPoint = (Mount-DiskImage -ImagePath "$BuildUSBPath\WinPE_FFU_Deploy.iso" -PassThru | Get-Volume).DriveLetter + ":\"
WriteLog "Copying WinPE files to $BootPartitionDriveLetter"
robocopy "$ISOMountPoint" "$BootPartitionDriveLetter" /E /COPYALL /R:5 /W:5 /J
Dismount-DiskImage -ImagePath "$BuildUSBPath\WinPE_FFU_Deploy.iso" | Out-Null
if ($CopyFFU.IsPresent) {
if ($null -ne $SelectedFFUFile) {
$DeployPartitionDriveLetter = (Get-WmiObject -Class win32_volume -Filter "Label='TempDeploy' AND DriveType=2 AND DriveLetter IS NOT NULL").Name
if ($SelectedFFUFile -is [array]) {
WriteLog "Copying multiple FFU files to $DeployPartitionDriveLetter. This could take a few minutes."
foreach ($FFUFile in $SelectedFFUFile) {
robocopy $(Split-Path $FFUFile -Parent) $DeployPartitionDriveLetter $(Split-Path $FFUFile -Leaf) /COPYALL /R:5 /W:5 /J
}
}
else {
WriteLog ("Copying " + $SelectedFFUFile + " to $DeployPartitionDriveLetter. This could take a few minutes.")
robocopy $(Split-Path $SelectedFFUFile -Parent) $DeployPartitionDriveLetter $(Split-Path $SelectedFFUFile -Leaf) /COPYALL /R:5 /W:5 /J
}
}
else {
WriteLog "No FFU file selected. Skipping copy."
}
}
Set-Volume -FileSystemLabel "TempBoot" -NewFileSystemLabel "Boot"
Set-Volume -FileSystemLabel "TempDeploy" -NewFileSystemLabel "Deploy"
if ($USBDrivesCount -gt 1) {
& mountvol $BootPartitionDriveLetter /D
& mountvol $DeployPartitionDriveLetter /D
}
WriteLog "Drive $counter completed"
}
WriteLog "USB Drives completed"
}
function Get-FFUEnvironment {
WriteLog 'Dirty.txt file detected. Last run did not complete succesfully. Will clean environment'
# Check for MSFT Virtual disks where location contains FFUDevelopment in the path
$disks = Get-Disk -FriendlyName *virtual*
foreach ($disk in $disks) {
$diskNumber = $disk.Number
$vhdLocation = $disk.Location
if ($vhdLocation -like "*FFUDevelopment*") {
WriteLog "Dismounting Virtual Disk $diskNumber with Location $vhdLocation"
Dismount-ScratchVhdx -VhdxPath $vhdLocation
$parentFolder = Split-Path -Parent $vhdLocation
WriteLog "Removing folder $parentFolder"
Remove-Item -Path $parentFolder -Recurse -Force
}
}
# Check for mounted DiskImages
$volumes = Get-Volume | Where-Object { $_.DriveType -eq 'CD-ROM' }
foreach ($volume in $volumes) {
$letter = $volume.DriveLetter
WriteLog "Dismounting DiskImage for volume $letter"
Get-Volume $letter | Get-DiskImage | Dismount-DiskImage | Out-Null
WriteLog "Dismounting complete"
}
# Remove unused mountpoints
WriteLog 'Remove unused mountpoints'
Invoke-Process cmd "/c mountvol /r"
WriteLog 'Removal complete'
# Check for content in the VM folder and delete any folders that start with _FFU-
$folders = Get-ChildItem -Path $VMLocation -Directory
foreach ($folder in $folders) {
if ($folder.Name -like '_FFU-*') {
WriteLog "Removing folder $($folder.FullName)"
Remove-Item -Path $folder.FullName -Recurse -Force
}
}
# Remove orphaned mounted images
$mountedImages = Get-WindowsImage -Mounted
if ($mountedImages) {
foreach ($image in $mountedImages) {
$mountPath = $image.Path
WriteLog "Dismounting image at $mountPath"
Dismount-WindowsImage -Path $mountPath -discard | Out-null
WriteLog "Successfully dismounted image at $mountPath"
}
}
# Remove Mount folder if it exists
if (Test-Path -Path "$FFUDevelopmentPath\Mount") {
WriteLog "Remove $FFUDevelopmentPath\Mount folder"
Remove-Item -Path "$FFUDevelopmentPath\Mount" -Recurse -Force
WriteLog 'Folder removed'
}
#Clear any corrupt Windows mount points
WriteLog 'Clearing any corrupt Windows mount points'
Clear-WindowsCorruptMountPoint | Out-null
WriteLog 'Complete'
#Clean up registry
if (Test-Path -Path 'HKLM:\FFU'){
Writelog 'Found HKLM:\FFU, removing it'
Invoke-Process reg "unload HKLM\FFU"
}
Writelog 'Removing dirty.txt file'
Remove-Item -Path "$FFUDevelopmentPath\dirty.txt" -Force
WriteLog "Cleanup complete"
} }
###END FUNCTIONS ###END FUNCTIONS
@@ -1302,6 +1397,11 @@ catch {
throw $_ throw $_
} }
#Check if environment is dirty
If(Test-Path -Path "$FFUDevelopmentPath\dirty.txt"){
Get-FFUEnvironment
}
#Create apps ISO for Office and/or 3rd party apps #Create apps ISO for Office and/or 3rd party apps
if ($InstallApps) { if ($InstallApps) {
try { try {
@@ -1341,6 +1441,9 @@ if ($InstallApps) {
#Create VHDX #Create VHDX
try { try {
#Create dirty.txt file to track if environment is dirty or clean
New-Item -Path .\ -Name "dirty.txt" -ItemType "file" | Out-Null
if ($ISOPath) { if ($ISOPath) {
$wimPath = Get-WimFromISO $wimPath = Get-WimFromISO
} }
@@ -1549,5 +1652,7 @@ If ($BuildUSBDrive) {
throw $_ throw $_
} }
} }
#Clean up dirty.txt file
Remove-Item -Path .\dirty.txt -Force | out-null
Write-Host "Script complete" Write-Host "Script complete"
WriteLog "Script complete" WriteLog "Script complete"
@@ -60,9 +60,7 @@ Remove-Variable DisplayVersion
Remove-Variable Office Remove-Variable Office
reg unload "HKLM\FFU" reg unload "HKLM\FFU"
#This prevents Critical Process Died errors you can have during deployment of the FFU - may not happen during capture from WinPE, but adding here to be consistent with VHDX capture #This prevents Critical Process Died errors you can have during deployment of the FFU - may not happen during capture from WinPE, but adding here to be consistent with VHDX capture
WriteLog 'Sleep 15 seconds to allow registry to completely unload' Start-sleep 60
Start-sleep 15
Start-Process -FilePath dism.exe -ArgumentList $dismArgs -Wait -PassThru -ErrorAction Stop | Out-Null Start-Process -FilePath dism.exe -ArgumentList $dismArgs -Wait -PassThru -ErrorAction Stop | Out-Null
#Copy DISM log to Host #Copy DISM log to Host
xcopy X:\Windows\logs\dism\dism.log W:\ /Y | Out-Null xcopy X:\Windows\logs\dism\dism.log W:\ /Y | Out-Null
@@ -117,7 +117,7 @@ $LogFileName = 'ScriptLog.txt'
$USBDrive = Get-USBDrive $USBDrive = Get-USBDrive
New-item -Path $USBDrive -Name $LogFileName -ItemType "file" -Force | Out-Null New-item -Path $USBDrive -Name $LogFileName -ItemType "file" -Force | Out-Null
$LogFile = $USBDrive + $LogFilename $LogFile = $USBDrive + $LogFilename
$version = '2309.1' $version = '2309.2'
WriteLog 'Begin Logging' WriteLog 'Begin Logging'
WriteLog "Script version: $version" WriteLog "Script version: $version"