PwSh.Fw.Iso.psm1
<#
.SYNOPSIS Module to export ISO function found here and there. .DESCRIPTION .NOTES Author: Charles-Antoine Degennes <cadegenn@gmail.com> Version: 0.0.1 Changelog: 2017.09.25, DCA - inital version Manifest created with command line: New-ModuleManifest iso.psd1 -RootModule iso.psm1 -ModuleVersion "0.0.1" -Author "Charles-Antoine Degennes <cadegenn@gmail.com>" #> function New-IsoFileWindows { <# .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 .LINK https://gallery.technet.microsoft.com/scriptcenter/New-ISOFile-function-a8deeffd .LINK https://github.com/wikijm/PowerShell-AdminScripts/blob/master/Miscellaneous/New-IsoFile.ps1 #> [CmdletBinding(DefaultParameterSetName='Source')]Param( [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source, [Alias('Destination')] [parameter(Position=2)][string]$Path = "$([io.path]::GetTempPath())/$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso", [ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null, [ValidateSet('UNKNOWN','CDROM','CDR','CDRW','DVDROM','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','HDDVDROM','HDDVDR','HDDVDRAM','BDROM','BDR','BDRE')] [string]$Media = 'DVDPLUSRW_DUALLAYER', [string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), [switch]$Force, [parameter(ParameterSetName='Clipboard')][switch]$FromClipboard ) Begin { Write-EnterFunction # ($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe' # if (!('ISOFile' -as [type])) { # Add-Type -CompilerParameters $cp -TypeDefinition @' if (!('ISOFile' -as [type])) { Add-Type -CompilerOptions '-unsafe' -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') # Constants from http://msdn.microsoft.com/en-us/library/windows/desktop/aa364840.aspx $FsiFileSystemISO9660 = 1 $FsiFileSystemJoliet = 2 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)) # détailler ce one-liner grâce aux infos vues sur @url https://gist.github.com/marnix/3944688 <#$Image = New-Object -com IMAPI2FS.MsftFileSystemImage $Image.VolumeName = $Title $Image.FileSystemsToCreate = $FsiFileSystemISO9660 + $FsiFileSystemJoliet #> 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" Write-LeaveFunction $Target } } function New-IsoFileLinux { [CmdletBinding()] [OutputType([String])] Param ( # Source folder [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source, # Destination filename [Alias('Destination')] [parameter(Position=2)][string]$Path = "$([io.path]::GetTempPath())/$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso", # optional boot file [ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null, # Title of the iso when mounted [string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), # force things [switch]$Force ) Begin { Write-EnterFunction } Process { if ($BootFile) { $ARGS += " -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table"} Execute-Command -exe "mkisofs" -args "$ARGS -J -r -V $Title -o $Path $Source" } End { Write-LeaveFunction } } <# .SYNOPSIS Wrapper around New-IsoFile* to abstract platform .DESCRIPTION Call correct New-ISOFile{{PLATFORM}} with all Parameters .NOTES General notes #> function New-IsoFile { [CmdletBinding()] [OutputType([String])] Param ( # Source folder [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source, # Destination filename [Alias('Destination')] [parameter(Position=2)][string]$Path = "$([io.path]::GetTempPath())/$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso", # optional boot file [ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null, # Title of the iso when mounted [string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), # force things [switch]$Force ) Begin { Write-EnterFunction } Process { if ($IsLinux) { New-IsoFileLinux @PSBoundParameters } if ($IsMacOS) { New-IsoFileMacOS @PSBoundParameters } if ($IsWindows) { New-IsoFileWindows @PSBoundParameters } } End { Write-LeaveFunction } } |