Compare commits

..

52 Commits

Author SHA1 Message Date
rbalsleyMSFT 47cd0deb03 Merge pull request #77 from rbalsleyMSFT/2409.2
2409.2
2024-09-17 13:54:58 -07:00
rbalsleyMSFT 378941cd5c Two fixes
- Fixed an issue with UWP apps downloaded via Winget weren't being fully installed. Added /StubPackageOption:installfull to the dism command
- Fixed an issue with Surface Drivers not downloading
2024-09-17 13:50:16 -07:00
rbalsleyMSFT 60d147c71d Update README.md 2024-09-10 11:45:44 -07:00
rbalsleyMSFT cd36150ddc Merge pull request #71 from rbalsleyMSFT/2409.1
2409.1
2024-09-10 11:44:49 -07:00
rbalsleyMSFT 198a544dbb update change log 2024-09-10 11:44:12 -07:00
rbalsleyMSFT 40616776eb - Added VMHostIPAddress and VMSwitchName validation to validate the IP address matches the VMSwitchName 2024-09-07 09:53:14 -07:00
rbalsleyMSFT 20c9cf8ab3 Merge pull request #65 from HedgeComp/Time-to-Complete-Hours
Time To Complete Shows Hours if Needed
2024-09-06 11:26:54 -07:00
rbalsleyMSFT 17558f86aa Merge pull request #64 from HedgeComp/OneDrive-Silent
Silently Install Onedrive
2024-09-06 11:26:15 -07:00
rbalsleyMSFT 7408dbb435 Merge branch '2409.1' of https://github.com/rbalsleyMSFT/FFU into 2409.1 2024-09-06 11:24:21 -07:00
rbalsleyMSFT 9c1fc59af9 - Added new variables for the PPKG, Unattend, Autopilot, and PEDrivers validation 2024-09-06 11:24:16 -07:00
HedgeComp 31c785b5da Update BuildFFUVM.ps1
Add Hours to Total Time to complete only if greater than 1 hour
2024-09-06 13:00:09 -04:00
HedgeComp 5b93135ebb Update BuildFFUVM.ps1
Add Silent switch install to Onedrivesetup.exe
2024-09-06 12:57:36 -04:00
rbalsleyMSFT 5f4cf0c66e Merge pull request #60 from zehadialam/2409.1
Fix for Missing Windows Boot Manager Entry
2024-09-06 09:34:11 -07:00
Zehadi Alam ddbf2b0339 Use bcdedit to set Windows Boot Manager and default Windows boot loader to be first in the display order of UEFI firmware 2024-09-05 17:57:35 -04:00
rbalsleyMSFT e62d481405 - Remove ValidateScript on InstallDrivers and break it out in a validation block so -Make and -Model can be specified anywhere in the command line
- Check for Prefixes.txt file and copy to the USB drive if it exists
- Perform better validation for PPKG, Unattend, Autopilot json, and drivers
- Comment out the Windows Security Platform update as the file has been removed from the MU Catalog.
2024-09-04 17:05:06 -07:00
rbalsleyMSFT 6c07ac8595 Merge branch '2409.1' of https://github.com/rbalsleyMSFT/FFU into 2409.1 2024-09-04 13:20:38 -07:00
rbalsleyMSFT 7d74feec0c - Fix an issue with removal of Defender/OneDrive/Edge after FFU is complete
- Migrate Winget downloads to use Export-WingetPackage cmdlet as per issue Known Issue: Winget downloads fail on Non-English OS #50
- Add better logging when unable to find HDD when applying FFU
2024-09-04 13:20:35 -07:00
rbalsleyMSFT 6b2a4bcb27 Merge pull request #51 from HedgeComp/2408.2
Allow Preview CU update
2024-09-04 13:08:58 -07:00
rbalsleyMSFT 6da9ece0d8 Merge pull request #54 from w0/main
use ValidateSet for WindowsSKU
2024-08-15 18:59:01 -07:00
w0 dc4438dcf9 use ValidateSet for WindowsSKU 2024-08-15 20:11:41 -05:00
rbalsleyMSFT e250e2a130 Changed some logging when winget apps can't be found 2024-08-13 16:11:36 -07:00
Doctair dad51fdf80 updated Docs to relect new $UpdatePreviewCU Parameter 2024-08-12 13:15:16 -04:00
Doctair d60b0301c5 Remove a temp copy of BUildScript 2024-08-12 10:15:45 -04:00
Doctair db3e09650a Add new Parameter for Installing Preview CU from
Mircosoft Update Catalog. Recent Windows Pro
not Auto Activating to Enterprise License Bug speared
this idea as its resoleve in lastes Prieview CU.

Parameter is default $False but if set to $true will install
Preivew CU and take precendence over $UpdateLastestCU.
2024-08-12 10:07:41 -04:00
rbalsleyMSFT bcb9911cd0 Small update to fix a logging issue with script run time duration 2024-08-07 13:01:26 -07:00
rbalsleyMSFT 67e3035c38 Merge pull request #47 from rbalsleyMSFT/2408.1
2408.1
2024-08-06 17:57:42 -07:00
rbalsleyMSFT 94dd256889 update docs 2024-08-06 17:55:17 -07:00
rbalsleyMSFT cc383c84cb update docs 2024-08-06 17:51:53 -07:00
rbalsleyMSFT b20b614f5e update changelog.md and ApplyFFU.ps1 to 2408.1 2024-08-06 17:39:13 -07:00
rbalsleyMSFT 31984e104e update readme.md 2024-08-06 15:52:35 -07:00
rbalsleyMSFT 94f74a194d update readme 2024-08-06 15:50:32 -07:00
rbalsleyMSFT eaa58e6804 update readme 2024-08-06 15:49:26 -07:00
rbalsleyMSFT 351c87ab96 update readme 2024-08-06 15:47:49 -07:00
rbalsleyMSFT 13e2765c3f update readme 2024-08-06 15:46:42 -07:00
rbalsleyMSFT c049840baa update readme.md 2024-08-06 15:45:44 -07:00
rbalsleyMSFT e1ab74e5a3 Refactored Get-USBDrives and New-DeploymentUSB to use tables when displaying multiple drives or FFUs to the user. Fixed an issue with cleaning up InstallAppsandSysprep.cmd. Re-wrote Readme.md. 2024-08-06 15:43:23 -07:00
rbalsleyMSFT 02d858f27f Merge pull request #45 from HedgeComp/2408.1
2408.1
2024-08-02 11:57:23 -07:00
rbalsleyMSFT 1d8e9f352d Merge branch '2408.1' of https://github.com/rbalsleyMSFT/FFU into 2408.1 2024-08-02 10:54:14 -07:00
rbalsleyMSFT 7b59e3d0ec Fixed an issue with clean up of Defender, OneDrive, and Edge. Fixed an issue with the formatting of InstallAppsandSysprep.cmd file. 2024-08-02 10:53:50 -07:00
Doctair 213da61389 Fix REad-Host Prompt message for FFU selecion 2024-08-02 12:20:17 -04:00
Doctair 9de55eb186 Comment Better 2024-08-02 12:11:54 -04:00
Doctair e3bec5ff45 Clean up some Remmed Lines and Added some Comments
for explanation
2024-08-02 12:02:58 -04:00
Doctair 1bfc4735d3 Sync arm64 changes and Rem $Capture False 2024-08-02 11:52:51 -04:00
Doctair 49b742b47b Added Logic for FFU Selection to Check for Integer
or 'A'

Fix Write Message to Display all FFUs found if not
using -Verbose, currently displays nothing so numbering
of FFUs is unkown for selection prompt

Added Simple total Runtime and Start and Finish Time
2024-08-02 11:35:18 -04:00
rbalsleyMSFT 7f79e50f72 Merge pull request #44 from HedgeComp/2408.1
External Disk Selection
2024-07-31 10:56:55 -07:00
Doctair 39b9d06d21 Correct Logic for Dirve letters and add Dirve Info
to the write-host selection for Disks.
2024-07-30 16:11:07 -04:00
Doctair 047881934a Add Logic to catch the disk selection of USB
External drives so that it will not accept a Letter
2024-07-30 13:57:54 -04:00
rbalsleyMSFT 689808eca7 commented some variables 2024-07-26 16:22:31 -07:00
rbalsleyMSFT 70571a3b49 Fixed an issue where Efisys_noprompt.bin was being used for deployment media. This should only be used for capture media 2024-07-26 16:04:53 -07:00
rbalsleyMSFT 06138ebaff Added $PromptExternalHardDiskMedia as a new variable defaulted to True to prevent accidentental data loss if external hard disks are detected 2024-07-24 17:16:30 -07:00
rbalsleyMSFT 81a3b10a06 added $AllowExternalHardDiskMedia variable and modified USB drive creation code to allow for External hard disks 2024-07-24 10:37:41 -07:00
rbalsleyMSFT 8ba88f4626 Fixed an issue with RAW disks and Clear-Disk 2024-07-23 16:31:16 -07:00
8 changed files with 1335 additions and 309 deletions
+45
View File
@@ -1,5 +1,50 @@
# Change Log
## **2409.1**
### Fixes
- Fix an issue with removal of Defender/OneDrive/Edge after FFU is complete
- Migrate Winget downloads to use [Export-WingetPackage cmdlet](https://github.com/microsoft/winget-cli/blob/master/doc/specs/%23658%20-%20WinGet%20Download.md#winget-powershell-cmdlet) as per issue #50
- Add support for preview updates https://github.com/rbalsleyMSFT/FFU/pull/51 - thanks to @HedgeComp
- Refactor validation of Unattend/prefixes, PPKG, Autopilot to check for these files early in the process, similar to how we check for drivers
- Add better logging when unable to find HDD when applying FFU. Will inform to add WinPE drivers to Deployment Media if HDD not found.
- Remove ValidateScript on InstallDrivers and break it out in a validation block so -Make and -Model can be specified anywhere in the command line
- Add validation for VMHostIPAddress and VMSwtichName and inform the user if these don't match. Should prevent issues where the FFU isn't getting created.
- Removed installation of the Windows Security Platform Update as it has been removed from the MU Catalog. See issue #58
- Thanks to w0 for PR #54 to change the validation set for WindowsSKU
- Thanks to @zehadialam for PR #60 to fix an issue with Windows boot loader for certain devices where Windows Boot Manager is not the first boot entry after the FFU is applied.
- Thanks to @HedgeComp for PR #64 and PR #65
## **2408.1**
### External Drive Support
Up until now, the USB build process has supported using drives identified by Windows as removable drives. Most USB sticks will identify as removable, however faster drives may show up as external hard disk media. You may also have a smaller, portable SSD drive that you'd like to use for imaging since these are typically much faster than regular USB 3.x thumb drives.
In adding this support, I do realize that there is potential for data loss for those that might have external hard drives attached to their machines.
To handle this, with help from [HedgeComp](https://github.com/HedgeComp), we've refactored the `Get-USBDrives` function. Two new variables have been created:
| Parameter | Type | Description |
| --------------------------- | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AllowExternalHardDiskMedia | Bool | If `$true`, will allow the use of media identified as External Hard Disk media via WMI class Win32_DiskDrive. Default is not defined. |
| PromptExternalHardDiskMedia | Bool | If `$true` and AllowExternalHardDiskMedia is `$true`, the script will prompt to select which drive to use. When set to `$true`, only a single drive will be created. If `$false`, the script won't prompt for which external hard disk to use and can use multiple external hard disks, similar to how removable USB drives function. |
By default, this functionality won't effect previous USB drive creation behavior. However if you want to take advantage of the new functionality, set `-AllowExternalHardDiskMedia $true`
Fixes/misc
- Fixed a display issue where if multiple FFU files were in the FFU folder, the script wouldn't display which FFUs to choose from when running the script without -verbose. This will now display a table with the last modified date whether you run with the -verbose switch or not.
- Added start/end/duration time (thanks [HedgeComp](https://github.com/HedgeComp))
- Fixed an issue where deployment media wasn't prompting for a key to be pressed as expected
- Fixed an issue when creating the USB drive and the drive had a RAW partition style that clear-disk would generate an error
- Cleaned up some commented code
- Added Create-PEMedia.ps1 as a helper script to quickly generate Deploy or Capture media
- Fixed an issue with clean up of Defender/OneDrive/Edge
- Fixed an issue with the formatting of InstallAppsandSysprep.cmd file
- Updated parameter documentation in the script to include newly added parameters
## **2407.1**
This is another major release that includes:
@@ -30,11 +30,8 @@ for /d %%D in ("%basepath%\*") do (
)
)
)
@REM for %%F in ("!appfolder!\*.xml") do (
@REM set "licensefile=%%F"
@REM )
if defined mainpackage (
set "dism_command=DISM /Online /Add-ProvisionedAppxPackage /PackagePath:"!mainpackage!""
set "dism_command=DISM /Online /Add-ProvisionedAppxPackage /PackagePath:"!mainpackage!" /Region:all /StubPackageOption:installfull"
if exist "!dependenciesfolder!" (
for %%G in ("!dependenciesfolder!\*") do (
set "dism_command=!dism_command! /DependencyPackagePath:"%%G""
@@ -48,7 +45,6 @@ for /d %%D in ("%basepath%\*") do (
) else (
set "dism_command=!dism_command! /SkipLicense"
)
set "dism_command=!dism_command! /Region:All"
echo !dism_command!
!dism_command!
)
File diff suppressed because it is too large Load Diff
+209
View File
@@ -0,0 +1,209 @@
param (
[string]$FFUDevelopmentPath = $PSScriptRoot,
[string]$adkPath = 'C:\Program Files (x86)\Windows Kits\10\',
[string]$WindowsArch = 'x64',
[bool]$CopyPEDrivers = $false,
[string]$CaptureISO = "$PSScriptRoot\WinPE_FFU_Capture_x64.iso",
[string]$DeployISO = "$PSScriptRoot\WinPE_FFU_Deploy_x64.iso",
[string]$LogFile = "$PSScriptRoot\Create-PEMedia.log",
[bool]$Capture,
[bool]$Deploy = $true
)
function WriteLog($LogText) {
Add-Content -path $LogFile -value "$((Get-Date).ToString()) $LogText" -Force -ErrorAction SilentlyContinue
Write-Verbose $LogText
}
function Invoke-Process {
[CmdletBinding(SupportsShouldProcess)]
param
(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[Parameter()]
[ValidateNotNullOrEmpty()]
[string]$ArgumentList
)
$ErrorActionPreference = 'Stop'
try {
$stdOutTempFile = "$env:TEMP\$((New-Guid).Guid)"
$stdErrTempFile = "$env:TEMP\$((New-Guid).Guid)"
$startProcessParams = @{
FilePath = $FilePath
ArgumentList = $ArgumentList
RedirectStandardError = $stdErrTempFile
RedirectStandardOutput = $stdOutTempFile
Wait = $true;
PassThru = $true;
NoNewWindow = $true;
}
if ($PSCmdlet.ShouldProcess("Process [$($FilePath)]", "Run with args: [$($ArgumentList)]")) {
$cmd = Start-Process @startProcessParams
$cmdOutput = Get-Content -Path $stdOutTempFile -Raw
$cmdError = Get-Content -Path $stdErrTempFile -Raw
if ($cmd.ExitCode -ne 0) {
if ($cmdError) {
throw $cmdError.Trim()
}
if ($cmdOutput) {
throw $cmdOutput.Trim()
}
}
else {
if ([string]::IsNullOrEmpty($cmdOutput) -eq $false) {
WriteLog $cmdOutput
}
}
}
}
catch {
#$PSCmdlet.ThrowTerminatingError($_)
WriteLog $_
Write-Host "Script failed - $Logfile for more info"
throw $_
}
finally {
Remove-Item -Path $stdOutTempFile, $stdErrTempFile -Force -ErrorAction Ignore
}
}
function New-PEMedia {
param (
[Parameter()]
[bool]$Capture,
[Parameter()]
[bool]$Deploy
)
#Need to use the Demployment and Imaging tools environment to create winPE media
$DandIEnv = "$adkPath`Assessment and Deployment Kit\Deployment Tools\DandISetEnv.bat"
$WinPEFFUPath = "$FFUDevelopmentPath\WinPE"
If (Test-path -Path "$WinPEFFUPath") {
WriteLog "Removing old WinPE path at $WinPEFFUPath"
Remove-Item -Path "$WinPEFFUPath" -Recurse -Force | out-null
}
WriteLog "Copying WinPE files to $WinPEFFUPath"
if($WindowsArch -eq 'x64') {
& cmd /c """$DandIEnv"" && copype amd64 $WinPEFFUPath" | Out-Null
}
elseif($WindowsArch -eq 'arm64') {
& cmd /c """$DandIEnv"" && copype arm64 $WinPEFFUPath" | Out-Null
}
#Invoke-Process cmd "/c ""$DandIEnv"" && copype amd64 $WinPEFFUPath"
WriteLog 'Files copied successfully'
WriteLog 'Mounting WinPE media to add WinPE optional components'
Mount-WindowsImage -ImagePath "$WinPEFFUPath\media\sources\boot.wim" -Index 1 -Path "$WinPEFFUPath\mount" | Out-Null
WriteLog 'Mounting complete'
$Packages = @(
"WinPE-WMI.cab",
"en-us\WinPE-WMI_en-us.cab",
"WinPE-NetFX.cab",
"en-us\WinPE-NetFX_en-us.cab",
"WinPE-Scripting.cab",
"en-us\WinPE-Scripting_en-us.cab",
"WinPE-PowerShell.cab",
"en-us\WinPE-PowerShell_en-us.cab",
"WinPE-StorageWMI.cab",
"en-us\WinPE-StorageWMI_en-us.cab",
"WinPE-DismCmdlets.cab",
"en-us\WinPE-DismCmdlets_en-us.cab"
)
if($WindowsArch -eq 'x64'){
$PackagePathBase = "$adkPath`Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\WinPE_OCs\"
}
elseif($WindowsArch -eq 'arm64'){
$PackagePathBase = "$adkPath`Assessment and Deployment Kit\Windows Preinstallation Environment\arm64\WinPE_OCs\"
}
foreach ($Package in $Packages) {
$PackagePath = Join-Path $PackagePathBase $Package
WriteLog "Adding Package $Package"
Add-WindowsPackage -Path "$WinPEFFUPath\mount" -PackagePath $PackagePath | Out-Null
WriteLog "Adding package complete"
}
If ($Capture) {
WriteLog "Copying $FFUDevelopmentPath\WinPECaptureFFUFiles\* to WinPE capture media"
Copy-Item -Path "$FFUDevelopmentPath\WinPECaptureFFUFiles\*" -Destination "$WinPEFFUPath\mount" -Recurse -Force | out-null
WriteLog "Copy complete"
#Remove Bootfix.bin - for BIOS systems, shouldn't be needed, but doesn't hurt to remove for our purposes
#Remove-Item -Path "$WinPEFFUPath\media\boot\bootfix.bin" -Force | Out-null
# $WinPEISOName = 'WinPE_FFU_Capture.iso'
$WinPEISOFile = $CaptureISO
# $Capture = $false
}
If ($Deploy) {
WriteLog "Copying $FFUDevelopmentPath\WinPEDeployFFUFiles\* to WinPE deploy media"
Copy-Item -Path "$FFUDevelopmentPath\WinPEDeployFFUFiles\*" -Destination "$WinPEFFUPath\mount" -Recurse -Force | Out-Null
WriteLog 'Copy complete'
#If $CopyPEDrivers = $true, add drivers to WinPE media using dism
if ($CopyPEDrivers) {
WriteLog "Adding drivers to WinPE media"
try {
Add-WindowsDriver -Path "$WinPEFFUPath\Mount" -Driver "$FFUDevelopmentPath\PEDrivers" -Recurse -ErrorAction SilentlyContinue | Out-null
}
catch {
WriteLog 'Some drivers failed to be added to the FFU. This can be expected. Continuing.'
}
WriteLog "Adding drivers complete"
}
# $WinPEISOName = 'WinPE_FFU_Deploy.iso'
$WinPEISOFile = $DeployISO
# $Deploy = $false
}
WriteLog 'Dismounting WinPE media'
Dismount-WindowsImage -Path "$WinPEFFUPath\mount" -Save | Out-Null
WriteLog 'Dismount complete'
#Make ISO
if ($WindowsArch -eq 'x64') {
$OSCDIMGPath = "$adkPath`Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg"
}
elseif ($WindowsArch -eq 'arm64') {
$OSCDIMGPath = "$adkPath`Assessment and Deployment Kit\Deployment Tools\arm64\Oscdimg"
}
$OSCDIMG = "$OSCDIMGPath\oscdimg.exe"
WriteLog "Creating WinPE ISO at $WinPEISOFile"
# & "$OSCDIMG" -m -o -u2 -udfver102 -bootdata:2`#p0,e,b$OSCDIMGPath\etfsboot.com`#pEF,e,b$OSCDIMGPath\Efisys_noprompt.bin $WinPEFFUPath\media $FFUDevelopmentPath\$WinPEISOName | Out-null
if($WindowsArch -eq 'x64'){
if($Capture){
$OSCDIMGArgs = "-m -o -u2 -udfver102 -bootdata:2`#p0,e,b`"$OSCDIMGPath\etfsboot.com`"`#pEF,e,b`"$OSCDIMGPath\Efisys_noprompt.bin`" `"$WinPEFFUPath\media`" `"$WinPEISOFile`""
}
if($Deploy){
$OSCDIMGArgs = "-m -o -u2 -udfver102 -bootdata:2`#p0,e,b`"$OSCDIMGPath\etfsboot.com`"`#pEF,e,b`"$OSCDIMGPath\Efisys.bin`" `"$WinPEFFUPath\media`" `"$WinPEISOFile`""
}
}
elseif($WindowsArch -eq 'arm64'){
if($Capture){
$OSCDIMGArgs = "-m -o -u2 -udfver102 -bootdata:1`#pEF,e,b`"$OSCDIMGPath\Efisys_noprompt.bin`" `"$WinPEFFUPath\media`" `"$WinPEISOFile`""
}
if($Deploy){
$OSCDIMGArgs = "-m -o -u2 -udfver102 -bootdata:1`#pEF,e,b`"$OSCDIMGPath\Efisys.bin`" `"$WinPEFFUPath\media`" `"$WinPEISOFile`""
}
}
Invoke-Process $OSCDIMG $OSCDIMGArgs
WriteLog "ISO created successfully"
WriteLog "Cleaning up $WinPEFFUPath"
Remove-Item -Path "$WinPEFFUPath" -Recurse -Force
WriteLog 'Cleanup complete'
}
if($Capture){
New-PEMedia -Capture $Capture
}
if($Deploy){
New-PEMedia -Deploy $Deploy
}
Binary file not shown.
+12 -24
View File
@@ -14,10 +14,6 @@ function Get-USBDrive(){
return $USBDriveLetter
}
# function Get-HardDrive(){
# $DeviceID = (Get-WmiObject -Class 'Win32_DiskDrive' | Where-Object {$_.MediaType -eq 'Fixed hard disk media' -and $_.Model -ne 'Microsoft Virtual Disk'}).DeviceID
# return $DeviceID
# }
function Get-HardDrive(){
$SystemInfo = Get-WmiObject -Class 'Win32_ComputerSystem'
$Manufacturer = $SystemInfo.Manufacturer
@@ -127,33 +123,23 @@ function Invoke-Process {
}
# This function can be used in instances where battery level might matter (e.g. installing firmware for Surface). The problem is that WinPE doesn't have
# a driver for the battery installed, so you'll need to inject drivers, which can be tricky because just injecting the battery driver might not be enough,
# you might also need other drivers that the battery driver is dependent on.
# function Get-Battery(){
# while (($BattLev = (Get-CimInstance win32_battery).EstimatedChargeRemaining) -lt "35")
# {
# WriteLog "Battery is currently at $BattLev`%. Waiting for 35`% to proceed..."
# Write-Host "Battery is currently at $BattLev`%. Waiting for 35`% to proceed..."
# Start-Sleep 60
# }
# WriteLog "Battery level is $BattLev `%, which is greater than 35'% applying FFU"
# Write-Host "Battery level is $BattLev `%, which is greater than 35'% applying FFU"
# }
#Get USB Drive and create log file
$LogFileName = 'ScriptLog.txt'
$USBDrive = Get-USBDrive
New-item -Path $USBDrive -Name $LogFileName -ItemType "file" -Force | Out-Null
$LogFile = $USBDrive + $LogFilename
$version = '2407.1'
$version = '2409.1'
WriteLog 'Begin Logging'
WriteLog "Script version: $version"
#Find PhysicalDrive
# $PhysicalDeviceID = Get-HardDrive
$hardDrive = Get-HardDrive
if($hardDrive -eq $null){
WriteLog 'No hard drive found. Exiting'
WriteLog 'Try adding storage drivers to the PE boot image (you can re-create your FFU and USB drive and add the PE drivers to the PEDrivers folder and add -CopyPEDrivers $true to the command line, or manually add them via DISM)'
Exit
}
$PhysicalDeviceID = $hardDrive.DeviceID
$BytesPerSector = $hardDrive.BytesPerSector
WriteLog "Physical BytesPerSector is $BytesPerSector"
@@ -432,10 +418,6 @@ If (Test-Path -Path $Drivers)
Writelog 'No driver folders found'
}
}
#If you want to enable battery level checking, uncomment the line below as well as the Get-Battery function near the top of the script
#Get-Battery
#Partition drive
Writelog 'Clean Disk'
try {
@@ -572,6 +554,12 @@ If (Test-Path -Path $Drivers)
WriteLog 'Copying drivers succeeded'
}
WriteLog "Setting Windows Boot Manager to be first in the display order."
Invoke-Process bcdedit.exe "/set {fwbootmgr} displayorder {bootmgr} /addfirst"
WriteLog "Windows Boot Manager has been set to be first in the display order."
WriteLog "Setting default Windows boot loader to be first in the display order."
Invoke-Process bcdedit.exe "/set {bootmgr} displayorder {default} /addfirst"
WriteLog "The default Windows boot loader has been set to be first in the display order."
#Copy DISM log to USBDrive
WriteLog "Copying dism log to $USBDrive"
invoke-process xcopy "X:\Windows\logs\dism\dism.log $USBDrive /Y"
+101 -7
View File
@@ -1,19 +1,113 @@
# Using Full Flash Update (FFU) files to speed up Windows deployment
This repo contains the full FFU process that we use in US Education at Microsoft to help customers with large deployments of Windows as they prepare for the new school year. This process isn't limited to only large deployments at the start of the year, but is the most common.
What if you could have a Windows image that has:
This process will copy Windows in about 2-3 minutes to the target device, optionally copy drivers, provisioning packages, Autopilot, etc. School technicians have even given the USB sticks to teachers and teachers calling them their "Magic USB sticks" to quickly get student devices reimaged in the event of an issue with their Windows PC.
- The latest Windows cumulative update
- The latest .NET cumulative update
- The latest Windows Defender Platform and Definition Updates
- The latest version of Microsoft Edge
- The latest version of OneDrive (Per-Machine)
- The latest version of Microsoft 365 Apps/Office
- The latest drivers from any of the major OEMs (Dell, HP, Lenovo, Microsoft) (yes, the latest, not some out of date enterprise CAB file from years ago)
- Winget support so you can integrate any app available from Winget directly in your image
- ARM64 support for the latest Copilot+ PCs
- The ability to bring your own drivers and apps if necessary
- Custom WinRE support
While we use this in Education at Microsoft, other industries can use it as well. We esepcially see a need for something like this with partners who do re-imaging on behalf of customers. The difference in Education is that they typically have large deployments that tend to happen at the beginning of the school year and any amount of time saved is helpful. Microsoft Deployment Toolkit, Configuration Manager, and other community solutions are all great solutions, but are typically slower due to WIM deployments being file-based while FFU files are sector-based.
And the best part: it takes less than two minutes to apply the image, even with all of these updates added to the media. After setting Windows up and going through Autopilot or a provisioning package, total elapsed time ~10 minutes (depending on what Intune or your device management tool is deploying).
The Full-Flash update (FFU) process can automatically download the latest release of Windows 11, the updates mentioned above, and creates a USB drive that can be used to quickly reimage a machine.
# Updates
2407.1 has been released! Check out the changes in the new [Change Log](ChangeLog.md)
2409.1 has been released! Check out the changes in the [Change Log](ChangeLog.md)
# Getting Started
If you're not familiar with Github, you can click the Green code button above and select download zip. Extract the zip file and make sure to copy the FFUDevelopment folder to the root of your C: drive. That will make it easy to follow the guide and allow the scripts to work properly.
- Download the latest [release](https://github.com/rbalsleyMSFT/FFU/releases)
- Extract the FFUDevelopment folder from the ZIP file (recommend to C:\FFUDevelopment)
- Follow the doc: C:\FFUDevelopment\Docs\BuildDeployFFU.docx
If extracted correctly, your c:\FFUDevelopment folder should look like the following. If it does, go to c:\FFUDevelopment\Docs\BuildDeployFFU.docx to get started.
## YouTube Detailed Walkthrough
![image](https://github.com/rbalsleyMSFT/FFU/assets/53497092/5400a203-9c2e-42b2-b24c-ab8dfd922ba1)
The first 15 minutes of the following video includes a quick start demo to get started. Below the video are a list of chapters. This video was taken with the 2407.2 build. Features released after that will not be demonstrated in the video.
[![Reimage Windows Fast with Full-Flash Update (FFU))](https://img.youtube.com/vi/rqXRbgeeKSQ/maxresdefault.jpg)](https://www.youtube.com/watch?v=rqXRbgeeKSQ "Reimage Windows Fast with Full-Flash Update (FFU))")
Chapters:
[00:00](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=0s) Begin
[03:21](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=201s) Quick Start Prereqs
[07:19](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=439s) Quick Start Demo
[14:12](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=852s) Script Parameters
[17:22](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=1042s) Obtaining Windows Media
[25:55](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=1555s) Adding Applications
[26:59](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=1619s) Adding M365 Apps/Office
[29:21](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=1761s) Adding Applications via Winget
[34:59](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=2099s) Bring your own Applications
[36:01](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=2161s) Customizing InstallAppsAndSysprep.cmd
[38:34](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=2314s) Demo - Application Configuration
[49:43](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=2983s) Drivers
[55:39](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=3339s) Automatically downloading drivers
[57:28](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=3448s) Microsoft Surface drivers
[58:55](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=3535s) Dell drivers
[01:01:45](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=3705s) Lenovo drivers
[01:03:16](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=3796s) HP drivers
[01:05:25](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=3925s) Bring your own drivers
[01:06:24](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=3984s) Demo - Drivers
[01:11:55](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=4315s) Multi-model driver support
[01:13:21](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=4401s) Device naming
[01:18:30](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=4710s) Device enrollment
[01:21:43](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=4903s) Autopilot
[01:24:57](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5097s) Provisioning packages
[01:26:54](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5214s) Custom WinRE
[01:29:59](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5399s) Demo - Putting it all together (Deep dive)
[01:32:06](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5526s) Downloading Lenovo 500w drivers
[01:33:28](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5608s) Downloading apps via Winget
[01:36:54](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5814s) Downloading Office, Defender, Edge, OneDrive
[01:38:15](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5895s) Building the Apps.iso
[01:39:08](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=5948s) Applying Windows to the VHDX
[01:40:16](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=6016s) Downloading and applying cumulative updates
[01:41:44](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=6104s) Building the VM
[01:48:13](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=6493s) Capturing the FFU
[01:53:38](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=6818s) Creating USB drive
[01:58:41](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=7121s) Deploying FFU
[02:11:48](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=7908s) Troubleshooting
[02:14:30](https://www.youtube.com/watch?v=rqXRbgeeKSQ&t=8070s) EDU Endpoint Office Hours