Skip to content

Instantly share code, notes, and snippets.

@Marcuzzo
Created January 13, 2016 12:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Marcuzzo/e336e5d3a44f012029ff to your computer and use it in GitHub Desktop.
Save Marcuzzo/e336e5d3a44f012029ff to your computer and use it in GitHub Desktop.
a simple script to build a WinPE image ( this is far from perfect but does the job for me )
# requires -Version 4
# Requires -RunAsAdministrator
<#
.SYNOPSIS
Create a custom WinPE image from scratch
.DESCRIPTION
This CmdLet allows you to create a custom WinPE image from Scratch
.EXAMPLE
Another example of how to use this cmdlet
.NOTES
ScriptName : Build_WinPE.ps1
Author : Marco Micozzi
Date :
License : GPL v3
Requirements: ADK
#>
#region Parameters
[CmdLetBinding()]
Param(
[Parameter(Mandatory = $true)]
[ValidateSet('8.1', '10')]
[string] $Version,
[Parameter( HelpMessage = 'The CPU architecture, can be either x86, amd64 or ia64.', Mandatory = $false)]
[ValidateSet('x86', 'amd64', 'ia64')]
[Alias('CPU', 'arc', 'proc')]
[string] $Architecture = 'amd64',
[Parameter( HelpMessage = 'Set the language used in the WinPE environment. Defaults to en-us')]
[ValidateSet('en-us', 'en-gb', 'nl-be', 'nl-nl',
'de-de', 'it-it', 'fr-fr', 'fr-be')]
[Alias('inlang')]
[string] $InputLanguage = 'nl-be',
[Parameter( HelpMessage = 'Set the language used in the WinPE environment. Defaults to en-us')]
[ValidateSet('en-us', 'en-gb', 'nl-be', 'nl-nl',
'de-de', 'it-it', 'fr-fr', 'fr-be')]
[Alias('syslang')]
[string] $SystemLanguage = 'en-us',
[Parameter( HelpMessage = 'The label of the produced ISO image file.')]
[Alias('Label', 'lbl')]
[string] $ISOLabel = 'Custom WinPE',
[Parameter( HelpMessage = 'The temporary directory where the PE will be built.')]
[Alias('BuildDir', 'blddir', 'bldir')]
[string] $BuildDirectory = 'C:\Temp\WinPE',
[Parameter( HelpMessage = 'Clean the BuildDirectory before starting the script')]
[switch] $Clean,
[Parameter( HelpMessage = 'Define a list of optional packages to add to the WinPE')]
[Alias('pkg')]
[ValidateSet('HTA', 'WMI', 'Scripting', 'NetFX', 'PowerShell',
'StorageWMI', 'DismCmdlets', 'LegacySetup')]
[string[]] $Packages = @('HTA', 'WMI', 'NetFX', 'Scripting', 'PowerShell', 'StorageWMI', 'DismCmdlets'),
[Parameter( HelpMessage = 'Indicates that an ISO should be created for the custom WinPE.' )]
[Alias('Make', 'Build', 'm')]
[switch] $MakeIso
)
# BUG: the script fails if the build directory exists
#endregion Parameters
#region Imports
# Import the module with common functions
#Import-Module $PSScriptRoot\common.psm1
#endregion Imports
#region Variables
[string] $MountDirectory = "$BuildDirectory\mount"
[string] $BootWIM = "$MountDirectory\ISO\sources\boot.wim"
#System32 is used in all Architecture types for our purposes.
[string] $SystemPath = "$MountDirectory\Windows\System32"
#endregion
#region Set Path
[string] $KitsRoot = "C:\Program Files (x86)\Windows Kits\$Version" #Get-KitsRoot
#[string] $ADKInstallationPath = "$(Get-ProgramFiles32)\Windows Kits\8.1\Assessment and Deployment Kit"
[string] $ADKPath = "$KitsRoot\Assessment and Deployment Kit"
[string] $DandIRoot = "$ADKPath\Deployment Tools"
[string] $WinPERoot = "$ADKPath\Windows Preinstallation Environment"
[System.Environment]::SetEnvironmentVariable("WinPERoot", $WinPERoot, "process")
# not sure if I should be using this here: $env:PROCESSOR_ARCHITECTURE
[string] $DismRoot = "$DandIRoot\$Architecture\DISM"
[string] $BCDBootRoot = "$DandIRoot\$Architecture\BCDBoot"
[string] $ImagingRoot = "$DandIRoot\$Architecture\Imaging"
[string] $OSCDImgRoot = "$DandIRoot\$Architecture\Oscdimg"
[System.Environment]::SetEnvironmentVariable("OSCDImgRoot", $OSCDImgRoot, "process")
[string] $WdsmcastRoot = "$DandIRoot\$Architecture\Wdsmcast"
[string] $HelpIndexerRoot = "$DandIRoot\HelpIndexer"
[string] $WSIMRoot = "$DandIRoot\WSIM"
[string] $NewPath = "$DISMRoot;$ImagingRoot;$BCDBootRoot;$OSCDImgRoot;$WdsmcastRoot;$HelpIndexerRoot;$WSIMRoot;$WinPERoot;"
# store the old path
[string] $OldPath = $Env:Path
[System.Environment]::SetEnvironmentVariable("PATH", $NewPath + "$env:SystemRoot\System32", "process")
#$Env:Path = $NewPath
#endregion
if ( Get-Module -Name Dism ) {
Remove-Module -Name Dism
}
Import-Module $DismRoot
Clear-WindowsCorruptMountPoint | Out-Null
# clean up all mounted images
Get-WindowsImage -Mounted | ForEach-Object {
Write-Host "Unmounting old mount in '$($_.Path)'"
Dismount-WindowsImage -Path $_.MountPath -Discard | Out-Null
}
# clean the temp dir
if ( $Clean.IsPresent ) {
if ( Test-Path -Path $BuildDirectory ) {
Remove-Item -Path $BuildDirectory -Recurse -Force
}
}
#Run Dism Cleanup... not sure if needed...?
Write-Host "Running Imagex /Cleanup..." -NoNewline
Dism /Cleanup-Wim
Write-Host " done" -ForegroundColor Green
#Run CopyPE.cmd to create the initial WinPE Image
Write-Host "Running CopyPE..." -NoNewline
copype.cmd $Architecture $BuildDirectory
Write-Host " done" -ForegroundColor Green
Write-Host "Mount the image" -NoNewline
Try {
$Mount = Mount-WindowsImage -ImagePath "$BuildDirectory\media\sources\boot.wim" -Index 1 -Path $MountDirectory
Write-Host " done" -ForegroundColor Green
}
Catch{
$message = "TRAPPED: {0}: '{1}'" -f ($_.Exception.GetType().FullName), ($_.Exception.Message)
Write-host "FAILED" -ForegroundColor Red
Exit
}
Write-Host "Adding Packages" -ForegroundColor Yellow
$Packages | ForEach-Object {
[string] $Package = "$WinPERoot\$Architecture\WinPE_OCs\WinPE-$_.cab"
[string] $PackageLang = "$WinPERoot\$Architecture\WinPE_OCs\$SystemLanguage\WinPE-$($_)_$SystemLanguage.cab"
if ( ( Test-Path -Path $Package ) -and ( Test-Path -Path $PackageLang ))
{
Write-Host "`tAdding $_" -ForegroundColor Yellow
Try{
Add-WindowsPackage -PackagePath $Package -Path $MountDirectory -IgnoreCheck | Out-Null
Add-WindowsPackage -PackagePath $PackageLang -Path $MountDirectory -IgnoreCheck | Out-Null
Write-Host "Done" -ForegroundColor Green
}
Catch{
Write-Host "Failed" -ForegroundColor Red
}
}
else
{
Write-Error "couldn't find: '$Package' or '$PackageLang'!"
}
}
Write-Host 'Set the input language' -ForegroundColor Yellow
Dism /image:"$MountDirectory" /Set-SysLocale:"$SystemLanguage"
Dism /image:"$MountDirectory" /Set-UserLocale:"$SystemLanguage"
Dism /image:"$MountDirectory" /Set-InputLocale:"$InputLanguage"
Copy-Item -Path "C:\Windows\System32\whoami.exe" -Destination "$SystemPath" -Force
Copy-Item -Path "C:\Windows\System32\shutdown.exe" -Destination "$SystemPath" -Force
#Copy-Item -Path "C:\Projects\Personal\NEW\todo\WinPE\Script\utilities\Winpeshl.ini" -Destination "$MountDirectory\Windows\System32\"
Write-Host 'Unmount the image' -NoNewline
Dismount-WindowsImage -Path $MountDirectory -Save
Write-Host " done" -ForegroundColor Green
if ( $MakeIso ){
Write-Host "Building ISO File in '$BuildDirectory\WinPE_$Architecture.iso'" -ForegroundColor Yellow
[string] $BOOTDATA="1#pEF,e,b`"$BuildDirectory\fwfiles\efisys.bin`""
if ( Test-Path -Path "$BuildDirectory\fwfiles\etfsboot.com" ){
$BOOTDATA="2#p0,e,b`"$BuildDirectory\fwfiles\etfsboot.com`"#pEF,e,b`"$BuildDirectory\fwfiles\efisys.bin`""
}
oscdimg -l"$ISOLabel" -bootdata:$BOOTDATA -u1 -udfver102 "$BuildDirectory\media" "$BuildDirectory\WinPE_$Architecture.iso"
}
[System.Environment]::SetEnvironmentVariable("PATH", $OldPath, "process")
Remove-Module Dism
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment