mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 10:19:36 -06:00
Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e95ff92b1 | |||
| d4274d54d2 | |||
| aee33a6a4b | |||
| 25a0928195 | |||
| d809fc021f | |||
| 582df6e3a8 | |||
| d5a4f96482 | |||
| d2fc9cf558 | |||
| b530ac5a5c | |||
| 2659336ee9 | |||
| c32a09bfc1 | |||
| f7ff415374 | |||
| 9cac674d7b | |||
| 2cf7da9c91 | |||
| 0d1d3a1ed5 | |||
| 7e2ebe8013 | |||
| 0606a1278c | |||
| 7c9f24f695 | |||
| 227fb4fa94 | |||
| 77ef154941 | |||
| a00aa3ee02 | |||
| 7b6b5efd8d | |||
| db62e05275 | |||
| 3db66eb55b | |||
| 4709177bc3 | |||
| e25a890946 | |||
| bc4a181182 | |||
| ce7af09f25 | |||
| e3da438225 | |||
| edbb7ccabe | |||
| f4360b34d9 | |||
| 0ed0cf4aa2 | |||
| 61fc2198c9 | |||
| f45f5a899b | |||
| 37f6dce344 | |||
| 10624787fe | |||
| d7a697d68d | |||
| 97954f59c3 | |||
| 3b23e9f420 | |||
| 94712ecbfc | |||
| a2c2b69026 | |||
| 6abc6f9d1a | |||
| db0fbfaaf4 | |||
| a59210c559 | |||
| add11b0037 | |||
| c26034a89c | |||
| 9287464eb8 | |||
| 1c103b2db7 | |||
| ed6a5fc7f1 | |||
| 768efc8cf7 | |||
| 39a9bc9022 | |||
| f90b7b3c9b | |||
| 802a225c3e | |||
| 74370db5de | |||
| db788c3c30 | |||
| eae619e7e8 | |||
| 0f3380e91e | |||
| 7c80486d88 | |||
| 1f65198803 | |||
| 0f18b7bd80 | |||
| b89f4a3b6b | |||
| 658d2d7af4 | |||
| f09c404f65 | |||
| fbe8eca263 | |||
| 923e8b070d | |||
| e6e53e566f | |||
| f144f1d71c | |||
| 3694e1a6e4 | |||
| d45b6dc8dc | |||
| 5194133a78 | |||
| 6e5d634af6 | |||
| 32d5ff3b47 | |||
| 5545554d7e | |||
| 6a0faa958e | |||
| 15c0478710 | |||
| bab9804022 | |||
| c93c417dba | |||
| 2fe91de000 | |||
| 412e3a078c | |||
| b6dda55a82 | |||
| b8bda93e8d | |||
| ac485f9c87 | |||
| 4b33627d19 | |||
| af28624e2d | |||
| 3457aedf5d | |||
| 5acac4ba5b | |||
| 0b151f9054 | |||
| cafc45dbba | |||
| e3cbcab6b2 | |||
| ec7e9a546c | |||
| 7a2aab3204 | |||
| 5dcdd2c36f | |||
| fb0a630bfd | |||
| 1da28024cc | |||
| 480e6a62b6 | |||
| 807456de86 | |||
| c8ef42ab21 |
+207
@@ -1,5 +1,212 @@
|
||||
# Change Log
|
||||
|
||||
# 2505.1
|
||||
|
||||
Highly recommended that you upgrade to this release. Fixes the issue with the May 2025 cumulative update and some SKU naming issues for SKUs other than Pro.
|
||||
|
||||
# Support for Windows LTSB/LTSC
|
||||
Thanks to @zehadialam for the code to allow support for LTSB and LTSC. This has been a requested feature from a number of customers and some might be opting for LTSC when Windows 10 support ends in October. We support LTSB 2016, LTSC 2019, 2021, 2024 including the N and IoT variants. Extensive testing has gone into validating CU and .net support. File an issue if you see any weird behavior.
|
||||
|
||||
# Support for automating computer naming via CSV
|
||||
Thanks to @JonasKloseBW for PR #150
|
||||
- Allows setting the computer name with a predefined list (SerialComputerNames.csv) of serial numbers and matching computer names
|
||||
- Defaults to FFU-{Random} if no matching serial number is found in list so FFU deployment can continue without user input
|
||||
|
||||
# Fixes
|
||||
- Thanks to @JonasKloseBW for PR #129 for adding the -AppListPath parameter
|
||||
- Fixed an issue where if AppsScriptVariables was configured in a config file, the hashtable wasn't being created by the script when setting the variable.
|
||||
- Fixed a crash where shortening the Windows SKU was creating duplicate shortened names for certain SKUs (EDU mainly, but others too)
|
||||
- Fix an issue with checkpoint CUs and May 2025-05B CU. Should future proof new checkpoint CUs in the future.
|
||||
|
||||
# Additional Fixes
|
||||
BuildFFUVM.ps1
|
||||
- Added parameter definitions that were missing:
|
||||
- AppListPath - Path to a JSON file containing a list of applications to install using WinGet. Default is $FFUDevelopmentPath\Apps\AppList.json.
|
||||
- PEDriversFolder - Path to the folder containing drivers to be injected into the WinPE deployment media. Default is $FFUDevelopmentPath\PEDrivers.
|
||||
- Added two new parameters:
|
||||
- UpdateLatestMicrocode - This is used for Windows 10/Server. When set to $true, will download and install the latest microcode updates for applicable Windows releases (e.g., Windows Server 2016/2019, Windows 10 LTSC 2016/2019) into the FFU. Default is $false.
|
||||
- UpdateADK - Added for airgapped scenarios where you've manually updated the ADK and don't need it to continually check. When set to $true, the script will check for and install the latest Windows ADK and WinPE add-on if they are not already installed or up-to-date. Default is $true.
|
||||
- Reorganized the WindowsSKU validateset to make it easier to read and added in 2016 LTSB releases
|
||||
- Changed version to 2505.1
|
||||
- Reorganized the releasetoMapping SKUs to make it easier to read
|
||||
- Omitted Defender/Edge from reporting KB ID since neither includes it
|
||||
- Updated Save-KB with some enhancements from the UI branch which will handle KBs that don't have an architecture defined in their file name that will leverage a new function Get-PEArchitecture that can interrogate the file name and determine the correct architecture
|
||||
- Updated Get-ShortenedWindowsSKU with LTSB/LTSC SKUs
|
||||
- Updated New-FFUFileName to use $winverinfo.Name for $WindowsRelease for client OSes to which will set $WindowsRelease to using Win10 or Win11. This fixes a bug where you might see 10 or 11 instead of Win10 or Win11 for FFU builds that use only the VHDX (e.g. `-InstallApps $false`. This keeps the naming consistent with FFUs built via VM.
|
||||
- Updated Get-WindowsVersionInfo to fix an issue with naming LTSC 2019
|
||||
- Added Get-PEArchitecture function
|
||||
- Commented out the Windows Security Platform Update code since the URL is dead for the content. This is fixed in the UI branch and will be reintroduced in Dev and Main at a later date when the UI work is complete.
|
||||
- Created a new variable `$isLTSC`
|
||||
- Modified and reorganized the search strings for the various .net framework components. LTSC introduced some complexity with handling the various .net releases.
|
||||
- VHDXCaching will now recurse the KBPath folder when finding downloaded KBs to include in its config file
|
||||
|
||||
Sample_default.json
|
||||
- Added new/missing parameters
|
||||
- ApplistPath
|
||||
- UpdateADK
|
||||
- UpdateLatestMicrocode
|
||||
|
||||
CaptureFFU.ps1
|
||||
- `$WindowsVersion` 2016 and 2019 for LTSC releases
|
||||
- Changed some SKU spacing to make things more consistent and included Enterprise N LTSC
|
||||
|
||||
ApplyFFU.ps1
|
||||
- Updated version to 2505.1
|
||||
|
||||
# 2412.1
|
||||
|
||||
This is a major release with a number of quality-of-life improvements that will reduce the time it takes to create FFUs. I highly recommend you update to this release.
|
||||
|
||||
## Windows Server Support
|
||||
Thanks to [JonasKloseBW](https://github.com/JonasKloseBW) we have added support for Windows Server! This includes support for Windows Server 2016 through 2025 and supports both core and desktop experience. It will require you to provide your own Server ISO
|
||||
using the `-ISOPath` parameter since we can't automatically download it like we can with client. You also will want to set the `-WindowsSKU` parameter to either `'Standard', 'Datacenter', 'Standard (Desktop Experience)', or 'Datacenter (Desktop Experience)'` depending on your needs.
|
||||
|
||||
Cumulative Updates for Windows and .NET should work as expected. Defender updates should work too. If you notice anything that doesn't work, open an issue.
|
||||
|
||||
## VHDX Caching Support
|
||||
Thanks again to Jonas for adding VHDX caching support #89. For those of you that might be making many FFUs for different configurations, instead of building the VHDX every time, you can cache the VHDX and re-use it for your next build. In testing, this seems to save about 10 minutes, depending on how you're installing Windows (via MCT download, or your own ISO and how old your media is).
|
||||
|
||||
The way this works is a VHDXCache folder is created in the FFUDevelopment folder. If `-AllowVHDXCaching $true`, we store the VHDX file and a config file that keeps track of the following info
|
||||
|
||||
```
|
||||
{
|
||||
"VhdxFileName": "_FFU-808829869.vhdx",
|
||||
"LogicalSectorSizeBytes": 512,
|
||||
"WindowsSKU": "Pro",
|
||||
"WindowsRelease": "11",
|
||||
"WindowsVersion": "24H2",
|
||||
"OptionalFeatures": "",
|
||||
"IncludedUpdates": [
|
||||
{
|
||||
"Name": "windows11.0-kb5043080-x64_953449672073f8fb99badb4cc6d5d7849b9c83e8.msu"
|
||||
},
|
||||
{
|
||||
"Name": "windows11.0-kb5045934-x64-ndp481_fa9c3adfb0532eb8f4e521f4fb92a179380184c5.msu"
|
||||
},
|
||||
{
|
||||
"Name": "windows11.0-kb5048667-x64_d4ad0ca69de9a02bc356757581e0e0d6960c9f93.msu"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
The VHDX files are cached before boot, so they've never been sysprepped. On subsequent runs, if `-AllowVHDXCaching $true` is set, we search the VHDXCache folder, loop through any config files, and look to see if we find one that matches the build information you've passed to the script. If a match is found, robocopy copies in the VHDX and uses the cached VHDX to build the FFU VM.
|
||||
|
||||
## Configuration File Support
|
||||
A configuration file can now be used to configure the parameters in lieu of, or in conjunction with, parameters specified on the command line. Configuration files are especially helpful for those making FFUs for different models, Windows releases, application sets, and more.
|
||||
|
||||
To use, run:
|
||||
`.\BuildFFUVM.ps1 -ConfigFile 'C:\FFUDevelopment\config\Sample_default.json' -verbose`
|
||||
|
||||
### Creating your own Configuration Json file
|
||||
|
||||
If you have a command line that you’ve been using for awhile and would like to convert it to a json file automatically, run your command line like normal, adding
|
||||
`-exportConfigFile 'C:\FFUDevelopment\config\YourConfigFile.json'`
|
||||
to the end of the command. Doing this will generate a well-formatted json file with your configuration settings.
|
||||
|
||||
You can also temporarily overwrite parameters while using a config file. Using the following sample command:
|
||||
|
||||
`.\BuildFFUVM.ps1 -ConfigFile 'C:\FFUDevelopment\config\Sample_default.json' -verbose`
|
||||
|
||||
If you’d like to not include Office (the Sample_default.json file installs Office), you’d add `-InstallOffice $False` to the command line
|
||||
|
||||
`.\BuildFFUVM.ps1 -ConfigFile 'C:\FFUDevelopment\config\Sample_default.json' -verbose -InstallOffice $False`
|
||||
|
||||
Doing this will temporarily overwrite whatever is in the json for the `InstallOffice` parameter. It will not modify the json file. If you would like to change the json file, you can add `-exportConfigFile 'C:\FFUDevelopment\config\Sample_default.json'` and that will overwrite the json file with the new parameter.
|
||||
|
||||
`.\BuildFFUVM.ps1 -ConfigFile 'C:\FFUDevelopment\config\Sample_default.json' -verbose -InstallOffice $False -exportConfigFile 'C:\FFUDevelopment\config\Sample_default.json'`
|
||||
|
||||
## Custom FFU Naming Support
|
||||
Thanks to Jonas, we now have custom FFU naming support. A new parameter -CustomFFUNameTemplate has been added.
|
||||
|
||||
This parameter sets a custom FFU output name with placeholders. Allowed placeholders are:
|
||||
|
||||
`{WindowsRelease}, {WindowsVersion}, {SKU}, {BuildDate}, {yyyy}, {MM}, {dd}, {H}, {hh}, {mm}, {tt}`
|
||||
|
||||
And below is a description of what to expect when you use each placeholder.
|
||||
|
||||
```
|
||||
{WindowsRelease} = 10, 11, 2016, 2019, 2022, 2025
|
||||
{WindowsVersion} = 1607, 1809, 21h2, 22h2, 23h2, 24h2, etc
|
||||
{SKU} = Home, Home N, Home Single Language, Education, Education N, Pro, Pro N, Pro Education, Pro Education N, Pro for Workstations, Pro N for Workstations, Enterprise, Enterprise N, Standard, Standard (Desktop Experience), Datacenter, Datacenter (Desktop Experience)
|
||||
{BuildDate} = e.g. Dec2024
|
||||
{yyyy} = e.g. 2024
|
||||
{MM} = 2 digit month format (e.g. 12 for December)
|
||||
{dd} = Day of the month in 2 digit format (19)
|
||||
{HH} = Current hour in 24-hour format (e.g., 14 for 2 PM)
|
||||
{hh} = Current hour in 12-hour format (e.g., 02 for 2 PM)
|
||||
{mm} = Current minute in 2-digit format (e.g., 09)
|
||||
{tt} = Current AM/PM designator (e.g., AM or PM)
|
||||
```
|
||||
|
||||
An example for Windows 11 24h2 Pro built today would be:
|
||||
|
||||
`-CustomFFUNameTemplate '{WindowsRelease}_{WindowsVersion}_{SKU}_{yyyy}-{MM}-{dd}_{HH}{mm}'`
|
||||
|
||||
Would result in a FFU file name of:
|
||||
|
||||
`Win11_24h2_Pro_2024-12-20_1225.ffu`
|
||||
|
||||
You can also mix in static text in the name
|
||||
|
||||
`-CustomFFUNameTemplate '{WindowsRelease}_{WindowsVersion}_{SKU}_Office_{yyyy}-{MM}-{dd}_{HH}{mm}'`
|
||||
|
||||
Would result in:
|
||||
|
||||
`Win11_24h2_Pro_Office_2024-12-20_1225.ffu`
|
||||
|
||||
## Additional PRs added
|
||||
#79 Includes the latest Microsoft Software Removal Tool from `@zehadialam` - use `-UpdateLatestMSRT $true`
|
||||
|
||||
#72 Includes some Unattend Sample files from @HedgeComp in the `$FFUDevelopment\Unattend` folder
|
||||
|
||||
#74 Includes some improvements to the USBImagingToolCreator.ps1 file from @w0
|
||||
|
||||
#103 Includes some additional improvements to the USBImagingToolCreator.ps1 file from @MKellyCBSD
|
||||
|
||||
## Misc Fixes
|
||||
- Added server skus to validateset for $WindowsSKU
|
||||
- Added new variable $installationType which uses $WindowsRelease to determine Server or Client. If $installationType is Server, $WindowsRelease version is used to set $WindowsVersion to the appropriate version (1607, 1809, 21H2)
|
||||
- Fixed an issue where the recovery partition wouldn't be created on server OSes due to winre.wim being hidden. Never saw this on client OSes even though it also was hidden IIRC.
|
||||
- Removed verbosity for Optimize-Volume as it was outputting when -verbose was not specified.
|
||||
- Modified some search strings for .NET CUs when installing on Server OS
|
||||
- Included SSU for Windows Server 2016 as it's mandatory
|
||||
- Added some error checking for Server 2019 and 2022 CU installations when CU fails due to lack of SSU. If you run into this error, you're using old media and should use the latest. Always use the latest ISO if you can.
|
||||
- $WindowsVersion set to 24h2, can override by using -WindowsVersion 23H2 if you want the old behavior
|
||||
- Removed the "Downloading information GUID" messages when downloading content from the Microsoft Update Catalog while -verbose was specified in the command line
|
||||
- In Get-KBLink, made a change to just grab the first result returned instead of the entire results page. This removes the need to use a break statement in Save-KB when downloading updates. This fixed an issue with the new 24H2 Checkpoint Cumulative Updates in Win11 and Server 2025.
|
||||
- Changed Windows MSRT search string for x64 and x86. This was mainly to get x64 to the top of the search results. x86 won't actually download since the code isn't in place for content from the MU Catalog to download x86 content (no idea if anyone actually builds x86 FFUs for Win10 - I hope not)
|
||||
- If not passing an ISO, hardcoded WindowsVersion of 22H2 for Windows 10 or 24H2 for Windows 11 since the ESD media only provides those two versions. Not doing this allowed for unnecessary VHDX creation since it checks the WindowsVersion via the json file. This also fixes an issue where CUs could be searched for that didn’t exist, but the media would still download
|
||||
- Added some additional logging entries
|
||||
- Removed verbose output of the Optimize-Volume command
|
||||
- Fixed an issue where not passing an ISO caused the script to fail
|
||||
- Cleaned up the KBPath folder at the end of the run
|
||||
- Changed some minor formatting items
|
||||
- Added Get-Childprocesses function to return child processes of parent process
|
||||
- Added a new -Wait boolean parameter to Invoke-Process function. This is to control whether Invoke-Process should wait in order to track stdout and stderr output. This is needed for processes that may hang, waiting for user input and there isn't a way to bypass (some Intel drivers provided by Dell leave dialog windows even when running silently)
|
||||
-Invoke-Process now returns process information (returns $cmd). This allows for process tracking when calling the function.
|
||||
- Since Invoke-Process now returns the process information, also needed to add Out-Null to the majority of the Invoke-Process references to prevent Invoke-Process from writing to the terminal
|
||||
- Refactored a lot of the Get-DellDrivers function due to inconsistencies with how driver extraction behaves between client and server devices. For client, /s /e seemed to work fine, but for server it would only extract the driver installer content and other dell related files, rather than the driver files themselves. We have since switched to using /s /drivers= which will extract the driver content. Not all drivers support /drivers= and may output some information to the terminal that looks like help documentation. If a driver doesn't support /drivers, the script falls back to using /s /e to do the extraction. If this doesn't work for you, you can always provide your own drivers that you manually download from Dell's website.
|
||||
- Updated Malicious Software Removal Tool (MSRT) code to handle Windows Server
|
||||
- Refactored the Get-ODTURL function to fix recent download issues. Also added some better error handling
|
||||
- Moved the odtsetup.exe download to the FFUDevelopment folder and will clean it up after office has downloaded
|
||||
Updated parameter definition block to be alphabetized (not to be confused by the param block, which is not alphabetized)
|
||||
- Added $PEDriversFolder script variable to the param block (for some reason it was missing)
|
||||
- Added ConfigFile and ExportConfigFile parameters to support json config files
|
||||
- Changed Version to 2412.1
|
||||
- Modified vhdxCacheItem class to include $LogicalSectorSizeBytes
|
||||
- Added new function Get-Parameters to help with new config and export config file functionality
|
||||
- Fixed Get-MicrosoftDrivers function to not require the HTMLFILE COM object, which isn't available in Windows 11. It seems to be installed with Office, which is what was allowing downloads to work and masked the issue.
|
||||
- Added long path support to prevent issues with oscdimg creating the Apps.iso.
|
||||
- Fixed an issue where the $PEDriversFolder variable wasn't being used (instead $FFUDevelopment\PEDrivers was used)
|
||||
- Created a new function New-FFUFileName - this works in conjunction with the new $CustomFFUNameTemplate. The function was needed to support both scenarios where $InstallApps is either $true or $false.
|
||||
- Added new function Export-ConfigFile. When passing -ExportConfigFile 'Path\To\ConfigFile.json' the script will generate a parameter dump of all of the configured parameters
|
||||
- Added driver folder validation to throw an error if spaces are detected in the folder name of the drivers folder (e.g. C:\FFUDevelopment\Drivers\Dell 3190). This is due to an issue with Dell drivers and their inability to handle paths with spaces consistently.
|
||||
- Added back the Windows Security Platform update which grabs it from the web instead of the Microsoft update catalog
|
||||
- Fixed an issue where the Drivers folder was being completely deleted instead of its sub-folders
|
||||
- Removed the Requires -PSEdition Desktop. The script works with both Desktop and Core, so pwsh 7 is fine.
|
||||
- Created a new config folder to hold config files. A new sample_default.json file is provided to show what the format looks like.
|
||||
- You can now set the computername in the unattend.xml file where ever you want. Prior it required that the computername was the first component element.
|
||||
|
||||
## **2409.1**
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -5,9 +5,12 @@ REM d:\Office\setup.exe /configure d:\office\DeployFFU.xml
|
||||
REM Install Defender Platform Update
|
||||
REM Install Defender Definitions
|
||||
REM Install Windows Security Platform Update
|
||||
REM Install Windows Malicious Software Removal Tool
|
||||
REM Install OneDrive Per Machine
|
||||
REM Install Edge Stable
|
||||
REM Winget Win32 Apps
|
||||
REM START Batch variables placeholder
|
||||
REM END Batch variables placeholder
|
||||
REM Add additional apps below here
|
||||
REM Contoso App (Example)
|
||||
REM msiexec /i d:\Contoso\setup.msi /qn /norestart
|
||||
|
||||
+1595
-603
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -4,22 +4,34 @@ param(
|
||||
$DeployISOPath,
|
||||
[Switch]$DisableAutoPlay
|
||||
)
|
||||
$Host.UI.RawUI.WindowTitle = 'USB Imaging Tool Creator'
|
||||
$Host.UI.RawUI.WindowTitle = 'Imaging Tool USB Creator'
|
||||
|
||||
if($DeployISOPath){
|
||||
$DevelopmentPath = $DeployISOPath | Split-Path
|
||||
$ImagesPath = "$DevelopmentPath\FFU"
|
||||
function WriteLog($LogText) {
|
||||
$LogFileName = '\Script.log'
|
||||
$LogFile = $DevelopmentPath + $LogFilename
|
||||
Add-Content -path $LogFile -value "$((Get-Date).ToString()) $LogText" -Force -ErrorAction SilentlyContinue
|
||||
Write-Verbose $LogText
|
||||
}
|
||||
Function Get-USBDrive {
|
||||
$USBDrives = (Get-WmiObject -Class Win32_DiskDrive -Filter "MediaType='Removable Media'")
|
||||
If ($USBDrives -and ($null -eq $USBDrives.count)) {
|
||||
$USBDrivesCount = 1
|
||||
|
||||
function Write-ProgressLog {
|
||||
param(
|
||||
[string]$Activity,
|
||||
[string]$Status
|
||||
)
|
||||
Write-Progress -Activity $Activity -Status $Status -PercentComplete (($currentStep / $totalSteps) * 100)
|
||||
WriteLog $Status
|
||||
$script:currentStep++
|
||||
|
||||
}
|
||||
else {
|
||||
Function Get-RemovableDrive {
|
||||
writelog "Get information for all removable drives"
|
||||
$USBDrives = Get-WmiObject Win32_DiskDrive | Where-Object {$_.MediaType -eq "Removable media"}
|
||||
If($USBDrives -and ($null -eq $USBDrives.count)) {
|
||||
$USBDrivesCount = 1
|
||||
} else {
|
||||
$USBDrivesCount = $USBDrives.Count
|
||||
}
|
||||
WriteLog "Found $USBDrivesCount USB drives"
|
||||
@@ -27,20 +39,23 @@ Function Get-USBDrive {
|
||||
if ($null -eq $USBDrives) {
|
||||
WriteLog "No removable USB drive found. Exiting"
|
||||
Write-Error "No removable USB drive found. Exiting"
|
||||
Pause
|
||||
exit 1
|
||||
}
|
||||
return $USBDrives, $USBDrivesCount
|
||||
}
|
||||
return $USBDrives, $USBDrivesCount
|
||||
}
|
||||
|
||||
Function Build-DeploymentUSB{
|
||||
param(
|
||||
[Array]$Drives
|
||||
)
|
||||
writelog "Checking if ffu files are present in the ffu folder"
|
||||
$Images = Get-ChildItem -Path $FFUPath -Filter "*.ffu" -File -Recurse
|
||||
writelog "Creating list of FFU image files"
|
||||
$Images = Get-ChildItem -Path $ImagesPath -Filter "*.ffu" -File -Recurse
|
||||
writelog "Checking if drivers are present in the drivers folder"
|
||||
$Drivers = Get-ChildItem -Path $DriversPath -Recurse
|
||||
$DrivesCount = $Drives.Count
|
||||
Writelog "Creating partitions..."
|
||||
Write-ProgressLog "Create Imaging Tool" "Creating partitions..."
|
||||
writelog "Create job to partition each usb drive"
|
||||
foreach ($USBDrive in $Drives) {
|
||||
$DriveNumber = $USBDrive.DeviceID.Replace("\\.\PHYSICALDRIVE", "")
|
||||
$Model = $USBDrive.model
|
||||
@@ -65,7 +80,7 @@ Function Build-DeploymentUSB{
|
||||
if($DrivesCount -gt 1){
|
||||
writelog "Get file system information for all drives"
|
||||
$Partitions = Get-Partition | Get-Volume
|
||||
}else{
|
||||
} else {
|
||||
writelog "Get file system information for drive number $DiskNumber"
|
||||
$Partitions = Get-Partition -DiskNumber $DriveNumber | Get-Volume
|
||||
}
|
||||
@@ -97,13 +112,21 @@ $Destination = $Drive + ":\"
|
||||
[string]$SFolder,
|
||||
[string]$DFolder
|
||||
)
|
||||
New-Item -Path $DFolder -ItemType Directory -Force -Confirm: $false | Out-Null
|
||||
Robocopy $SFolder $DFolder /E /COPYALL /R:5 /W:5 /J
|
||||
}
|
||||
|
||||
WriteLog "Start job to copy all FFU files to $Destination"
|
||||
Start-Job -ScriptBlock $jobScriptBlock -ArgumentList $FFUPath, $Destination | Out-Null
|
||||
Start-Job -ScriptBlock $jobScriptBlock -ArgumentList $ImagesPath, $Destination | Out-Null
|
||||
}
|
||||
}
|
||||
if(!($Images)){
|
||||
foreach ($Drive in $DeployDrives) {
|
||||
WriteLog "Create images directory"
|
||||
$drivepath = $Drive + ":\"
|
||||
New-Item -Path "$drivepath" -Name Images -ItemType Directory -Force -Confirm: $false | Out-Null
|
||||
}
|
||||
}
|
||||
if($Drivers){
|
||||
writelog "Copying driver files to all drives labeled deploy concurrently"
|
||||
foreach ($Drive in $DeployDrives) {
|
||||
@@ -128,14 +151,14 @@ if(!($Drivers)){
|
||||
}
|
||||
}
|
||||
if($DrivesCount -gt 1){
|
||||
Writelog "Building $DrivesCount drives concurrently...Please be patient..."
|
||||
}else{
|
||||
Writelog "Building the imaging tool on $model...Please be patient..."
|
||||
Write-ProgressLog "Create Imaging Tool" "Building $DrivesCount drives concurrently...Please be patient..."
|
||||
} else {
|
||||
Write-ProgressLog "Create Imaging Tool" "Building the imaging tool on $model...Please be patient..."
|
||||
}
|
||||
Get-Job | Wait-Job | Out-Null
|
||||
|
||||
Dismount-DiskImage -ImagePath $DeployISOPath | Out-Null
|
||||
Writelog "Drive creation jobs completed..."
|
||||
Write-ProgressLog "Create Imaging Tool" "Drive creation jobs completed..."
|
||||
}
|
||||
|
||||
Function New-DeploymentUSB {
|
||||
@@ -167,20 +190,15 @@ Function New-DeploymentUSB {
|
||||
$var = $true
|
||||
$DriveSelected = Read-Host 'Enter the drive number to apply the .iso to'
|
||||
$DriveSelected = ($DriveSelected -as [int]) -1
|
||||
if($Last){
|
||||
writelog "All drives selected"
|
||||
}else{
|
||||
writelog "Drive $DriveSelected selected"}
|
||||
writelog "Drive $DriveSelected selected"
|
||||
}
|
||||
catch {
|
||||
|
||||
catch {
|
||||
Write-Host 'Input was not in correct format. Please enter a valid FFU number'
|
||||
$var = $false
|
||||
}
|
||||
} until (($DriveSelected -le $Count -1 -or $last) -and $var)
|
||||
|
||||
$DisableAutoPlayCurrentSetting = (Get-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers" -Name DisableAutoplay).DisableAutoplay
|
||||
if($DisableAutoPlay -and $DisableAutoPlayCurrentSetting -ne 1){
|
||||
writelog "Disable autoPlay current setting is $DisableAutoPlayCurrentSetting"
|
||||
if($DisableAutoPlay){
|
||||
WriteLog "Setting the registry key to disable autoplay for all drives"
|
||||
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers" -Name "DisableAutoplay" -Value 1 -Type DWORD
|
||||
}
|
||||
@@ -193,16 +211,16 @@ Function New-DeploymentUSB {
|
||||
if($Selection -eq $last){
|
||||
Read-Host -Prompt "ALL DRIVES SELECTED! WILL ERASE ALL CURRENTLY CONNECTED USB DRIVES!! Press ENTER to continue"
|
||||
Build-DeploymentUSB -Drives $Drives
|
||||
}else{
|
||||
} else {
|
||||
Read-Host -Prompt "Drive number $Selection was selected. Press ENTER to continue"
|
||||
Build-DeploymentUSB -Drives $Drives[$DriveSelected]
|
||||
}
|
||||
WriteLog "Setting the registry key to re-enable autoplay for all drives"
|
||||
if($DisableAutoPlay){
|
||||
Writelog "Setting disable autoplay setting back to $DisableAutoPlayCurrentSetting"
|
||||
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers" -Name "DisableAutoplay" -Value $DisableAutoPlayCurrentSetting -Type DWORD
|
||||
Write-ProgressLog "Create Imaging Tool" "Enabling Autoplay"
|
||||
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers" -Name "DisableAutoplay" -Value 0 -Type DWORD
|
||||
}
|
||||
Writelog "Completed!"
|
||||
Write-ProgressLog "Create Imaging Tool" "Completed!"
|
||||
}
|
||||
#Get USB Drive and create log file
|
||||
if(Test-Path "$DevelopmentPath\Script.log"){
|
||||
@@ -211,12 +229,15 @@ New-item -Path $DevelopmentPath -Name 'Script.log' -ItemType "file" -Force | Out
|
||||
}
|
||||
WriteLog 'Begin Logging'
|
||||
WriteLog 'Getting USB drive information and usb drive count'
|
||||
$USBDrives,$USBDrivesCount = Get-USBDrive
|
||||
$USBDrives,$USBDrivesCount = Get-RemovableDrive
|
||||
WriteLog 'Setting first step for percentage progress bar'
|
||||
$currentStep = 1
|
||||
New-DeploymentUSB -Drives $USBDrives -Count $USBDrivesCount
|
||||
|
||||
read-host -Prompt "USB drive creation complete. Press ENTER to exit"
|
||||
|
||||
Exit
|
||||
}else{
|
||||
} else {
|
||||
Write-Host "No .ISO file selected..."
|
||||
read-host "Press ENTER to Exit..."
|
||||
Exit
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Modify the net use W: \\192.168.1.158\FFUCaptureShare /user:ffu_user ddb1f077-3eed-433c-b4d9-7b8cd54ce727
|
||||
net use W: \\192.168.1.158\FFUCaptureShare /user:ffu_user ddb1f077-3eed-433c-b4d9-7b8cd54ce727
|
||||
|
||||
#Custom naming placeholder
|
||||
$AssignDriveLetter = 'x:\AssignDriveLetter.txt'
|
||||
Start-Process -FilePath diskpart.exe -ArgumentList "/S $AssignDriveLetter" -Wait -ErrorAction Stop | Out-Null
|
||||
#Load Registry Hive
|
||||
@@ -11,53 +11,102 @@ reg load "HKLM\FFU" $Software
|
||||
|
||||
$SKU = Get-ItemPropertyValue -Path 'HKLM:\FFU\Microsoft\Windows NT\CurrentVersion\' -Name 'EditionID'
|
||||
[int]$CurrentBuild = Get-ItemPropertyValue -Path 'HKLM:\FFU\Microsoft\Windows NT\CurrentVersion\' -Name 'CurrentBuild'
|
||||
$DisplayVersion = Get-ItemPropertyValue -Path 'HKLM:\FFU\Microsoft\Windows NT\CurrentVersion\' -Name 'DisplayVersion'
|
||||
$InstallationType = Get-ItemPropertyValue -Path 'HKLM:\FFU\Microsoft\Windows NT\CurrentVersion\' -Name 'InstallationType'
|
||||
if ($CurrentBuild -notin 14393, 17763 -and $InstallationType -ne "Server") {
|
||||
$WindowsVersion = Get-ItemPropertyValue -Path 'HKLM:\FFU\Microsoft\Windows NT\CurrentVersion\' -Name 'DisplayVersion'
|
||||
}
|
||||
# For Windows 10 LTSB 2016, set WindowsVersion to 2016
|
||||
if ($CurrentBuild -eq 14393 -and $InstallationType -eq "Client") {
|
||||
$WindowsVersion = '2016'
|
||||
}
|
||||
# For Windows 10 LTSC 2019, set WindowsVersion to 2019
|
||||
if ($CurrentBuild -eq 17763 -and $InstallationType -eq "Client") {
|
||||
$WindowsVersion = '2019'
|
||||
}
|
||||
|
||||
|
||||
$BuildDate = Get-Date -uformat %b%Y
|
||||
|
||||
$SKU = switch ($SKU) {
|
||||
Core { 'Home' }
|
||||
CoreN { 'HomeN'}
|
||||
CoreSingleLanguage { 'HomeSL'}
|
||||
CoreN { 'Home_N' }
|
||||
CoreSingleLanguage { 'Home_SL' }
|
||||
Professional { 'Pro' }
|
||||
ProfessionalN { 'ProN'}
|
||||
ProfessionalN { 'Pro_N' }
|
||||
ProfessionalEducation { 'Pro_Edu' }
|
||||
ProfessionalEducationN { 'Pro_EduN' }
|
||||
ProfessionalEducationN { 'Pro_Edu_N' }
|
||||
Enterprise { 'Ent' }
|
||||
EnterpriseN { 'EntN'}
|
||||
EnterpriseN { 'Ent_N' }
|
||||
EnterpriseS { 'Ent_LTSC' }
|
||||
EnterpriseSN { 'Ent_N_LTSC' }
|
||||
IoTEnterpriseS { 'IoT_Ent_LTSC' }
|
||||
Education { 'Edu' }
|
||||
EducationN { 'EduN'}
|
||||
EducationN { 'Edu_N' }
|
||||
ProfessionalWorkstation { 'Pro_Wks' }
|
||||
ProfessionalWorkstationN { 'Pro_WksN' }
|
||||
ProfessionalWorkstationN { 'Pro_Wks_N' }
|
||||
ServerStandard { 'Srv_Std' }
|
||||
ServerDatacenter { 'Srv_Dtc' }
|
||||
}
|
||||
|
||||
if($CurrentBuild -ge 22000){
|
||||
$Name = 'Win11'
|
||||
if ($InstallationType -eq "Client") {
|
||||
if ($CurrentBuild -ge 22000) {
|
||||
$WindowsRelease = 'Win11'
|
||||
}
|
||||
else {
|
||||
$WindowsRelease = 'Win10'
|
||||
}
|
||||
}
|
||||
else{
|
||||
$Name = 'Win10'
|
||||
else {
|
||||
$WindowsRelease = switch ($CurrentBuild) {
|
||||
26100 { '2025' }
|
||||
20348 { '2022' }
|
||||
17763 { '2019' }
|
||||
14393 { '2016' }
|
||||
Default { $WindowsVersion }
|
||||
}
|
||||
if ($InstallationType -eq "Server Core") {
|
||||
$SKU += "_Core"
|
||||
}
|
||||
}
|
||||
|
||||
#If Office is installed, modify the file name of the FFU
|
||||
#$Office = Get-childitem -Path 'M:\Program Files\Microsoft Office' -ErrorAction SilentlyContinue | Out-Null
|
||||
$Office = Get-childitem -Path 'M:\Program Files\Microsoft Office' -ErrorAction SilentlyContinue
|
||||
if($Office){
|
||||
$ffuFilePath = "W:\$Name`_$DisplayVersion`_$SKU`_Office`_$BuildDate.ffu"
|
||||
$dismArgs = "/capture-ffu /imagefile=$ffuFilePath /capturedrive=\\.\PhysicalDrive0 /name:$Name$DisplayVersion$SKU /Compress:Default"
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
$ffuFilePath = "W:\$Name`_$DisplayVersion`_$SKU`_Apps`_$BuildDate.ffu"
|
||||
$dismArgs = "/capture-ffu /imagefile=$ffuFilePath /capturedrive=\\.\PhysicalDrive0 /name:$Name$DisplayVersion$SKU /Compress:Default"
|
||||
|
||||
if ($CustomFFUNameTemplate) {
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -replace '{WindowsRelease}', $WindowsRelease
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -replace '{WindowsVersion}', $WindowsVersion
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -replace '{SKU}', $SKU
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -replace '{BuildDate}', $BuildDate
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -replace '{yyyy}', (Get-Date -UFormat '%Y')
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -creplace '{MM}', (Get-Date -UFormat '%m')
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -replace '{dd}', (Get-Date -UFormat '%d')
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -creplace '{HH}', (Get-Date -UFormat '%H')
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -creplace '{hh}', (Get-Date -UFormat '%I')
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -creplace '{mm}', (Get-Date -UFormat '%M')
|
||||
$CustomFFUNameTemplate = $CustomFFUNameTemplate -replace '{tt}', (Get-Date -UFormat '%p')
|
||||
if($CustomFFUNameTemplate -notlike '*.ffu') {
|
||||
$CustomFFUNameTemplate += '.ffu'
|
||||
}
|
||||
$dismArgs = "/capture-ffu /imagefile=W:\$CustomFFUNameTemplate /capturedrive=\\.\PhysicalDrive0 /name:$WindowsRelease$WindowsVersion$SKU /Compress:Default"
|
||||
} else {
|
||||
#If Office is installed, modify the file name of the FFU
|
||||
#$Office = Get-childitem -Path 'M:\Program Files\Microsoft Office' -ErrorAction SilentlyContinue | Out-Null
|
||||
$Office = Get-ChildItem -Path 'M:\Program Files\Microsoft Office' -ErrorAction SilentlyContinue
|
||||
if ($Office) {
|
||||
$ffuFilePath = "W:\$WindowsRelease`_$WindowsVersion`_$SKU`_Office`_$BuildDate.ffu"
|
||||
} else {
|
||||
$ffuFilePath = "W:\$WindowsRelease`_$WindowsVersion`_$SKU`_Apps`_$BuildDate.ffu"
|
||||
}
|
||||
$dismArgs = "/capture-ffu /imagefile=$ffuFilePath /capturedrive=\\.\PhysicalDrive0 /name:$WindowsRelease$WindowsVersion$SKU /Compress:Default"
|
||||
}
|
||||
|
||||
#Unload Registry
|
||||
Set-Location X:\
|
||||
Remove-Variable SKU
|
||||
Remove-Variable CurrentBuild
|
||||
Remove-Variable DisplayVersion
|
||||
Remove-Variable Office
|
||||
if ($CurrentBuild -notin 14393, 17763) {
|
||||
Remove-Variable WindowsVersion
|
||||
}
|
||||
if($Office) {
|
||||
Remove-Variable Office
|
||||
}
|
||||
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
|
||||
Write-Host "Sleeping for 60 seconds to allow registry to unload prior to capture"
|
||||
@@ -65,5 +114,4 @@ Start-sleep 60
|
||||
Start-Process -FilePath dism.exe -ArgumentList $dismArgs -Wait -PassThru -ErrorAction Stop | Out-Null
|
||||
#Copy DISM log to Host
|
||||
xcopy X:\Windows\logs\dism\dism.log W:\ /Y | Out-Null
|
||||
|
||||
wpeutil Shutdown
|
||||
|
||||
@@ -55,11 +55,18 @@ function Set-DiskpartAnswerFiles($DiskpartFile,$DiskID){
|
||||
|
||||
function Set-Computername($computername){
|
||||
[xml]$xml = Get-Content $UnattendFile
|
||||
if($xml.unattend.settings.component.Count -ge 2){
|
||||
#Assumes that Computername is the first component element
|
||||
$xml.unattend.settings.component[0].ComputerName = $computername
|
||||
}else{
|
||||
$xml.unattend.settings.component.ComputerName = $computername
|
||||
$components = $xml.unattend.settings.component
|
||||
$found = $false
|
||||
foreach ($component in $components) {
|
||||
if ($component.ComputerName) {
|
||||
$component.ComputerName = $computername
|
||||
$found = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (-not $found) {
|
||||
WriteLog 'ComputerName element not found in unattend.xml.'
|
||||
throw 'ComputerName element not found in unattend.xml.'
|
||||
}
|
||||
$xml.Save($UnattendFile)
|
||||
return $computername
|
||||
@@ -128,14 +135,14 @@ $LogFileName = 'ScriptLog.txt'
|
||||
$USBDrive = Get-USBDrive
|
||||
New-item -Path $USBDrive -Name $LogFileName -ItemType "file" -Force | Out-Null
|
||||
$LogFile = $USBDrive + $LogFilename
|
||||
$version = '2409.1'
|
||||
$version = '2505.2'
|
||||
WriteLog 'Begin Logging'
|
||||
WriteLog "Script version: $version"
|
||||
|
||||
#Find PhysicalDrive
|
||||
# $PhysicalDeviceID = Get-HardDrive
|
||||
$hardDrive = Get-HardDrive
|
||||
if($hardDrive -eq $null){
|
||||
if($null -eq $hardDrive){
|
||||
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
|
||||
@@ -215,6 +222,7 @@ if (Test-Path -Path $PPKGFolder){
|
||||
$UnattendFolder = $USBDrive + "unattend\"
|
||||
$UnattendFilePath = $UnattendFolder + "unattend.xml"
|
||||
$UnattendPrefixPath = $UnattendFolder + "prefixes.txt"
|
||||
$UnattendComputerNamePath = $UnattendFolder + "SerialComputerNames.csv"
|
||||
If (Test-Path -Path $UnattendFilePath){
|
||||
$UnattendFile = Get-ChildItem -Path $UnattendFilePath
|
||||
If ($UnattendFile){
|
||||
@@ -227,6 +235,12 @@ If (Test-Path -Path $UnattendPrefixPath){
|
||||
$UnattendPrefix = $true
|
||||
}
|
||||
}
|
||||
If (Test-Path -Path $UnattendComputerNamePath){
|
||||
$UnattendComputerNameFile = Get-ChildItem -Path $UnattendComputerNamePath
|
||||
If ($UnattendComputerNameFile){
|
||||
$UnattendComputerName = $true
|
||||
}
|
||||
}
|
||||
|
||||
#Ask for device name if unattend exists
|
||||
if ($Unattend -and $UnattendPrefix){
|
||||
@@ -271,7 +285,25 @@ if ($Unattend -and $UnattendPrefix){
|
||||
$computername = Set-Computername($computername)
|
||||
Writelog "Computer name set to $computername"
|
||||
}
|
||||
elseif($Unattend){
|
||||
elseif($Unattend -and $UnattendComputerName){
|
||||
Writelog 'Unattend file found with SerialComputerNames.csv. Getting name for current computer.'
|
||||
$SerialComputerNames = Import-Csv -Path $UnattendComputerNameFile.FullName -Delimiter ","
|
||||
|
||||
$SerialNumber = (Get-CimInstance -Class Win32_Bios).SerialNumber
|
||||
$SCName = $SerialComputerNames | Where-Object { $_.SerialNumber -eq $SerialNumber }
|
||||
|
||||
If ($SCName) {
|
||||
[string]$computername = $SCName.ComputerName
|
||||
$computername = Set-Computername($computername)
|
||||
Writelog "Computer name set to $computername"
|
||||
} else {
|
||||
Writelog 'No matching serial number found in SerialComputerNames.csv. Setting random computer name to complete setup.'
|
||||
[string]$computername = ("FFU-" + (-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 11 | ForEach-Object { [char]$_ })))
|
||||
$computername = Set-Computername($computername)
|
||||
Writelog "Computer name set to $computername"
|
||||
}
|
||||
}
|
||||
elseif($Unattend) {
|
||||
Writelog 'Unattend file found with no prefixes.txt, asking for name'
|
||||
[string]$computername = Read-Host 'Enter device name'
|
||||
Set-Computername($computername)
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||
<settings pass="specialize">
|
||||
<!--<ComputerName> must be in the first Component Element "Microsoft-Windows-Shell-Setup" . Do not change the order or remove it -->
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ComputerName>MYCOMPUTER</ComputerName><!--Leave Default will be renamed-->
|
||||
<TimeZone>Eastern Standard Time</TimeZone><!--Add Your Local TimeZone-->
|
||||
</component>
|
||||
<!-- Place additional Components Elements and Settings below here: -->
|
||||
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<RunASynchronous>
|
||||
<RunASynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Path>cmd.exe /c date 09-07-2024</Path> <!--Set the device clock to the current date. Helpful when BIOS clocks out of sync. -->
|
||||
<Description>Set system date to a specific date</Description>
|
||||
</RunASynchronousCommand>
|
||||
</RunASynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<InputLocale>0409:00000409</InputLocale><!--Set your Keybaord and System Local https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-8.1-and-8/hh825682(v=win.10) -->
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<OOBE>
|
||||
<ProtectYourPC>3</ProtectYourPC> <!--Disable Diagnostic Data sent to Microsoft-->
|
||||
<HideEULAPage>true</HideEULAPage><!--Hide the End User License agreement -->
|
||||
<HideWirelessSetupInOOBE>false</HideWirelessSetupInOOBE> <!--Show Wifi Setup -->
|
||||
</OOBE>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
@@ -1,8 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
<settings pass="specialize">
|
||||
<!--<ComputerName> must be in the first Component Element "Microsoft-Windows-Shell-Setup" . Do not change the order or remove it -->
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="arm64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ComputerName>MyComputer</ComputerName>
|
||||
</component>
|
||||
<!--Place addtional Components Elements and settings below here. -->
|
||||
</settings>
|
||||
</unattend>
|
||||
@@ -1,8 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
<settings pass="specialize">
|
||||
<!--<ComputerName> must be in the first Component Element "Microsoft-Windows-Shell-Setup" . Do not change the order or remove it -->
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ComputerName>MyComputer</ComputerName>
|
||||
</component>
|
||||
<!--Place addtional Components Elements and settings below here. -->
|
||||
</settings>
|
||||
</unattend>
|
||||
@@ -1,6 +1,8 @@
|
||||
**Update 2025-08-01:** [2507.2 UI Preview is now available](https://github.com/rbalsleyMSFT/FFU/releases) - click the link to get the build and check out the Youtube walk-through.
|
||||
|
||||
# Using Full Flash Update (FFU) files to speed up Windows deployment
|
||||
|
||||
What if you could have a Windows image that has:
|
||||
What if you could have a Windows image (Windows 10/11 or Server) that has:
|
||||
|
||||
- The latest Windows cumulative update
|
||||
- The latest .NET cumulative update
|
||||
@@ -18,10 +20,6 @@ And the best part: it takes less than two minutes to apply the image, even with
|
||||
|
||||
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
|
||||
|
||||
2409.1 has been released! Check out the changes in the [Change Log](ChangeLog.md)
|
||||
|
||||
# Getting Started
|
||||
|
||||
- Download the latest [release](https://github.com/rbalsleyMSFT/FFU/releases)
|
||||
|
||||
Reference in New Issue
Block a user