You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
9.7 KiB

import-module dism -verbose:$false
$OfficeVersionId = @{
o2013 = "o2013"
}
$IsoUrls = @{
$WindowsVersionId.w81 = @{
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X86FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X86FREE_EN-US_DV9.ISO"
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO"
}
$WindowsVersionId.w10 = @{
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/C/3/9/C399EEA8-135D-4207-92C9-6AAB3259F6EF/10240.16384.150709-1700.TH1_CLIENTENTERPRISEEVAL_OEMRET_X86FRE_EN-US.ISO"
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/C/3/9/C399EEA8-135D-4207-92C9-6AAB3259F6EF/10240.16384.150709-1700.TH1_CLIENTENTERPRISEEVAL_OEMRET_X64FRE_EN-US.ISO"
}
$WindowsVersionId.w10ltsb = @{
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/6/2/4/624ECF83-38A6-4D64-8758-FABC099503DC/10240.16384.150709-1700.TH1_CLIENTENTERPRISE_S_EVAL_X86FRE_EN-US.ISO"
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/6/2/4/624ECF83-38A6-4D64-8758-FABC099503DC/10240.16384.150709-1700.TH1_CLIENTENTERPRISE_S_EVAL_X64FRE_EN-US.ISO"
}
$WindowsVersionId.server2012r2 = @{
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/6/2/A/62A76ABB-9990-4EFC-A4FE-C7D698DAEB96/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO"
}
$OfficeVersionId.o2013 = @{
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/2/9/C/29CC45EF-4CDA-4710-9FB3-1489786570A1/OfficeProfessionalPlus_x86_en-us.img"
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/2/9/C/29CC45EF-4CDA-4710-9FB3-1489786570A1/OfficeProfessionalPlus_x64_en-us.img"
}
}
# TODO: Copy-ItemAndExclude
# function Copy-ItemAndExclude {
# [cmdletbinding()] param(
# [parameter(mandatory=$true)] [string] $path,
# [parameter(mandatory=$true)] [string] $destination,
# [parameter(mandatory=$true)] [string[]] $exclude,
# [switch] $force
# )
# $path = resolve-path $path | select -expand path
# $sourceItems = Get-ChildItem -Path $path -Recurse -Exclude $exclude
# Write-EventLogWrapper "Found $($sourceItems.count) items to copy from '$path'"
# #$sourceItems | copy-item -force:$force -destination {Join-Path $destination $_.FullName.Substring($path.length)}
# $sourceItems | copy-item -force:$force -destination {
# if ($_.GetType() -eq [System.IO.FileInfo]) {
# Join-Path $destination $_.FullName.Substring($path.length)
# }
# else {
# Join-Path $destination $_.Parent.FullName.Substring($path.length)
# }
# }
# }
<#
.description
Get the path of the Windows ADK or AIK or whatever the fuck they're calling it from a format string
- {0} is always the WAIK directory
- e.g. "C:\Program Files (x86)\Windows Kits\8.1\"
- e.g. "X:\Program Files\Windows Kits\8.0"
- {1} is always the host architecture (x86 or amd64)
- i THINK this is right, but I don't understand WHY. why do you need an amd64 version of oscdimg.exe?
- however, there are arm executables lying around, and i definitely can't execute those. wtf?
So we expect a string like "{0}\bin\{1}\wsutil.exe"
#>
function Get-AdkPath {
[cmdletbinding()] param(
[parameter(mandatory=$true)] [string] $pathFormatString
)
$adkPath = ""
$possibleAdkPaths = @("${env:ProgramFiles(x86)}\Windows Kits\8.1","${env:ProgramFiles}\Windows Kits\8.1")
$possibleAdkPaths |% { if (test-path $_) { $adkPath = $_ } }
if (-not $adkPath) { throw "Could not find the Windows Automated Installation Kit" }
Write-EventLogWrapper "Found the WAIK at '$adkPath'"
$arch = Get-OSArchitecture
switch ($arch) {
$ArchitectureId.i386 {
$formatted = $pathFormatString -f $adkPath,$waikArch
if (test-path $formatted) { return $formatted }
}
$ArchitectureId.amd64 {
foreach ($waikArch in @("amd64","x64")) {
$formatted = $pathFormatString -f $adkPath,$waikArch
if (test-path $formatted) { return $formatted }
}
}
default {
throw "Could not determine architecture of '$arch'"
}
}
throw "Could not resolve format string '$pathFormatString' to an existing path"
}
function New-WindowsInstallMedia { # TODO fixme not sure I wanna handle temp dirs this way??
[cmdletbinding()] param(
[parameter(mandatory=$true)] [string] $sourceIsoPath,
[parameter(mandatory=$true)] [string] $installMediaTemp, # WILL BE DELETED
[parameter(mandatory=$true)] [string] $installWimPath, # your new install.wim file
[parameter(mandatory=$true)] [string] $outputIsoPath
)
$oscdImgPath = Get-AdkPath "{0}\Assessment and Deployment Kit\Deployment Tools\{1}\Oscdimg\oscdimg.exe"
$installWimPath = resolve-path $installWimPath | select -expand path
$installMediaTemp = mkdir -force $installMediaTemp | select -expand fullname
$outputIsoParentPath = split-path $outputIsoPath -parent
$outputIsoFilename = split-path $outputIsoPath -leaf
$outputIsoParentPath = mkdir -force $outputIsoParentPath | select -expand fullname
if (test-path $installMediaTemp) { rm -recurse -force $installMediaTemp }
mkdir -force $installMediaTemp | out-null
$diskVol = get-diskimage -imagepath $sourceIsoPath | get-volume
if (-not $diskVol) {
mount-diskimage -imagepath $sourceIsoPath
$diskVol = get-diskimage -imagepath $sourceIsoPath | get-volume
}
$driveLetter = $diskVol | select -expand DriveLetter
$existingInstallMediaDir = "${driveLetter}:"
# TODO: the first copy here copies the original install.wim, and the second copies the new one over it
# this is really fucking dumb right? but then, THIS is way fucking dumber:
# http://stackoverflow.com/questions/731752/exclude-list-in-powershell-copy-item-does-not-appear-to-be-working
# PS none of those solutions are generic enough to get included so fuck it
copy-item -recurse -path "$existingInstallMediaDir\*" -destination "$installMediaTemp" -verbose:$verbose
remove-item -force -path "$installMediaTemp\sources\install.wim"
copy-item -path $installWimPath -destination "$installMediaTemp\sources\install.wim" -force -verbose:$verbose
$etfsBoot = resolve-path "$existingInstallMediaDir\boot\etfsboot.com" | select -expand Path
$oscdimgCall = '& "{0}" -m -n -b"{1}" "{2}" "{3}"' -f @($oscdImgPath, $etfsBoot, $installMediaTemp, $outputIsoPath)
Write-EventLogWrapper "Calling OSCDIMG: '$oscdimgCall"
Invoke-ExpressionAndCheck $oscdimgCall -verbose:$verbose
dismount-diskimage -imagepath $sourceIsoPath
}
<#
.notes
The install.wim file doesn't (ever? sometimes?) denote architecture in its image names, but boot.wim (always? usually?) does
#>
function Get-BootWimArchitecture {
[cmdletbinding()] param(
[parameter(mandatory=$true)] $wimFile
)
$bootWimInfo = Get-WindowsImage -imagePath $wimFile -verbose:$verbose
$arch = $null
if (-not $bootWimInfo) { throw "Got no information for wimfile at '$wimFile'"}
elseif ($bootWimInfo[0].ImageName -match "x86") { $arch = $ArchitectureId.i386 }
elseif ($bootWimInfo[0].ImageName -match "x64") { $arch = $ArchitectureId.amd64 }
else { throw "Could not determine architecture for '$wimFile'"}
write-verbose "Found an architecture of '$arch' for '$wimFile'"
return $arch
}
function Apply-WindowsUpdatesToIso {
[cmdletbinding()] param (
[parameter(mandatory=$true)] [string] $inputIso,
[parameter(mandatory=$true)] [string] $outputIso,
[parameter(mandatory=$true)] [string] $wsusOfflineDir,
[parameter(mandatory=$true)] [string] $wimMountDir
)
$myWimMounts = @()
mount-diskimage -imagepath $inputIso
$mountedDrive = get-diskimage -imagepath $inputIso | get-volume | select -expand DriveLetter
$installWim = "$labTempDir\install.wim"
if (-not (test-path $installWim)) {
cp "${mountedDrive}:\Sources\install.wim" $labTempDir -verbose:$verbose
}
else {
write-verbose "Using EXISTING install.wim at '$installWim'"
}
Set-ItemProperty -path $installWim -name IsReadOnly -value $false -force
$arch = Get-BootWimArchitecture -wimFile "${mountedDrive}:\sources\boot.wim" -verbose:$verbose
dismount-diskimage -imagepath $inputIso
$wimInfo = Get-WindowsImage -imagePath $installWim
$shortCode = Get-WOShortCode -OSName $wimInfo[0].ImageName -OSArchitecture $arch
#$updatePath = resolve-path "${wsusOfflineDir}\client\$shortCode\glb" | select -expand Path
$updatePath = "D:\iso\wintriallab\temp-slipstream\WSUSCache\w63-i386-glb"
foreach ($wimInfo in (Get-WindowsImage -imagePath $installWim)) {
$wimMountSubdir = mkdir "${wimMountDir}\$($wimInfo.ImageIndex)" -force | select -expand fullname
Mount-WindowsImage -imagePath $installWim -index $wimInfo.ImageIndex -path $wimMountSubdir
write-verbose "Applying '$((ls $updatePath).count)' updates to '$wimInfo'''"
try {
Add-WindowsPackage -PackagePath $updatePath -path $wimMountSubdir
}
catch {
write-verbose "Caught error(s) when installing packages:`n`n$_`n"
}
Dismount-WindowsImage -Path $wimMountSubdir -Save
}
New-WindowsInstallMedia -sourceIsoPath $inputIso -installMediaTemp $installMediaTemp -installWimPath $installWim -outputIsoPath $outputIso
}