mirror of
https://github.com/timsutton/brigadier.git
synced 2024-09-19 11:18:44 -04:00
Merge pull request #39 from theaquamarine/powershell
PowerShell port of script
This commit is contained in:
commit
e7922c7d32
1 changed files with 165 additions and 0 deletions
165
brigadier.ps1
Normal file
165
brigadier.ps1
Normal file
|
@ -0,0 +1,165 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
Fetch and install Boot Camp ESDs with ease.
|
||||
.DESCRIPTION
|
||||
Download and unpack Boot Camp drivers and support software from Apple or your software update servers for specified Mac models.
|
||||
|
||||
Can also install drivers and software if used with the "-Install" parameter.
|
||||
.EXAMPLE
|
||||
brigadier.ps1
|
||||
Download and unpack the ESD that applies to current computer's model to the current working directory.
|
||||
|
||||
.EXAMPLE
|
||||
brigadier.ps1 -Model 'MacBookAir5,2'
|
||||
Download and unpack the ESD for a specific model to the current working directory.
|
||||
|
||||
.EXAMPLE
|
||||
brigadier.ps1 -Install
|
||||
Download, unpack, and install drivers for the current computer, deleting the drivers after installation.
|
||||
.NOTES
|
||||
This is a PowerShell port of timsutton's original Python script https://github.com/timsutton/brigadier/
|
||||
.LINK
|
||||
https://github.com/timsutton/brigadier/
|
||||
#>
|
||||
|
||||
[CmdletBinding(DefaultParameterSetName='Download')]
|
||||
Param(
|
||||
# Model identifier to use, defaulting to the current machine's model.
|
||||
[Parameter(ParameterSetName='Download')]
|
||||
[string]$Model = (Get-CimInstance -Class Win32_ComputerSystem).Model,
|
||||
|
||||
# After the installer is downloaded, perform the install automatically.
|
||||
[Parameter(ParameterSetName='Install',
|
||||
Mandatory=$true
|
||||
)]
|
||||
[switch]$Install,
|
||||
|
||||
# Directory to extract installer files to. Defaults to the current directory.
|
||||
[string]$OutputDir = $PWD,
|
||||
|
||||
# Keep the files that were downloaded/extracted after installing/
|
||||
[Parameter(ParameterSetName='Install')]
|
||||
[switch]$KeepFiles,
|
||||
|
||||
# Specify an exact product ID to download.
|
||||
[array]$ProductId,
|
||||
|
||||
# URL for software update catalog to use, eg for an intenal Software Update Service or Reposado
|
||||
[Alias('SUCATALOG_URL')]
|
||||
[string]$CatalogURL = 'https://swscan.apple.com/content/catalogs/others/index-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog',
|
||||
|
||||
# URL to download 7-Zip from, if not installed
|
||||
[Alias('SEVENZIP_URL')]
|
||||
[string]$SevenZipURL = 'https://www.7-zip.org/a/7z1900-x64.exe'
|
||||
)
|
||||
|
||||
# Disable Invoke-WebRequest progress bar to speed up download due to bug
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
# Create Output Directory if it does not exist
|
||||
if (!(Test-Path $OutputDir)) { New-Item -Path $OutputDir -ItemType Directory -Force }
|
||||
|
||||
# Check if at least 7zip 15.14 is installed. If not, download and install it.
|
||||
$7z = "$env:ProgramFiles\7-Zip\7z.exe"
|
||||
$7zDownload = Join-Path $env:Temp $SevenZipURL.Split('/')[-1]
|
||||
if (Test-Path $7z) { $7zInstalled = $true }
|
||||
if ([version](Get-ItemProperty $7z).VersionInfo.FileVersion -lt 15.14) {
|
||||
Write-Host "7-Zip not installed, will install and remove."
|
||||
Invoke-WebRequest -Uri $SevenZipURL -OutFile $7zDownload -ErrorAction Stop
|
||||
Start-Process -FilePath $env:SystemRoot\System32\msiexec.exe -ArgumentList "/i $7zDownload /qb- /norestart" -Wait -Verbose
|
||||
}
|
||||
|
||||
Write-Host "Using model: $Model"
|
||||
|
||||
# Read data from sucatalog and find all Bootcamp ESD's
|
||||
Write-Host "Downloading software update catalog..."
|
||||
$bootcamplist = @()
|
||||
[xml]$sucatalog = Invoke-WebRequest -Uri $CatalogURL -Method Get -ErrorAction Stop
|
||||
$sucatalog.plist.dict.dict.dict | Where-Object { $_.String -match "Bootcamp" } | ForEach-Object {
|
||||
# Search dist files to find supported models, using regex match to find models in dist files - stole regex from brigadier's source
|
||||
$modelRegex = "([a-zA-Z]{4,12}[1-9]{1,2}\,[1-6])"
|
||||
$distURL = ($_.dict | Where-Object { $_.Key -match "English" }).String
|
||||
$distXML = (Invoke-RestMethod -Uri $distURL).InnerXml
|
||||
$SupportedModels = [regex]::Matches($distXML,$modelRegex).Value
|
||||
if ($SupportedModels -contains $Model) {
|
||||
$_ | Add-Member -NotePropertyName Version -NotePropertyValue ([regex]::Match($distURL,"(\d{3}-\d{4,5})").Value)
|
||||
Write-Output "Found supported ESD: $($_.Version), posted $($_.Date)"
|
||||
$bootcamplist += $_
|
||||
}
|
||||
}
|
||||
|
||||
if ($ProductId) {
|
||||
Write-Host "ProductID specified, filtering Boot Camp ESD selection to match."
|
||||
$bootcamplist = $bootcamplist | Where-Object {$_.Version -in $ProductId}
|
||||
}
|
||||
|
||||
if ($bootcamplist.Length -gt 1) {
|
||||
Write-Host "Found more than 1 supported Bootcamp ESD. Selecting newest based on posted date which may not always be correct"
|
||||
} elseif ($bootcamplist.length -eq 0) {
|
||||
Write-Warning "Couldn't find a Boot Camp ESD for the model $Model in the given software update catalog."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$esd = $bootcamplist | Sort-Object -Property Date | Select-Object -Last 1
|
||||
# Build a hash table of the package's properties from the XML
|
||||
$package = $esd.array.dict.selectnodes('key') | ForEach-Object {@{$($_.'#text') = $($_.nextsibling.'#text')}}
|
||||
$package += @{'ESDVersion' = $($esd.Version)}
|
||||
Write-Host "Selected $($package.ESDVersion) as it's the most recently posted."
|
||||
|
||||
$landingDir = Join-Path $OutputDir "BootCamp-$($package.ESDVersion)"
|
||||
$workingDir = Join-Path $env:Temp "BootCamp-unpack-$($package.ESDVersion)"
|
||||
$packagePath = Join-Path $workingDir 'BootCampESD.pkg'
|
||||
$payloadPath = Join-Path $workingDir 'Payload~'
|
||||
$dmgPath = Join-Path $workingDir 'WindowsSupport.dmg'
|
||||
|
||||
if (Test-Path -PathType Container $landingDir) {
|
||||
# Python just deletes the folder
|
||||
Write-Warning "Final destination folder $landingDir already exists, please remove it to redownload."
|
||||
exit 1
|
||||
}
|
||||
if (-not (Test-Path -PathType Container $workingDir)) {mkdir $workingDir > $null}
|
||||
|
||||
# Download the BootCamp ESD if required
|
||||
if (-not (Test-Path -PathType Leaf $packagePath)) {
|
||||
Write-Host "Starting download from $($package.URL)"
|
||||
Start-BitsTransfer -Source $package.URL -Destination "$packagePath" -ErrorAction Stop
|
||||
Write-Host "Download complete"
|
||||
} else {
|
||||
# Not sure what's used for the digest, but we can match size.
|
||||
if ((Get-Item $packagePath | Select-Object -ExpandProperty Length) -eq $package.Size) {
|
||||
Write-Host "$($package.ESDVersion) already exists at $packagePath, not redownloading."
|
||||
} else {
|
||||
Write-Warning "A file already exists at $packagePath but does not match $($package.URL), please remove it."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Extract the bootcamp installer
|
||||
Write-Host "Extracting..."
|
||||
& $7z -o"$workingDir" -y e "$packagePath"
|
||||
& $7z -o"$workingDir" -y e "$payloadPath"
|
||||
if (-not (Test-Path -PathType Container $landingDir)) {mkdir $landingDir > $null}
|
||||
& $7z -o"$landingDir" -y x "$dmgPath"
|
||||
|
||||
# Uninstall 7zip if we installed it
|
||||
if ($7zInstalled -ne $true) {
|
||||
Write-Host "Removing 7-Zip..."
|
||||
Start-Process -FilePath $env:SystemRoot\System32\msiexec.exe -ArgumentList "/x $7zDownload /qb- /norestart" -Wait
|
||||
Remove-Item $7zDownload
|
||||
}
|
||||
|
||||
# Install Bootcamp and use MST if specified (I uploaded one that I had to use to fix the latest ESD on an iMac14,1)
|
||||
if ($Install) {
|
||||
# Install Bootcamp
|
||||
$scaction = New-ScheduledTaskAction -Execute "msiexec.exe" -Argument "/i $landingDir\Bootcamp\Drivers\Apple\BootCamp.msi /qn /norestart"
|
||||
$sctrigger = New-ScheduledTaskTrigger -At ((Get-Date).AddSeconds(15)) -Once
|
||||
$scprincipal = New-ScheduledTaskPrincipal "SYSTEM" -RunLevel Highest
|
||||
$scsettings = New-ScheduledTaskSettingsSet
|
||||
$sctask = New-ScheduledTask -Action $scaction -Principal $scprincipal -Trigger $sctrigger -Settings $scsettings
|
||||
Register-ScheduledTask "Install Bootcamp" -InputObject $sctask -User "SYSTEM"
|
||||
do { Write-Output "Sleeping 20 seconds"; Start-Sleep -Seconds 20 } while (Get-Process -Name "msiexec" -ErrorAction SilentlyContinue)
|
||||
if (-not $KeepFiles) { Remove-Item -Path "$landingDir" -Recurse -Force -ErrorAction SilentlyContinue }
|
||||
}
|
||||
|
||||
Write-Host "Cleaning up working directory..."
|
||||
Remove-Item -Path $workingDir -Recurse
|
Loading…
Reference in a new issue