Skip to content

Instantly share code, notes, and snippets.

@9000cats
Created October 17, 2025 22:53
Show Gist options
  • Select an option

  • Save 9000cats/282f210203e9eadc98ea5448c076891c to your computer and use it in GitHub Desktop.

Select an option

Save 9000cats/282f210203e9eadc98ea5448c076891c to your computer and use it in GitHub Desktop.
PowerShell function to create an ISO image file from a folder. Requires Windows ADK (Deployment Tools portion) to be installed, as it needs oscdimg.exe.
function New-CustomISO {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[ValidateScript({ Test-Path $_ -PathType Container })]
[string]$SourcePath,
[Parameter(Mandatory)]
[ValidatePattern('\.iso$', ErrorMessage='IsoPath must end with .iso')]
[string]$IsoPath,
[string]$VolumeLabel = $(Split-Path $SourcePath -Leaf),
[ValidateSet('UDF','Joliet')]
[string]$FileSystem = 'UDF',
[ValidateSet('1.02','2.01','2.50')]
[string]$UdfVersion = '2.01'
)
# Ensure destination directory exists
$isoDir = Split-Path -Path $IsoPath -Parent
if (-not (Test-Path $isoDir)) { New-Item -ItemType Directory -Path $isoDir -Force | Out-Null }
# Normalize label
$VolumeLabel = ($VolumeLabel -replace '[^\w\-. ]','')
if ($VolumeLabel.Length -gt 32) { $VolumeLabel = $VolumeLabel.Substring(0,32) }
# Find oscdimg.exe
$Osc = (Get-Command oscdimg.exe -ErrorAction SilentlyContinue)?.Source
if (-not $Osc) {
$pf86 = ${env:ProgramFiles(x86)}
$candidates = @(
(Join-Path $pf86 'Windows Kits\11\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe'),
(Join-Path $pf86 'Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe'),
(Join-Path $pf86 'Windows Kits\11\ADK\Deployment Tools\amd64\Oscdimg\oscdimg.exe'),
(Join-Path $pf86 'Windows Kits\10\ADK\Deployment Tools\amd64\Oscdimg\oscdimg.exe')
) | Where-Object { Test-Path $_ }
$Osc = $candidates | Select-Object -First 1
}
if (-not $Osc) { throw "oscdimg.exe not found. Install the Windows ADK (Deployment Tools)." }
# Filesystem flag (no incompatible combos)
$fsFlag = if ($FileSystem -eq 'UDF') {
switch ($UdfVersion) { '1.02' { '-u1' } '2.01' { '-u2' } '2.50' { '-u3' } }
} else { '-j1' }
# Clean source path (avoid trailing backslash weirdness)
$src = $SourcePath.TrimEnd('\')
# Remove existing ISO only if present
if (Test-Path -LiteralPath $IsoPath -PathType Leaf) {
Remove-Item -LiteralPath $IsoPath -Force
}
# Build arguments as an ARRAY (let PowerShell quote properly)
$args = @(
"-l$VolumeLabel", # label
"-m", # ignore media size
"-o", # optimize duplicates
$fsFlag,
$src, # source folder
$IsoPath # destination ISO
)
Write-Host "Creating ISO from '$SourcePath' to '$IsoPath' using: $Osc" -ForegroundColor Cyan
# Invoke directly; capture $LASTEXITCODE
& $Osc @args
$exit = $LASTEXITCODE
if ($exit -ne 0) {
throw "oscdimg failed with exit code $exit."
}
$item = Get-Item -LiteralPath $IsoPath -ErrorAction SilentlyContinue
if (-not $item -or $item.Length -le 0) {
throw "ISO creation failed or produced an empty file."
}
Write-Host "✅ ISO successfully created: $IsoPath" -ForegroundColor Green
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment