Last active
September 25, 2023 20:48
-
-
Save Chirishman/2f6c287408062640bdea0edfdc8ab807 to your computer and use it in GitHub Desktop.
MakeWinPEMedia - Replacement for Existing w/ PowerShell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
setlocal | |
rem | |
rem Set variables for local use | |
rem | |
set TEMPL=media | |
set FWFILES=fwfiles | |
set DISKPARTSCRIPT=%TMP%\UFDFormatDiskpartScript.txt | |
set EXITCODE=0 | |
rem | |
rem Input validation | |
rem | |
if /i "%1"=="/?" goto usage | |
if /i "%1"=="" goto usage | |
if /i "%~2"=="" goto usage | |
if /i "%~3"=="" goto usage | |
if /i not "%~5"=="" goto usage | |
if /i not "%1"=="/UFD" ( | |
if /i not "%1"=="/ISO" goto usage | |
) | |
rem | |
rem Based on parameters input, assign local variables | |
rem | |
if /i "%~2"=="/f" ( | |
set FORCED=1 | |
set WORKINGDIR=%~3 | |
set DEST=%~4 | |
) else ( | |
set FORCED=0 | |
set WORKINGDIR=%~2 | |
set DEST=%~3 | |
) | |
rem | |
rem Make sure the working directory exists | |
rem | |
if not exist "%WORKINGDIR%" ( | |
echo ERROR: Working directory does not exist: "%WORKINGDIR%". | |
goto fail | |
) | |
rem | |
rem Make sure the working directory is valid as per our requirements | |
rem | |
if not exist "%WORKINGDIR%\%TEMPL%" ( | |
echo ERROR: Working directory is not valid: "%WORKINGDIR%". | |
goto fail | |
) | |
if not defined %TMP% ( | |
set DISKPARTSCRIPT=.\UFDFormatDiskpartScript.txt | |
) | |
if /i "%1"=="/UFD" goto UFDWorker | |
if /i "%1"=="/ISO" goto ISOWorker | |
rem | |
rem UFD section of the script, for creating bootable WinPE UFD | |
rem | |
:UFDWorker | |
rem | |
rem Make sure the user has administrator privileges | |
rem These will be required to format the drive and set the boot code | |
rem | |
set ADMINTESTDIR=%WINDIR%\System32\Test_%RANDOM% | |
mkdir "%ADMINTESTDIR%" 2>NUL | |
if errorlevel 1 ( | |
echo ERROR: You need to run this command with administrator privileges. | |
goto fail | |
) else ( | |
rd /s /q "%ADMINTESTDIR%" | |
) | |
rem | |
rem Make sure the destination refers to a storage drive, | |
rem and is not any other type of path | |
rem | |
echo %DEST%| findstr /B /E /I "[A-Z]:" >NUL | |
if errorlevel 1 ( | |
echo ERROR: Destination needs to be a disk drive, e.g F:. | |
goto fail | |
) | |
rem | |
rem Make sure the destination path exists | |
rem | |
if not exist "%DEST%" ( | |
echo ERROR: Destination drive "%DEST%" does not exist. | |
goto fail | |
) | |
if %FORCED% EQU 1 goto UFDWorker_FormatUFD | |
rem | |
rem Confirm from the user that they want to format the drive | |
rem | |
echo WARNING, ALL DATA ON DISK DRIVE %DEST% WILL BE LOST! | |
choice /M "Proceed with Format " | |
if errorlevel 2 goto UFDWorker_NoFormatUFD | |
if errorlevel 1 goto UFDWorker_FormatUFD | |
:UFDWorker_NoFormatUFD | |
echo UFD %DEST% will not be formatted; exiting. | |
goto cleanup | |
:UFDWorker_FormatUFD | |
rem | |
rem Format the volume using diskpart, in FAT32 file system | |
rem | |
echo select volume=%DEST% > "%DISKPARTSCRIPT%" | |
echo format fs=fat32 label="WinPE" quick >> "%DISKPARTSCRIPT%" | |
echo active >> "%DISKPARTSCRIPT%" | |
echo Formatting %DEST%... | |
echo. | |
diskpart /s "%DISKPARTSCRIPT%" >NUL | |
set DISKPARTERR=%ERRORLEVEL% | |
del /F /Q "%DISKPARTSCRIPT%" | |
if errorlevel 1 ( | |
echo WARNING: Failed to delete temporary DiskPart script "%DISKPARTSCRIPT%". | |
) | |
if %DISKPARTERR% NEQ 0 ( | |
echo ERROR: Failed to format "%DEST%"; DiskPart errorlevel %DISKPARTERR%. | |
goto fail | |
) | |
rem | |
rem Set the boot code on the volume using bootsect.exe | |
rem | |
echo Setting the boot code on %DEST%... | |
echo. | |
bootsect.exe /nt60 %DEST% /force /mbr >NUL | |
if errorlevel 1 ( | |
echo ERROR: Failed to set the boot code on %DEST%. | |
goto fail | |
) | |
rem | |
rem We first decompress the source directory that we are copying from. | |
rem This is done to work around an issue with xcopy when working with | |
rem compressed NTFS source directory. | |
rem | |
rem Note that this command will not cause an error on file systems that | |
rem do not support compression - because we do not use /f. | |
rem | |
compact /u "%WORKINGDIR%\%TEMPL%" >NUL | |
if errorlevel 1 ( | |
echo ERROR: Failed to decompress "%WORKINGDIR%\%TEMPL%". | |
goto fail | |
) | |
rem | |
rem Copy the media files from the user-specified working directory | |
rem | |
echo Copying files to %DEST%... | |
echo. | |
xcopy /herky "%WORKINGDIR%\%TEMPL%\*.*" "%DEST%\" >NUL | |
if errorlevel 1 ( | |
echo ERROR: Failed to copy files to "%DEST%\". | |
goto fail | |
) | |
goto success | |
rem | |
rem ISO section of the script, for creating bootable ISO image | |
rem | |
:ISOWorker | |
rem | |
rem Make sure the destination refers to an ISO file, ending in .ISO | |
rem | |
echo %DEST%| findstr /E /I "\.iso" >NUL | |
if errorlevel 1 ( | |
echo ERROR: Destination needs to be an .ISO file. | |
goto fail | |
) | |
if not exist "%DEST%" goto ISOWorker_OscdImgCommand | |
if %FORCED% EQU 1 goto ISOWorker_CleanDestinationFile | |
rem | |
rem Confirm from the user that they want to overwrite the existing ISO file | |
rem | |
choice /M "Destination file %DEST% exists, overwrite it " | |
if errorlevel 2 goto ISOWorker_DestinationFileExists | |
if errorlevel 1 goto ISOWorker_CleanDestinationFile | |
:ISOWorker_DestinationFileExists | |
echo Destination file %DEST% will not be overwritten; exiting. | |
goto cleanup | |
:ISOWorker_CleanDestinationFile | |
rem | |
rem Delete the existing ISO file | |
rem | |
del /F /Q "%DEST%" | |
if errorlevel 1 ( | |
echo ERROR: Failed to delete "%DEST%". | |
goto fail | |
) | |
:ISOWorker_OscdImgCommand | |
rem | |
rem Set the correct boot argument based on availability of boot apps | |
rem | |
set BOOTDATA=1#pEF,e,b"%WORKINGDIR%\%FWFILES%\efisys.bin" | |
if exist "%WORKINGDIR%\%FWFILES%\etfsboot.com" ( | |
set BOOTDATA=2#p0,e,b"%WORKINGDIR%\%FWFILES%\etfsboot.com"#pEF,e,b"%WORKINGDIR%\%FWFILES%\efisys.bin" | |
) | |
rem | |
rem Create the ISO file using the appropriate OSCDImg command | |
rem | |
echo Creating %DEST%... | |
echo. | |
oscdimg -bootdata:%BOOTDATA% -u1 -udfver102 "%WORKINGDIR%\%TEMPL%" "%DEST%" >NUL | |
if errorlevel 1 ( | |
echo ERROR: Failed to create "%DEST%" file. | |
goto fail | |
) | |
goto success | |
:success | |
set EXITCODE=0 | |
echo. | |
echo Success | |
echo. | |
goto cleanup | |
:usage | |
set EXITCODE=1 | |
echo Creates bootable WinPE USB flash drive or ISO file. | |
echo. | |
echo MakeWinPEMedia {/ufd ^| /iso} [/f] ^<workingDirectory^> ^<destination^> | |
echo. | |
echo /ufd Specifies a USB Flash Drive as the media type. | |
echo NOTE: THE USB FLASH DRIVE WILL BE FORMATTED. | |
echo /iso Specifies an ISO file (for CD or DVD) as the media type. | |
echo /f Suppresses prompting to confirm formatting the UFD | |
echo or overwriting existing ISO file. | |
echo workingDirectory Specifies the working directory created using copype.cmd | |
echo The contents of the ^<workingDirectory^>\media folder | |
echo will be copied to the UFD or ISO. | |
echo destination Specifies the UFD volume or .ISO path and file name. | |
echo. | |
echo Examples: | |
echo MakeWinPEMedia /UFD C:\WinPE_amd64 G: | |
echo MakeWinPEMedia /UFD /F C:\WinPE_amd64 H: | |
echo MakeWinPEMedia /ISO C:\WinPE_x86 C:\WinPE_x86\WinPE_x86.iso | |
goto cleanup | |
:fail | |
set EXITCODE=1 | |
goto cleanup | |
:cleanup | |
endlocal & exit /b %EXITCODE% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Still requires oscdimg.exe in your path | |
function New-WinPEMedia { | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory)] | |
[ValidateSet('USB','ISO')] | |
[string]$OutputType, | |
[Parameter(Mandatory)] | |
[string]$PESource, | |
[Parameter(Mandatory)] | |
[string]$OutputPath, | |
[Parameter()] | |
[switch]$Force | |
) | |
if (-not (Test-Path -Path $PESource)){ | |
Write-Error -Category ReadError -Message "Working Directory Not Found: $PESource" -ErrorAction Stop | |
} | |
$MediaFolder = Join-Path -Path $PESource -ChildPath 'media' | |
$FWFolder = Join-Path -Path $PESource -ChildPath 'fwfiles' | |
$EFISYSPath = Join-Path -Path $FWFolder -ChildPath 'efisys.bin' | |
$ETFSBootPath = (Join-Path -Path $FWFolder -ChildPath 'etfsboot.com') | |
if ($OutputType -eq 'USB'){ | |
if ($outputpath -match '^\w(|:(|\\))$' -and ( $Volume = Get-Volume $OutputPath -ErrorAction SilentlyContinue)){ | |
if ([System.Security.Principal.WindowsPrincipal]::new([System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { | |
Format-Volume -Confirm:$(-not $Force) -Force:$Force -FileSystem FAT32 -NewFileSystemLabel 'WinPE' -DriveLetter $Volume.DriveLetter | |
$Volume | Get-Partition | Set-Partition -IsActive $true | |
try { | |
bootsect.exe /nt60 (-join($Volume.DriveLetter,':')) /force /mbr | |
} catch { | |
Write-Error -Category WriteError -Message "Failed to set the boot code on $OutputPath" -ErrorAction Stop | |
} | |
$file = Get-WmiObject -Query "SELECT * FROM CIM_DataFile WHERE Name='C:\\scripts\\test.vhd'" | |
Get-ChildItem -Path $MediaFolder -Recurse -File | %{Get-WmiObject -Query "SELECT * FROM CIM_DataFile WHERE Name='$($_.FullName -replace '\\','\\')'"} | ?{$_.Compressed} | %{$_.Decompress()} | %{$_.Uncompress()} | |
Get-ChildItem -path $MediaFolder | Copy-Item -Destination $OutputPath -Recurse | |
} | |
else { | |
Write-Error -Category PermissionDenied -Message 'You need to run this command with administrator privileges' -ErrorAction Stop | |
} | |
} else { | |
Write-Error -Category OpenError -Message "Target Drive Not Found: $OutputPath" -ErrorAction Stop | |
} | |
} elseif ($OutputType -eq 'ISO') { | |
#ISO behavior Here | |
if (-not ($OutputPath -match '\.iso$')){ | |
Write-Error -Category InvalidArgument -Message "Invalid or Absent File Extension. Path must end in .iso" -ErrorAction Stop | |
} elseif (Test-Path -Path $OutputPath -PathType Leaf) { | |
Remove-Item -Path $OutputPath -Force:$Force -Confirm:$(-not $Force) | |
if (Test-Path -Path $OutputPath -PathType Leaf){ | |
Write-Error -Category InvalidResult -Message "Item $OutputPath will not be overwritten or deletion attempt failed; exiting" -ErrorAction Stop | |
} | |
} elseif (-not (Test-Path -Path ((($OutputPath -split '\\') | select -SkipLast 1) -join '\') -PathType Container)) { | |
Write-Error -Category InvalidArgument -Message "Invalid Output Path - Parent Folder Does Not Exist" -ErrorAction Stop | |
} | |
$BOOTDATA = $( | |
if (Test-Path -Path $ETFSBootPath) { | |
"2#p0,e,b""$ETFSBootPath""#pEF,e,b""$EFISYSPath""" | |
} else { | |
"1#pEF,e,b""$EFISYSPath""" | |
} | |
) | |
$FWFolder | |
try { | |
[void]$( | |
oscdimg -bootdata:$BOOTDATA -u1 -udfver102 $MediaFolder $OutputPath | |
) | |
} catch { | |
Write-Error -Category WriteError -Message "Failed to create $OutputPath" -ErrorAction Stop | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment