mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 10:19:36 -06:00
7d74feec0c
- 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
565 lines
20 KiB
PowerShell
565 lines
20 KiB
PowerShell
function Get-USBDrive(){
|
|
$USBDriveLetter = (Get-Volume | Where-Object {$_.DriveType -eq 'Removable' -and $_.FileSystemType -eq 'NTFS'}).DriveLetter
|
|
if ($null -eq $USBDriveLetter){
|
|
#Must be using a fixed USB drive - difficult to grab drive letter from win32_diskdrive. Assume user followed instructions and used Deploy as the friendly name for partition
|
|
$USBDriveLetter = (Get-Volume | Where-Object {$_.DriveType -eq 'Fixed' -and $_.FileSystemType -eq 'NTFS' -and $_.FileSystemLabel -eq 'Deploy'}).DriveLetter
|
|
#If we didn't get the drive letter, stop the script.
|
|
if ($null -eq $USBDriveLetter){
|
|
WriteLog 'Cannot find USB drive letter - most likely using a fixed USB drive. Name the 2nd partition with the FFU files as Deploy so the script can grab the drive letter. Exiting'
|
|
Exit
|
|
}
|
|
|
|
}
|
|
$USBDriveLetter = $USBDriveLetter + ":\"
|
|
return $USBDriveLetter
|
|
}
|
|
|
|
function Get-HardDrive(){
|
|
$SystemInfo = Get-WmiObject -Class 'Win32_ComputerSystem'
|
|
$Manufacturer = $SystemInfo.Manufacturer
|
|
$Model = $SystemInfo.Model
|
|
WriteLog "Device Manufacturer: $Manufacturer"
|
|
WriteLog "Device Model: $Model"
|
|
WriteLog 'Getting Hard Drive info'
|
|
if ($Manufacturer -eq 'Microsoft Corporation' -and $Model -eq 'Virtual Machine'){
|
|
WriteLog 'Running in a Hyper-V VM. Getting virtual disk on Index 0 and SCSILogicalUnit 0'
|
|
$DiskDrive = Get-WmiObject -Class 'Win32_DiskDrive' | Where-Object {$_.MediaType -eq 'Fixed hard disk media' `
|
|
-and $_.Model -eq 'Microsoft Virtual Disk' `
|
|
-and $_.Index -eq 0 `
|
|
-and $_.SCSILogicalUnit -eq 0
|
|
}
|
|
}
|
|
else{
|
|
WriteLog 'Not running in a VM. Getting physical disk drive'
|
|
$DiskDrive = Get-WmiObject -Class 'Win32_DiskDrive' | Where-Object {$_.MediaType -eq 'Fixed hard disk media' -and $_.Model -ne 'Microsoft Virtual Disk'}
|
|
}
|
|
$DeviceID = $DiskDrive.DeviceID
|
|
$BytesPerSector = $Diskdrive.BytesPerSector
|
|
|
|
# Create a custom object to return both values
|
|
$result = New-Object PSObject -Property @{
|
|
DeviceID = $DeviceID
|
|
BytesPerSector = $BytesPerSector
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
function WriteLog($LogText){
|
|
Add-Content -path $LogFile -value "$((Get-Date).ToString()) $LogText"
|
|
}
|
|
|
|
function Set-DiskpartAnswerFiles($DiskpartFile,$DiskID){
|
|
(Get-Content $DiskpartFile).Replace('disk 0', "disk $DiskID") | Set-Content -Path $DiskpartFile
|
|
}
|
|
|
|
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
|
|
}
|
|
$xml.Save($UnattendFile)
|
|
return $computername
|
|
}
|
|
|
|
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 = $false;
|
|
}
|
|
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 - check scriptlog.txt on the USB drive for more info'
|
|
throw $_
|
|
|
|
} finally {
|
|
Remove-Item -Path $stdOutTempFile, $stdErrTempFile -Force -ErrorAction Ignore
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#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 = '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"
|
|
WriteLog "Physical DeviceID is $PhysicalDeviceID"
|
|
|
|
#Parse DiskID Number
|
|
$DiskID = $PhysicalDeviceID.substring($PhysicalDeviceID.length - 1,1)
|
|
WriteLog "DiskID is $DiskID"
|
|
|
|
#Find FFU Files
|
|
[array]$FFUFiles = @(Get-ChildItem -Path $USBDrive*.ffu)
|
|
$FFUCount = $FFUFiles.Count
|
|
|
|
#If multiple FFUs found, ask which to install
|
|
If ($FFUCount -gt 1) {
|
|
WriteLog "Found $FFUCount FFU Files"
|
|
$array = @()
|
|
|
|
for($i=0;$i -le $FFUCount -1;$i++){
|
|
$Properties = [ordered]@{Number = $i + 1 ; FFUFile = $FFUFiles[$i].FullName}
|
|
$array += New-Object PSObject -Property $Properties
|
|
}
|
|
$array | Format-Table -AutoSize -Property Number, FFUFile
|
|
do {
|
|
try {
|
|
$var = $true
|
|
[int]$FFUSelected = Read-Host 'Enter the FFU number to install'
|
|
$FFUSelected = $FFUSelected -1
|
|
}
|
|
|
|
catch {
|
|
Write-Host 'Input was not in correct format. Please enter a valid FFU number'
|
|
$var = $false
|
|
}
|
|
} until (($FFUSelected -le $FFUCount -1) -and $var)
|
|
|
|
$FFUFileToInstall = $array[$FFUSelected].FFUFile
|
|
WriteLog "$FFUFileToInstall was selected"
|
|
}
|
|
elseif ($FFUCount -eq 1) {
|
|
WriteLog "Found $FFUCount FFU File"
|
|
$FFUFileToInstall = $FFUFiles[0].FullName
|
|
WriteLog "$FFUFileToInstall will be installed"
|
|
}
|
|
else {
|
|
Writelog 'No FFU files found'
|
|
Write-Host 'No FFU files found'
|
|
Exit
|
|
}
|
|
|
|
#FindAP
|
|
$APFolder = $USBDrive + "Autopilot\"
|
|
If (Test-Path -Path $APFolder){
|
|
[array]$APFiles = @(Get-ChildItem -Path $APFolder*.json)
|
|
$APFilesCount = $APFiles.Count
|
|
if ($APFilesCount -ge 1){
|
|
$autopilot = $true
|
|
}
|
|
}
|
|
|
|
|
|
#FindPPKG
|
|
$PPKGFolder = $USBDrive + "PPKG\"
|
|
if (Test-Path -Path $PPKGFolder){
|
|
[array]$PPKGFiles = @(Get-ChildItem -Path $PPKGFolder*.ppkg)
|
|
$PPKGFilesCount = $PPKGFiles.Count
|
|
if ($PPKGFilesCount -ge 1){
|
|
$PPKG = $true
|
|
}
|
|
}
|
|
|
|
#FindUnattend
|
|
$UnattendFolder = $USBDrive + "unattend\"
|
|
$UnattendFilePath = $UnattendFolder + "unattend.xml"
|
|
$UnattendPrefixPath = $UnattendFolder + "prefixes.txt"
|
|
If (Test-Path -Path $UnattendFilePath){
|
|
$UnattendFile = Get-ChildItem -Path $UnattendFilePath
|
|
If ($UnattendFile){
|
|
$Unattend = $true
|
|
}
|
|
}
|
|
If (Test-Path -Path $UnattendPrefixPath){
|
|
$UnattendPrefixFile = Get-ChildItem -Path $UnattendPrefixPath
|
|
If ($UnattendPrefixFile){
|
|
$UnattendPrefix = $true
|
|
}
|
|
}
|
|
|
|
#Ask for device name if unattend exists
|
|
if ($Unattend -and $UnattendPrefix){
|
|
Writelog 'Unattend file found with prefixes.txt. Getting prefixes.'
|
|
$UnattendPrefixes = @(Get-content $UnattendPrefixFile)
|
|
$UnattendPrefixCount = $UnattendPrefixes.Count
|
|
If ($UnattendPrefixCount -gt 1) {
|
|
WriteLog "Found $UnattendPrefixCount Prefixes"
|
|
$array = @()
|
|
for($i=0;$i -le $UnattendPrefixCount -1;$i++){
|
|
$Properties = [ordered]@{Number = $i + 1 ; DeviceNamePrefix = $UnattendPrefixes[$i]}
|
|
$array += New-Object PSObject -Property $Properties
|
|
}
|
|
$array | Format-Table -AutoSize -Property Number, DeviceNamePrefix
|
|
do {
|
|
try {
|
|
$var = $true
|
|
[int]$PrefixSelected = Read-Host 'Enter the prefix number to use for the device name'
|
|
$PrefixSelected = $PrefixSelected -1
|
|
}
|
|
catch {
|
|
Write-Host 'Input was not in correct format. Please enter a valid prefix number'
|
|
$var = $false
|
|
}
|
|
} until (($PrefixSelected -le $UnattendPrefixCount -1) -and $var)
|
|
$PrefixToUse = $array[$PrefixSelected].DeviceNamePrefix
|
|
WriteLog "$PrefixToUse was selected"
|
|
}
|
|
elseif ($UnattendPrefixCount -eq 1) {
|
|
WriteLog "Found $UnattendPrefixCount Prefix"
|
|
$PrefixToUse = $UnattendPrefixes[0]
|
|
WriteLog "Will use $PrefixToUse as device name prefix"
|
|
}
|
|
#Get serial number to append. This can make names longer than 15 characters. Trim any leading or trailing whitespace
|
|
$serial = (Get-CimInstance -ClassName win32_bios).SerialNumber.Trim()
|
|
#Combine prefix with serial
|
|
$computername = ($PrefixToUse + $serial) -replace "\s","" # Remove spaces because windows does not support spaces in the computer names
|
|
#If computername is longer than 15 characters, reduce to 15. Sysprep/unattend doesn't like ComputerName being longer than 15 characters even though Windows accepts it
|
|
If ($computername.Length -gt 15){
|
|
$computername = $computername.substring(0,15)
|
|
}
|
|
$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)
|
|
Writelog "Computer name set to $computername"
|
|
}
|
|
else {
|
|
WriteLog 'No unattend folder found. Device name will be set via PPKG, AP JSON, or default OS name.'
|
|
}
|
|
|
|
#If both AP and PPKG folder found with files, ask which to use.
|
|
If($autopilot -eq $true -and $PPKG -eq $true){
|
|
WriteLog 'Both PPKG and Autopilot json files found'
|
|
Write-Host 'Both Autopilot JSON files and Provisioning packages were found.'
|
|
do {
|
|
try {
|
|
$var = $true
|
|
[int]$APorPPKG = Read-Host 'Enter 1 for Autopilot or 2 for Provisioning Package'
|
|
}
|
|
|
|
catch {
|
|
Write-Host 'Incorrect value. Please enter 1 for Autopilot or 2 for Provisioning Package'
|
|
$var = $false
|
|
}
|
|
} until (($APorPPKG -gt 0 -and $APorPPKG -lt 3) -and $var)
|
|
If ($APorPPKG -eq 1){
|
|
$PPKG = $false
|
|
}
|
|
else{
|
|
$autopilot = $false
|
|
}
|
|
}
|
|
|
|
#If multiple AP json files found, ask which to install
|
|
If ($APFilesCount -gt 1 -and $autopilot -eq $true) {
|
|
WriteLog "Found $APFilesCount Autopilot json Files"
|
|
$array = @()
|
|
|
|
for($i=0;$i -le $APFilesCount -1;$i++){
|
|
$Properties = [ordered]@{Number = $i + 1 ; APFile = $APFiles[$i].FullName; APFileName = $APFiles[$i].Name}
|
|
$array += New-Object PSObject -Property $Properties
|
|
}
|
|
$array | Format-Table -AutoSize -Property Number, APFileName
|
|
do {
|
|
try {
|
|
$var = $true
|
|
[int]$APFileSelected = Read-Host 'Enter the AP json file number to install'
|
|
$APFileSelected = $APFileSelected - 1
|
|
}
|
|
|
|
catch {
|
|
Write-Host 'Input was not in correct format. Please enter a valid AP json file number'
|
|
$var = $false
|
|
}
|
|
} until (($APFileSelected -le $APFilesCount -1) -and $var)
|
|
|
|
$APFileToInstall = $array[$APFileSelected].APFile
|
|
$APFileName = $array[$APFileSelected].APFileName
|
|
WriteLog "$APFileToInstall was selected"
|
|
}
|
|
elseif ($APFilesCount -eq 1 -and $autopilot -eq $true) {
|
|
WriteLog "Found $APFilesCount AP File"
|
|
$APFileToInstall = $APFiles[0].FullName
|
|
$APFileName = $APFiles[0].Name
|
|
WriteLog "$APFileToInstall will be copied"
|
|
}
|
|
else {
|
|
Writelog 'No AP files found or AP was not selected'
|
|
}
|
|
|
|
#If multiple PPKG files found, ask which to install
|
|
If ($PPKGFilesCount -gt 1 -and $PPKG -eq $true) {
|
|
WriteLog "Found $PPKGFilesCount PPKG Files"
|
|
$array = @()
|
|
|
|
for($i=0;$i -le $PPKGFilesCount -1;$i++){
|
|
$Properties = [ordered]@{Number = $i + 1 ; PPKGFile = $PPKGFiles[$i].FullName; PPKGFileName = $PPKGFiles[$i].Name}
|
|
$array += New-Object PSObject -Property $Properties
|
|
}
|
|
$array | Format-Table -AutoSize -Property Number, PPKGFileName
|
|
do {
|
|
try {
|
|
$var = $true
|
|
[int]$PPKGFileSelected = Read-Host 'Enter the PPKG file number to install'
|
|
$PPKGFileSelected = $PPKGFileSelected - 1
|
|
}
|
|
|
|
catch {
|
|
Write-Host 'Input was not in correct format. Please enter a valid PPKG file number'
|
|
$var = $false
|
|
}
|
|
} until (($PPKGFileSelected -le $PPKGFilesCount -1) -and $var)
|
|
|
|
$PPKGFileToInstall = $array[$PPKGFileSelected].PPKGFile
|
|
WriteLog "$PPKGFileToInstall was selected"
|
|
}
|
|
elseif ($PPKGFilesCount -eq 1 -and $PPKG -eq $true) {
|
|
WriteLog "Found $PPKGFilesCount PPKG File"
|
|
$PPKGFileToInstall = $PPKGFiles[0].FullName
|
|
WriteLog "$PPKGFileToInstall will be used"
|
|
}
|
|
else {
|
|
Writelog 'No PPKG files found or PPKG not selected.'
|
|
}
|
|
|
|
#Find Drivers
|
|
$Drivers = $USBDrive + "Drivers"
|
|
If (Test-Path -Path $Drivers)
|
|
{
|
|
#Check if multiple driver folders found, if so, just select one folder to save time/space
|
|
$DriverFolders = Get-ChildItem -Path $Drivers -directory
|
|
$DriverFoldersCount = $DriverFolders.count
|
|
If ($DriverFoldersCount -gt 1)
|
|
{
|
|
WriteLog "Found $DriverFoldersCount driver folders"
|
|
$array = @()
|
|
|
|
for($i=0; $i -le $DriverFoldersCount -1; $i++){
|
|
$Properties = [ordered]@{Number = $i + 1; Drivers = $DriverFolders[$i].FullName}
|
|
$array += New-Object PSObject -Property $Properties
|
|
}
|
|
$array | Format-Table -AutoSize -Property Number, Drivers
|
|
do {
|
|
try {
|
|
$var = $true
|
|
[int]$DriversSelected = Read-Host 'Enter the set of drivers to install'
|
|
$DriversSelected = $DriversSelected - 1
|
|
}
|
|
|
|
catch {
|
|
Write-Host 'Input was not in correct format. Please enter a valid driver folder number'
|
|
$var = $false
|
|
}
|
|
} until (($DriversSelected -le $DriverFoldersCount -1) -and $var)
|
|
|
|
$Drivers = $array[$DriversSelected].Drivers
|
|
WriteLog "$Drivers was selected"
|
|
}
|
|
elseif ($DriverFoldersCount -eq 1) {
|
|
WriteLog "Found $DriverFoldersCount driver folder"
|
|
$Drivers = $DriverFolders.FullName
|
|
WriteLog "$Drivers will be installed"
|
|
}
|
|
else {
|
|
Writelog 'No driver folders found'
|
|
}
|
|
}
|
|
#Partition drive
|
|
Writelog 'Clean Disk'
|
|
try {
|
|
$Disk = Get-Disk -Number $DiskID
|
|
if ($Disk.PartitionStyle -ne "RAW") {
|
|
$Disk | clear-disk -RemoveData -RemoveOEM -Confirm:$false
|
|
}
|
|
}
|
|
catch {
|
|
WriteLog 'Cleaning disk failed. Exiting'
|
|
throw $_
|
|
}
|
|
|
|
Writelog 'Cleaning Disk succeeded'
|
|
|
|
#Apply FFU
|
|
WriteLog "Applying FFU to $PhysicalDeviceID"
|
|
WriteLog "Running command dism /apply-ffu /ImageFile:$FFUFileToInstall /ApplyDrive:$PhysicalDeviceID"
|
|
#In order for Applying Image progress bar to show up, need to call dism directly. Might be a better way to handle, but must have progress bar show up on screen.
|
|
dism /apply-ffu /ImageFile:$FFUFileToInstall /ApplyDrive:$PhysicalDeviceID
|
|
$recoveryPartition = Get-Partition -Disk $Disk | Where-Object PartitionNumber -eq 4
|
|
if ($recoveryPartition) {
|
|
WriteLog 'Setting recovery partition attributes'
|
|
$diskpartScript = @(
|
|
"SELECT DISK $($Disk.Number)",
|
|
"SELECT PARTITION $($recoveryPartition.PartitionNumber)",
|
|
"GPT ATTRIBUTES=0x8000000000000001",
|
|
"EXIT"
|
|
)
|
|
$diskpartScript | diskpart.exe | Out-Null
|
|
WriteLog 'Setting recovery partition attributes complete'
|
|
}
|
|
if($LASTEXITCODE -eq 0){
|
|
WriteLog 'Successfully applied FFU'
|
|
}
|
|
elseif($LASTEXITCODE -eq 1393){
|
|
WriteLog "Failed to apply FFU - LastExitCode = $LastExitCode"
|
|
WriteLog "This is likely due to a mismatched LogicalSectorByteSize"
|
|
WriteLog "BytesPerSector value from Win32_Diskdrive is $BytesPerSector"
|
|
if ($BytesPerSector -eq 4096){
|
|
WriteLog "The FFU build process by default uses a 512 LogicalSectorByteSize. Rebuild the FFU by adding -LogicalSectorByteSize 4096 to the command line"
|
|
}
|
|
elseif($BytesPerSector -eq 512){
|
|
WriteLog "This FFU was likely built with a LogicalSectorByteSize of 4096. Rebuild the FFU by adding -LogicalSectorByteSize 512 to the command line"
|
|
}
|
|
#Copy DISM log to USBDrive
|
|
invoke-process xcopy.exe "X:\Windows\logs\dism\dism.log $USBDrive /Y"
|
|
exit
|
|
}
|
|
else{
|
|
Writelog "Failed to apply FFU - LastExitCode = $LASTEXITCODE also check dism.log on the USB drive for more info"
|
|
#Copy DISM log to USBDrive
|
|
invoke-process xcopy.exe "X:\Windows\logs\dism\dism.log $USBDrive /Y"
|
|
exit
|
|
}
|
|
Get-Disk | Where-Object Number -eq $DiskID | Get-Partition | Where-Object PartitionNumber -eq 3 | Set-Partition -NewDriveLetter W
|
|
|
|
#Copy modified WinRE if folder exists, else copy inbox WinRE
|
|
$WinRE = $USBDrive + "WinRE\winre.wim"
|
|
If (Test-Path -Path $WinRE)
|
|
{
|
|
WriteLog 'Copying modified WinRE to Recovery directory'
|
|
Get-Disk | Where-Object Number -eq $DiskID | Get-Partition | Where-Object Type -eq Recovery | Set-Partition -NewDriveLetter R
|
|
Invoke-Process xcopy.exe "/h $WinRE R:\Recovery\WindowsRE\ /Y"
|
|
WriteLog 'Copying WinRE to Recovery directory succeeded'
|
|
WriteLog 'Registering location of recovery tools'
|
|
Invoke-Process W:\Windows\System32\Reagentc.exe "/Setreimage /Path R:\Recovery\WindowsRE /Target W:\Windows"
|
|
Get-Disk | Where-Object Number -eq $DiskID | Get-Partition | Where-Object Type -eq Recovery | Remove-PartitionAccessPath -AccessPath R:
|
|
WriteLog 'Registering location of recovery tools succeeded'
|
|
}
|
|
#Autopilot JSON
|
|
If ($APFileToInstall){
|
|
WriteLog "Copying $APFileToInstall to W:\windows\provisioning\autopilot"
|
|
Invoke-process xcopy.exe "$APFileToInstall W:\Windows\provisioning\autopilot\"
|
|
WriteLog "Copying $APFileToInstall to W:\windows\provisioning\autopilot succeeded"
|
|
# Rename file in W:\Windows\Provisioning\Autopilot to AutoPilotConfigurationFile.json
|
|
try {
|
|
Rename-Item -Path "W:\Windows\Provisioning\Autopilot\$APFileName" -NewName 'W:\Windows\Provisioning\Autopilot\AutoPilotConfigurationFile.json'
|
|
WriteLog "Renamed W:\Windows\Provisioning\Autopilot\$APFilename to W:\Windows\Provisioning\Autopilot\AutoPilotConfigurationFile.json"
|
|
}
|
|
|
|
catch{
|
|
Writelog "Copying $APFileToInstall to W:\windows\provisioning\autopilot failed with error: $_"
|
|
throw $_
|
|
}
|
|
}
|
|
#Apply PPKG
|
|
If ($PPKGFileToInstall){
|
|
try {
|
|
#Make sure to delete any existing PPKG on the USB drive
|
|
Get-Childitem -Path $USBDrive\*.ppkg | ForEach-Object {
|
|
Remove-item -Path $_.FullName
|
|
}
|
|
WriteLog "Copying $PPKGFileToInstall to $USBDrive"
|
|
Invoke-process xcopy.exe "$PPKGFileToInstall $USBDrive"
|
|
WriteLog "Copying $PPKGFileToInstall to $USBDrive succeeded"
|
|
}
|
|
|
|
catch{
|
|
Writelog "Copying $PPKGFileToInstall to $USBDrive failed with error: $_"
|
|
throw $_
|
|
}
|
|
}
|
|
#Set DeviceName
|
|
If ($computername){
|
|
try{
|
|
$PantherDir = 'w:\windows\panther'
|
|
If (Test-Path -Path $PantherDir){
|
|
Writelog "Copying $UnattendFile to $PantherDir"
|
|
Invoke-process xcopy "$UnattendFile $PantherDir /Y"
|
|
WriteLog "Copying $UnattendFile to $PantherDir succeeded"
|
|
}
|
|
else{
|
|
Writelog "$PantherDir doesn't exist, creating it"
|
|
New-Item -Path $PantherDir -ItemType Directory -Force
|
|
Writelog "Copying $UnattendFile to $PantherDir"
|
|
Invoke-Process xcopy.exe "$UnattendFile $PantherDir"
|
|
WriteLog "Copying $UnattendFile to $PantherDir succeeded"
|
|
}
|
|
}
|
|
catch{
|
|
WriteLog "Copying Unattend.xml to name device failed"
|
|
throw $_
|
|
}
|
|
}
|
|
|
|
#Add Drivers
|
|
#Some drivers can sometimes fail to copy and dism ends up with a non-zero error code. Invoke-process will throw and terminate in these instances.
|
|
If (Test-Path -Path $Drivers)
|
|
{
|
|
WriteLog 'Copying drivers'
|
|
Write-Warning 'Copying Drivers - dism will pop a window with no progress. This can take a few minutes to complete. This is done so drivers are logged to the scriptlog.txt file. Please be patient.'
|
|
Invoke-process dism.exe "/image:W:\ /Add-Driver /Driver:""$Drivers"" /Recurse"
|
|
WriteLog 'Copying drivers succeeded'
|
|
}
|
|
|
|
#Copy DISM log to USBDrive
|
|
WriteLog "Copying dism log to $USBDrive"
|
|
invoke-process xcopy "X:\Windows\logs\dism\dism.log $USBDrive /Y"
|
|
WriteLog "Copying dism log to $USBDrive succeeded"
|
|
|
|
|
|
|
|
|