Last active
December 20, 2023 19:28
-
-
Save jonathanelbailey/c021fe5791d8baf42e7924215f2502cd to your computer and use it in GitHub Desktop.
a powershell module that allows for the modification of ISO images.
This file contains 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
# this function grabs the iso image from the user supplied http location. | |
function get-isoimage{ | |
[CmdletBinding()] | |
param( | |
$uri, | |
$workingfolder | |
) | |
begin{ | |
$file_name = $uri -replace "http://[\s\S]+\/([\s\S]+\.iso)$",'$1' | |
$out_file = Join-Path $workingfolder -ChildPath $file_name | |
} | |
process{ | |
$web_req = measure-command {Invoke-WebRequest -Uri $uri -OutFile $out_file} | |
} | |
end{ | |
Write-host "time:" + $web_req.Minutes + "min" | |
Write-Output gci $out_file | |
} | |
} | |
# this function creates the working directory that the image will be working out of. | |
function new-isoworkspace{ | |
[CmdletBinding()] | |
param( | |
$imagepath, | |
$workingfolder | |
) | |
begin{ | |
$mount_folder = Join-Path $workingfolder -ChildPath "mount" | |
} | |
process{ | |
$mount_obj = Mount-DiskImage -ImagePath $imagepath -StorageType ISO | |
$drive = ($mount_obj | Get-Volume).DriveLetter + ":" | |
copy-item $drive\* $workingfolder -force -recurse | |
} | |
end{ | |
Write-Output (gci $mount_folder) | |
} | |
} | |
# taken from https://gallery.technet.microsoft.com/scriptcenter/New-ISOFile-function-a8deeffd, created by Chris Wu | |
function New-IsoFile | |
{ | |
<# | |
.Synopsis | |
Creates a new .iso file | |
.Description | |
The New-IsoFile cmdlet creates a new .iso file containing content from chosen folders | |
.Example | |
New-IsoFile "c:\tools","c:Downloads\utils" | |
This command creates a .iso file in $env:temp folder (default location) that contains c:\tools and c:\downloads\utils folders. The folders themselves are included at the root of the .iso image. | |
.Example | |
New-IsoFile -FromClipboard -Verbose | |
Before running this command, select and copy (Ctrl-C) files/folders in Explorer first. | |
.Example | |
dir c:\WinPE | New-IsoFile -Path c:\temp\WinPE.iso -BootFile "${env:ProgramFiles(x86)}\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\efisys.bin" -Media DVDPLUSR -Title "WinPE" | |
This command creates a bootable .iso file containing the content from c:\WinPE folder, but the folder itself isn't included. Boot file etfsboot.com can be found in Windows ADK. Refer to IMAPI_MEDIA_PHYSICAL_TYPE enumeration for possible media types: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366217(v=vs.85).aspx | |
.Notes | |
NAME: New-IsoFile | |
AUTHOR: Chris Wu | |
LASTEDIT: 03/23/2016 14:46:50 | |
#> | |
[CmdletBinding(DefaultParameterSetName='Source')]Param( | |
[parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source, | |
[parameter(Position=2)][string]$Path = "$env:temp\$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso", | |
[ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null, | |
[ValidateSet('CDR','CDRW','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','BDR','BDRE')][string] $Media = 'DVDPLUSRW_DUALLAYER', | |
[string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), | |
[switch]$Force, | |
[parameter(ParameterSetName='Clipboard')][switch]$FromClipboard | |
) | |
Begin { | |
($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe' | |
if (!('ISOFile' -as [type])) { | |
Add-Type -CompilerParameters $cp -TypeDefinition @' | |
public class ISOFile | |
{ | |
public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks) | |
{ | |
int bytes = 0; | |
byte[] buf = new byte[BlockSize]; | |
var ptr = (System.IntPtr)(&bytes); | |
var o = System.IO.File.OpenWrite(Path); | |
var i = Stream as System.Runtime.InteropServices.ComTypes.IStream; | |
if (o != null) { | |
while (TotalBlocks-- > 0) { | |
i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes); | |
} | |
o.Flush(); o.Close(); | |
} | |
} | |
} | |
'@ | |
} | |
if ($BootFile) { | |
if('BDR','BDRE' -contains $Media) { Write-Warning "Bootable image doesn't seem to work with media type $Media" } | |
($Stream = New-Object -ComObject ADODB.Stream -Property @{Type=1}).Open() # adFileTypeBinary | |
$Stream.LoadFromFile((Get-Item -LiteralPath $BootFile).Fullname) | |
($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream) | |
} | |
$MediaType = @('UNKNOWN','CDROM','CDR','CDRW','DVDROM','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','HDDVDROM','HDDVDR','HDDVDRAM','BDROM','BDR','BDRE') | |
Write-Verbose -Message "Selected media type is $Media with value $($MediaType.IndexOf($Media))" | |
($Image = New-Object -com IMAPI2FS.MsftFileSystemImage -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType.IndexOf($Media)) | |
if (!($Target = New-Item -Path $Path -ItemType File -Force:$Force -ErrorAction SilentlyContinue)) { Write-Error -Message "Cannot create file $Path. Use -Force parameter to overwrite if the target file already exists."; break } | |
} | |
Process { | |
if($FromClipboard) { | |
if($PSVersionTable.PSVersion.Major -lt 5) { Write-Error -Message 'The -FromClipboard parameter is only supported on PowerShell v5 or higher'; break } | |
$Source = Get-Clipboard -Format FileDropList | |
} | |
foreach($item in $Source) { | |
if($item -isnot [System.IO.FileInfo] -and $item -isnot [System.IO.DirectoryInfo]) { | |
$item = Get-Item -LiteralPath $item | |
} | |
if($item) { | |
Write-Verbose -Message "Adding item to the target image: $($item.FullName)" | |
try { $Image.Root.AddTree($item.FullName, $true) } catch { Write-Error -Message ($_.Exception.Message.Trim() + ' Try a different media type.') } | |
} | |
} | |
} | |
End { | |
if ($Boot) { $Image.BootImageOptions=$Boot } | |
$Result = $Image.CreateResultImage() | |
[ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks) | |
Write-Verbose -Message "Target image ($($Target.FullName)) has been created" | |
$Target | |
} | |
} | |
$iso_uri = 'http://jenkins.ovirt.org/job/ovirt-node-ng_ovirt-4.1_build-artifacts-el7-x86_64/lastSuccessfulBuild/artifact/exported-artifacts/ovirt-node-ng-installer-ovirt-4.1-2017031904.iso' | |
$working_folder = join-path $env:temp -childpath 'work' | |
get-isoimage -uri $iso_uri -workingfolder $working_folder | |
$iso_name = 'ovirt-node-ng-installer-ovirt-4.1-2017031904.iso' | |
$image_path = join-path $working_folder -childpath $iso_name | |
new-isoworkspace -imagepath $image_path -workingfoler $working_folder | |
$ks_uri = 'https://gist.githubusercontent.com/jonathanelbailey/b2ba868d39491f4e6a7497010b0f6b18/raw/' | |
$ks_regexp = 'inst\.ks=hd:LABEL=CentOS\\x207\\x20x86_64:\/interactive-defaults\.ks' | |
$isolinux_cfg = join-path \temp\work\mount -ChildPath "isolinux\isolinux.cfg" | |
$content = get-content $isolinux_cfg -raw | |
($content -replace $ks_regexp,"inst.ks=$ks_uri").replace("`r`n","`n")| Set-Content $isolinux_cfg | |
$new_iso_path = join-path $working_folder -childpath $iso_name | |
dir $mount_folder | new-isoimage -path $new_iso_path -title "Ovirt-Node-Next-4.1-x86_64" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey thanks for this. A few bugs:
New-IsoWorkspace
$workingfolder
should be$mount_folder
And here is the updated New-IsoFile function for PowerShell 6+:
CompilerParameters
was replaced byCompilerOptions
and simply expects a string: