Last active
April 1, 2025 22:12
-
-
Save rdbahm/851ef4cfe77ba1a132a693a003cbb84d to your computer and use it in GitHub Desktop.
Integrate Nutanix VirtIO drivers into a Windows ISO
This file contains hidden or 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
#requires -RunAsAdministrator | |
<# | |
.SYNOPSIS | |
Given a Windows install disk and a Nutanix VirtIO disc, produce install media which includes Nutanix drivers. | |
.PARAMETER WindowsPath | |
The path to a Windows install DVD (or a mounted ISO), such as D:\ | |
.PARAMETER NutanixDriverPath | |
The path to the appropriate Nutanix drivers from the VirtIO ISO. For example, F:\Windows Server 2019 | |
.NOTES | |
You must have the Windows ADK installed - specifically, the "Deployment Tools." | |
This takes a good long while to run, and your antivirus WILL slow things down (though shouldn't break anything). You could consider setting $ScratchPath to a location excluded from AV scans. | |
The search indexer also does a number on performance. Disabling it could help performance if you're doing a lot of ISOs. | |
The script is based on https://polarclouds.co.uk/injecting-drivers-windows-server-2025-installer/ | |
#> | |
Param( | |
[Parameter(Mandatory)] | |
[String] | |
$WindowsPath, | |
[Parameter(Mandatory)] | |
[String] | |
$NutanixDriverPath, | |
[Parameter(Mandatory)] | |
[String] | |
$OutputPath, | |
[String] | |
$OscdimgPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg", | |
[String] | |
$ScratchPath = $env:TEMP | |
) | |
$WinISOPath = Join-Path $ScratchPath "Windows-ISO" | |
$WimMount = Join-Path $ScratchPath "Wim" | |
# Double-check that we're set to the right driver directory. | |
if(!(Test-Path (Join-Path $NutanixDriverPath "x64"))) { | |
# There's no "x64" directory, so we're in the wrong spot. | |
Throw 'Incorrect Nutanix directory specified. Make sure you provided a path which contains the directory "x64".' | |
} | |
# Double-check that the ISO write directory exists. | |
if(!(Test-Path (Split-Path $OutputPath -Parent))) { | |
Throw 'The output directory does not exist.' | |
} | |
# Verify that OSCDIMG exists. | |
if(!(Test-Path (Join-Path $OscdimgPath "oscdimg.exe"))) { | |
Throw "Check `$oscdimgpath. Oscdimg.exe is not present at $oscdimgpath" | |
} | |
$MountedWIMs = Get-WindowsImage -Mounted | |
if($null -notlike $MountedWIMs) { | |
Write-Warning "A WIM is already mounted. Unmounting it." | |
$MountedWIMs | Dismount-WindowsImage -Discard | |
} | |
# If the WinISO path already exists, delete it. | |
if(Test-Path $WinISOPath) { | |
$null = Remove-Item $WinISOPath -Force -Recurse | |
} | |
$null = New-Item -Path $WinISOPath -ItemType Directory | |
$null = Copy-Item -Path $WindowsPath\* -Destination $WinISOPath -Recurse -Force | |
# Unset all read-only properties. | |
Foreach($Item in (Get-ChildItem $WinISOPath -Recurse)) { | |
if($Item.IsReadOnly -eq $true) { | |
$Item.IsReadOnly = $false | |
} | |
} | |
# Repeat for WimMount. | |
if(Test-Path $WimMount) { | |
$null = Remove-Item $WimMount -Force -Recurse | |
} | |
$null = New-Item -Path $WimMount -ItemType Directory | |
ForEach ($Image in (Get-WindowsImage -ImagePath "$WinISOPath\sources\boot.wim")){ | |
Write-Host "Updating boot.wim: $($Image.ImageName)" | |
$null = Mount-WindowsImage -ImagePath "$WinISOPath\sources\boot.wim" -Path "$WimMount" -Index $Image.ImageIndex | |
$null = Add-WindowsDriver -Path "$WimMount" -Driver "$NutanixDriverPath" -Recurse | |
$null = Dismount-WindowsImage -Path "$WimMount" -Save | |
} | |
ForEach ($Image in (Get-WindowsImage -ImagePath "$WinISOPath\sources\install.wim")){ | |
Write-Host "Updating install.wim: $($Image.ImageName)" | |
$null = Mount-WindowsImage -ImagePath "$WinISOPath\sources\install.wim" -Path "$WimMount" -Index $Image.ImageIndex | |
$null = Add-WindowsDriver -Path "$WimMount" -Driver "$NutanixDriverPath" -Recurse | |
$null = Dismount-WindowsImage -Path "$WimMount" -Save | |
} | |
Start-Process -NoNewWindow -FilePath "$OscdimgPath\oscdimg.exe" -ArgumentList "-m -o -u2 -udfver102 -bootdata:2#p0,e,b$WinISOPath\boot\etfsboot.com#pEF,e,b$WinISOPath\efi\microsoft\boot\efisys.bin $WinISOPath $OutputPath" | |
Write-Host "Done!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment