Creating a WinPE bootable image with Powershell 4

Prerequisites: I did all the following from a Windows 8.1 preview that has Powershell 4.0 installed by default

Step 1: Download ADK 8.1

#Requires -Version 4
#Requires -RunAsAdministrator 

Function Get-ADKFiles {
[CmdletBinding()]    
param(
    [parameter(Mandatory)]
    [system.string]$TargetFolder
)
Begin {
    $HT = @{}
    $HT += @{ ErrorAction = 'Stop'}
    # Validate target folder
    try {
        Get-Item $TargetFolder @HT | Out-Null
    } catch {
        Write-Warning -Message "The target folder specified as parameter does not exist"
        break
    }
}

Process {
    $adkGenericURL = (Invoke-WebRequest -Uri http://go.microsoft.com/fwlink/?LinkID=286749 -MaximumRedirection 0 -ErrorAction SilentlyContinue)
    # There's an expected error saying:
    # The maximum redirection count has been exceeded. 
    # To increase the number of redirections allowed, supply a higher value to the -MaximumRedirection parameter.

    # 302 = redirect as moved temporarily
    if ($adkGenericURL.StatusCode -eq 302) {
    
        # Currently set to http://download.microsoft.com/download/C/B/B/CBBEC593-D142-4478-A4AD-31F7B01899DF/adk/
        $MainURL = $adkGenericURL.Headers.Location

        $AllURLs = DATA {
            ConvertFrom-StringData @'
                0=Toolkit Documentation-x86_en-us.msi
                1=e5f4f4dc519b35948be4500a7dfeab14.cab
                2=d562ae79e25b943d03fc6aa7a65f9b81.cab
                3=56e5d88e2c299be31ce4fc4a604cede4.cab
                4=4fc82a5cedaab58e43b487c17f6ef6f3.cab
                5=dotNetFx45_Full_x86_x64.exe
                6=Application Compatibility Toolkit-x86_en-us.msi
                7=3d610ba2a5a333717eea5f9db277718c.cab
                8=f7699e5a82dcf6476e5ed2d8a3507ace.cab
                9=e65f08c56c86f4e6d7e9358fa99c4c97.cab
                10=0a3a39d2f8a258e1dea4e76da0ec31b8.cab
                11=Microsoft Compatibility Monitor-x86_en-us.msi
                12=Application Compatibility Toolkit-x64_en-us.msi
                13=83bd1072721871ea0bdc4fab780d9382.cab
                14=Microsoft Compatibility Monitor-x86_en-us.msi
                15=Windows Deployment Tools-x86_en-us.msi
                16=bbf55224a0290f00676ddc410f004498.cab
                17=b6758178d78e2a03e1d692660ec642bd.cab
                18=f2a850bce4500b85f37a8aaa71cbb674.cab
                19=a011a13d3157dae2dbdaa7090daa6acb.cab
                20=9050f238beb90c3f2db4a387654fec4b.cab
                21=f480ed0b7d2f1676b4c1d5fc82dd7420.cab
                22=2517aec0259281507bfb693d7d136f30.cab
                23=8624feeaa6661d6216b5f27da0e30f65.cab
                24=eacac0698d5fa03569c86b25f90113b5.cab
                25=630e2d20d5f2abcc3403b1d7783db037.cab
                26=d2611745022d67cf9a7703eb131ca487.cab
                27=a7eb3390a15bcd2c80a978c75f2dcc4f.cab
                28=5d984200acbde182fd99cbfbe9bad133.cab
                29=1439dbcbd472f531c37a149237b300fc.cab
                30=69f8595b00cf4081c2ecc89420610cbd.cab
                31=413a073d16688e177d7536cd2a64eb43.cab
                32=ea9c0c38594fd7df374ddfc620f4a1fd.cab
                33=3b71855dfae6a44ab353293c119908b8.cab
                34=0c48c56ca00155f992c30167beb8f23d.cab
                35=662ea66cc7061f8b841891eae8e3a67c.cab
                36=36e3c2de16bbebad20daec133c22acb1.cab
                37=870d7f92116bc55f7f72e7a9f5d5d6e1.cab
                38=500e0afd7cc09e1e1d6daca01bc67430.cab
                39=56dd07dea070851064af5d29cadfac56.cab
                40=fcc051e0d61320c78cac9fe4ad56a2a2.cab
                41=c98a0a5b63e591b7568b5f66d64dc335.cab
                42=abbeaf25720d61b6b6339ada72bdd038.cab
                43=Windows System Image Manager on amd64-x86_en-us.msi
                44=Windows System Image Manager on x86-x86_en-us.msi
                45=Windows Deployment Customizations-x86_en-us.msi
                46=377a2b6b26ea305c924c25cf942400d6.cab
                47=93ed81ef8cf2e77c6ebc8aba5d95b9cf.cab
                48=4e56c6c11e546d4265da4e9ff7686b67.cab
                49=WimMountAdkSetupX86.exe
                50=WimMountAdkSetupAmd64.exe
                51=WimMountAdkSetupArm.exe
                52=Windows PE x86 x64-x86_en-us.msi
                53=a32918368eba6a062aaaaf73e3618131.cab
                54=9722214af0ab8aa9dffb6cfdafd937b7.cab
                55=aa25d18a5fcce134b0b89fb003ec99ff.cab
                56=0b63b7c537782729483bff2d64a620fa.cab
                57=Windows PE x86 x64 wims-x86_en-us.msi
                58=6d3c63e785ac9ac618ae3f1416062098.cab
                59=690b8ac88bc08254d351654d56805aea.cab
                60=User State Migration Tool-x86_en-us.msi
                61=5ac1863798809c64e85c2535a27a3da6.cab
                62=4d2878f43060bacefdd6379f2dae89b0.cab
                63=Volume Activation Management Tool-x86_en-us.msi
                64=fe43ba83b8d1e88cc4f4bfeac0850c6c.cab
                65=WPTx86-x86_en-us.msi
                66=WPTx64-x86_en-us.msi
                67=WPT Redistributables-x86_en-us.msi
                68=WPTx86-x86_en-us.msi
                69=WPTx64-x86_en-us.msi
                70=WPTarm-arm_en-us.msi
                71=Windows Assessment Toolkit-x86_en-us.msi
                72=0ce2876e9da7f82aac8755701aecfa64.cab
                73=24b9e5f1f97c2f05aa95ee1f671fd3cc.cab
                74=23ca402f61cda3f672b3081da79dab63.cab
                75=Windows Assessment Toolkit (AMD64 Architecture Specific)-x86_en-us.msi
                76=Windows Assessment Toolkit (X86 Architecture Specific)-x86_en-us.msi
                77=Assessments on Client-x86_en-us.msi
                78=b3892d561b571a5b8c81d33fbe2d6d24.cab
                79=3611bd81544efa3deb061718f15aee0c.cab
                80=ed711e0a0102f1716cc073671804eb4c.cab
                81=57007192b3b38fcd019eb88b021e21cc.cab
                82=450f8c76ee138b1d53befd91b735652b.cab
                83=f8f7800500b180b8a2103c40ce94f56a.cab
                84=77adc85e5c49bbd36a91bb751dc55b39.cab
                85=d519967dbb262c80060d9efb5079aa23.cab
                86=bd748d6fbff59b2a58cebdb99c3c6747.cab
                87=3585b51691616d290315769bec85eb6f.cab
                88=fa7c072a4c8f9cf0f901146213ebbce7.cab
                89=cfb8342932e6752026b63046a8d93845.cab
                90=527b957c06e68ebb115b41004f8e3ad0.cab
                91=a03686381bcfa98a14e9c579f7784def.cab
                92=cd23bfdfd9e3dfa8475bf59c2c5d6901.cab
                93=ab3291752bc7a02f158066789e9b0c03.cab
                94=6bdcd388323175da70d836a25654aa92.cab
                95=a1d26d38d4197f7873a8da3a26fc351c.cab
                96=6da2af86cb1227e66cf9bc85f2786782.cab
                97=625aa8d1c0d2b6e8cf41c50b53868ecd.cab
                98=bc1fef9daa903321722c08ce3cf51261.cab
                99=86ae476dfe0498a5b5d1b6f3076412c7.cab
                100=a565f18707816c0d052281154b768ac0.cab
                101=732eefaf52275b7a708311a31c82c814.cab
                102=6dc62760f8235e462db8f91f6eaa1d90.cab
                103=fbcf182748fd71a49becc8bb8d87ba92.cab
                104=1f90b0f7321fab8dcdedaba3b30415f3.cab
                105=c0f42c479da796da513cc5592f0759d3.cab
                106=6d2cfb2c5343c33c8d9e54e7d1f613f9.cab
                107=0302dc615b0a5fd4810430b2cdacb5e3.cab
                108=781e7c95c1b6b277057c9b53b7b5a044.cab
                109=036c618de505eeb40cca35afad6264f5.cab
                110=7ab29d7f105f1e7814198f23b60f8e5d.cab
                111=d5abe4833b23e13dc7038bde9c525069.cab
                112=aa4db181ead2227e76a3d291da71a672.cab
                113=b0189bdfbad208b3ac765f88f21a89df.cab
                114=38d93b8047d5efb04cf01ab7ec66d090.cab
                115=3dc1ed76e5648b575ed559e37a1052f0.cab
                116=3814eaa1d4e897c02ac4ca93e7e7796a.cab
                117=3814eaa1d4e897c02ac4ca93e7e7796a.cab
                118=17c9d60f2bc5bc54c58782d614afcbf0.cab
                119=125b1c8c81e36ec9dbe5abf370ff9919.cab
                120=be7ebc1ac434ead4ab1cf36e3921b70e.cab
                121=268b1a41f6bd2906449944b964bf7393.cab
                122=b5227bb68c3d4641d71b769e3ac606a1.cab
                123=7c11b295fb7f25c6d684b1957e96a226.cab
                124=94cae441bc5628e21814208a973bbb9d.cab
                125=a30d7a714f70ca6aa1a76302010d7914.cab
                126=45c632fb53b95fe3bd58a6242325afa6.cab
                127=0d981f062236baed075df3f42b1747db.cab
                128=4d15138ec839ce36f5b68c16b332920a.cab
                129=7011bf2f8f7f2df2fdd2ed7c82053d7f.cab
                130=0708be5ffbe332f6a1571c929c1322a5.cab
                131=c6babfeb2e1e6f814e70cacb52a0f923.cab
                132=39837d43d71c401e7edc9ba3e569cd69.cab
                133=3eaef6a740a72a55f4a0ac3039d05419.cab
                134=11bdc4a4637c4d7ab86107fd13dcb9c6.cab
                135=8c27542f7954c25af62730fbb1e211d2.cab
                136=1620efa4ffe2a6563530bd0158b17fe6.cab
                137=fd5778f772c39c09c3dd8cd99e7f0543.cab
                138=ac9ff098e23012b74624db792b538132.cab
                139=SQLEXPR_x86_ENU.exe
                140=Windows Assessment Services-x86_en-us.msi
                141=7c195d91008a0a6ad16e535ac228467d.cab
                142=6894c1e1e549c4ab533078e3ff2e92af.cab
                143=eebe1a56de59fd5a57e26205ff825f33.cab
                144=Windows Assessment Services - Client (Server SKU)-x86_en-us.msi
                145=18e5e442fc73caa309725c0a69394a46.cab
                146=5775a15b7f297f3e705a74609cb21bbc.cab
                147=Windows Assessment Services - Client (AMD64 Architecture Specific, Server SKU)-x86_en-us.msi
                148=Assessments on Server-x86_en-us.msi
                149=wasinstaller.exe
                150=Windows Assessment Services - Client (Client SKU)-x86_en-us.msi
                151=Windows Assessment Services - Client (X86 Architecture Specific, Client SKU)-x86_en-us.msi
                152=Windows Assessment Services - Client (AMD64 Architecture Specific, Client SKU)-x86_en-us.msi
                153=Kits Configuration Installer-x86_en-us.msi
'@
        }

        # Create target folders if required as BIT doesn't accept missing folders
        If (-not(Test-Path (Join-Path -Path $TargetFolder -ChildPath Installers))) {
            try {
                New-Item -Path (Join-Path -Path $TargetFolder -ChildPath Installers) -ItemType Directory -Force @HT
                # New-Item -Path $TargetFolder -ItemType Directory -Force -ErrorAction Stop
            } catch {
                Write-Warning -Message "Failed to create folder $($TargetFolder)/Installers"
                break
            }
        }

        # Get adksetup.exe
        iwr -Uri "$($MainURL)adksetup.exe" -OutFile  "$($TargetFolder)\adksetup.exe"

        # Create an job that will downlad our first file
        $job = Start-BitsTransfer -Suspended -Source "$($MainURL)Installers/$($AllURLs['0'])" -Asynchronous -Destination (Join-Path -Path $TargetFolder -ChildPath ("Installers/$($AllURLs['0'])")) 
        
        For ($i = 1 ; $i -lt $AllURLs.Count ; $i++) {
            $URL = $Destination = $null
            $URL = "$($MainURL)Installers/$($AllURLs[$i.ToString()])"
            $Destination = Join-Path -Path (Join-Path -Path $TargetFolder -ChildPath Installers) -ChildPath (([URI]$URL).Segments[-1] -replace '%20'," ")
            # Add-BitsFile http://technet.microsoft.com/en-us/library/dd819411.aspx
            $newjob = Add-BitsFile -BitsJob $job -Source  $URL -Destination $Destination
            Write-Progress -Activity "Adding file $($newjob.FilesTotal)" -Status "Percent completed: " -PercentComplete (($newjob.FilesTotal)*100/($AllURLs.Count))
        }

        # Begin the download and show us the job
        Resume-BitsTransfer  -BitsJob $job -Asynchronous

        # http://msdn.microsoft.com/en-us/library/windows/desktop/ee663885%28v=vs.85%29.aspx
        while ($job.JobState -in @('Connecting','Transferring','Queued')) {
            Write-Progress -activity "Downloading ADK files" -Status "Percent completed: " -PercentComplete ($job.BytesTransferred*100/$job.BytesTotal)
        } 
        Switch($job.JobState) {
         "Transferred" {
            Complete-BitsTransfer -BitsJob $job
            break
        }
         "Error" {
            # List the errors.
            $job | Format-List 
        } 
        default {
            # Perform corrective action.
        } 
        }
    }
}
End {}
}

# Dotsource the above script            
. C:\Get-ADK81.ps1            
            
# Download ADK 8.1            
Get-ADKFiles -TargetFolder C:\ADK.8.1            

Step 2: Install ADK 8.1

$MyADKPath = "C:\ADK.8.1"            
            
If (Test-Path -Path "$MyADKPath\adksetup.exe") {            
    & (gcm "$MyADKPath\adksetup.exe") @(            
     "/installpath", "${env:ProgramFiles(x86)}\Windows Kits\8.1",            
     "/features",            
     "OptionId.DeploymentTools OptionId.WindowsPreinstallationEnvironment",            
     "/norestart","/ceip","off",            
     "/log","$env:TEMP\ADKsetup.log",            
     "/quiet"            
    )            
}            
            
$adkinstall = (Get-Process -Name "adksetup")[0]            
            
while (-not($adkinstall.HasExited)) {            
    $adkinstall.Refresh()            
    Get-Content -Path "$env:TEMP\ADKsetup.log" -Tail 1             
 Start-Sleep -Seconds 1            
}

Step 3: Create a custom WinPE wim image

…and its ISO file as well to be either burnt on a CD/DVD or that can be used as a bootable media of a virtual machine :-)

$Arch = "x64"
$TargetArch = "amd64"
$PEFolder = "C:\WINPE_$($Arch)"
$WAIKLOCATION = "${env:ProgramFiles(x86)}\Windows Kits\8.1\Assessment and Deployment Kit"
if (Test-Path $WAIKLOCATION) {

    $PEFolder,"$PEFolder\ISO","$PEFolder\ISO\Sources","$PEFolder\mount" | ForEach-Object {
        if (-not(Test-Path $_ -PathType Container)) {
            try {
                New-Item -Path $_ -ItemType Container -ErrorAction Stop -Force
            } catch {
                Write-Warning -Message "Failed to create target folders"
            }
        }
    }

    try {
        Copy-Item -Path "$WAIKLOCATION\Windows Preinstallation Environment\$TargetArch\Media\bootmgr*" -Destination "$PEFolder\ISO\" -Force -ErrorAction Stop
        Copy-Item -Path "$WAIKLOCATION\Deployment Tools\$TargetArch\Oscdimg\etfsboot.com" -Destination $PEFolder -Force -ErrorAction Stop
        Copy-Item -Path "$WAIKLOCATION\Deployment Tools\$TargetArch\Oscdimg\efisys.bin" -Destination $PEFolder -Force -ErrorAction Stop
        & (gcm "$env:systemroot\system32\robocopy.exe") @("$WAIKLOCATION\Windows Preinstallation Environment\$TargetArch\Media\boot","$PEFolder\ISO\boot",'/S','/r:0','/Z','/PURGE') | Out-Null
        Copy-Item -Path "$WAIKLOCATION\Windows Preinstallation Environment\$TargetArch\en-us\winpe.wim" -Destination $PEFolder -ErrorAction Stop -Force
    } catch {
        Write-Warning "Copy Failed"
        break
    }

    try {

        # Mount the image
        Get-WindowsImage -ImagePath "$PEFolder\winpe.wim" -ErrorAction Stop | ForEach-Object {
            Mount-WindowsImage -Path "$PEFolder\mount" -ErrorAction Stop -Index $_.ImageIndex -ImagePath $_.ImagePath
        }

        # dism.exe /Get-MountedWimInfo
        Get-WindowsImage -Mounted -ErrorAction Stop

        # Add Packages
        "HTA","Scripting","WMI","Dot3Svc","NetFx","PowerShell","DismCmdlets" | ForEach-Object {
            Add-WindowsPackage -Path "$PEFolder\mount" -PackagePath "$WAIKLOCATION\Windows Preinstallation Environment\$TargetArch\WinPE_OCs\winpe-$_.cab" -ErrorAction Stop
        }

        # Set the keyboard layout to French
        & (gcm "$WAIKLOCATION\Deployment Tools\$TargetArch\DISM\dism.exe") @("/image:$PEFolder\mount",'/Set-InputLocale:040c:0000040c')

        # Increase the writable memory space
        & (gcm "$WAIKLOCATION\Deployment Tools\$TargetArch\DISM\dism.exe") @("/image:$PEFolder\mount",'/Set-ScratchSpace:256')

        # Set the time zone to GMT+1 Brussels, Copenhagen, Madrid, Paris
        & (gcm "$WAIKLOCATION\Deployment Tools\$TargetArch\DISM\dism.exe") @("/image:$PEFolder\mount",'/Set-TimeZone:Romance Standard Time')

        # Unmount
        Get-WindowsImage -Mounted -ErrorAction Stop | ForEach-Object {
            # Save-WindowsImage -Path $_.ImagePath
            Dismount-WindowsImage -Path $_.Path -Save -ErrorAction Stop
        }

        # Create the ISO file    
        Copy-Item -Path "$PEFolder\winpe.wim" -Destination "$PEFolder\ISO\Sources\boot.wim" -ErrorAction Stop

        $BOOTDATA='2#p0,e,b"{0}"#pEF,e,b"{1}"' -f "$PEFolder\etfsboot.com","$PEFolder\efisys.bin"
        & (gcm "$WAIKLOCATION\Deployment Tools\amd64\Oscdimg\oscdimg.exe") @("-bootdata:$BOOTDATA",'-u1','-udfver102',"$PEFolder\ISO","$PEFolder\winpe.iso")

    } catch {
        Write-Warning "Failed to create ISO image"
    }
}

Step 4: Prepare a USB stick

# Erase all the data on the USB stick ~ diskpart / clean            
(Get-Disk)[-1] | Clear-Disk -RemoveData:$true            

(Get-Disk)[-1] | Get-Partition            
# Create an active partition            
(Get-Disk)[-1] | New-Partition -UseMaximumSize:$true -IsActive -Verbose            

# List the new volume            
(Get-Disk)[-1] | Get-Partition | Get-Volume            
# Simulate the format of the volume            
(Get-Disk)[-1] | Get-Partition | Get-Volume | Format-Volume -FileSystem NTFS -WhatIf            
# Format the new partition            
(Get-Disk)[-1] | Get-Partition | Get-Volume | Format-Volume -FileSystem NTFS

If the partition doesn’t get a drive letter assigned automatically, you can do:

(Get-Disk)[-1] | Get-Partition  | Set-Partition -NewDriveLetter Z

Move the content to the USB media:

robocopy --% C:\WINPE_x64\ISO Z:\ /S /r:0 /Z

Booting from the ISO file a VM with 1024MB memory and no HDD attached



About these ads

2 thoughts on “Creating a WinPE bootable image with Powershell 4

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s