Как создать ISO через PowerShell
Добрый день! Наверняка многие кто работает с различными гипервизорами или создает кастомизированные образы, знаком с форматом ISO. Чаще всего он используется для создания загрузочных флешек или установки операционных систем, но бывают ситуации, когда благодаря ему вы можете передать необходимые данные в изолированную систему или сегмент. Сегодня я хочу вас научить методам создания собственного ISO файла с нужным вам наполнением, уверяю вас что в практике системного администратора, данное знание будет очень полезным.
Подготовка модуля создающего ISO
Наша задача написать функцию "Create-IsoFile" сохранить ее как модуль, который мы будим с вами вызывать при создании ISO. Мы будим вызывать встроенную API, это удобно, так как не требует установки специализированных программ (Например UltraISO) и главное не потребует прав локального администратора в системе.
Про создание и использований функций PowerShell, я подробно вам рассказывал, так что на этом я останавливаться не буду.
Основные наши шаги, пишем функцию, превращаем в модуль и вызываем его, весь код я вам советую вставить в PowerShell ISE.
function Create-IsoFile # Определяем функцию Create-IsoFile с параметрами для создания нашего ISO-файла
{
# Обязательный параметр Source, принимающий данные на вход
[CmdletBinding(DefaultParameterSetName='Source')]Param(
[parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source,# В параметр Path задаюся указания пути сохранения ISO-файла
[parameter(Position=2)][string]$Path = "$env:temp\$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso",# Параметр BootFile для указания файла загрузки (опционально)
[ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null,# Параметр Media используется для выбора типа носителя с предопределенным набором значений
[ValidateSet('CDR','CDRW','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','BDR','BDRE')][string] $Media = 'DVDPLUSRW_DUALLAYER',# Параметр Title позволяет указать названия ISO-образа, по умолчанию - подставляется текущее время
[string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"),# Параметр Force принудительно перезаписывает существующий файл
[switch]$Force,# Параметр FromClipboard нужен для получения источника из буфера обмена (опционально)
[parameter(ParameterSetName='Clipboard')][switch]$FromClipboard
)Begin {
# Настройка параметров компилятора для создания класса ISOFile
($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe'# Проверка, существует ли уже класс ISOFile, если нет, то создаем его
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();
}
}
}
'@
}# Если указан параметр BootFile, тоделаем его как загрузочный образ
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))# Пробуем создать целевой ISO по указанному пути, если не удалось - выводим ошибку
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
}
}
Сохраним его по пути C:\Program Files\WindowsPowerShell\Modules\Create-IsoFile в формате psm1. Если папки Modules не будет, то смело ее создавайте.
Вызовем теперь PowerShell окно и удостоверимся в наличии модуля Create-IsoFile, для этого введите:
Get-Module -ListAvailable
Вы должны увидеть в списке ваш ново созданный модуль Create-IsoFile.
Создание ISO через PowerShell
Первое, что вы должны теперь сделать, это указать в открытом ранее окне PowerShell, где у нас будет папка в которую вы положите нужные вам данные, из которых будет создаваться ISO образ. В моем примере это будет E:\InputISO. Создаем переменную $source_dir.
$source_dir = "E:\InputISO"
Теперь импортируем наш модуль с помощью команды:
Import-Module Create-IsoFile
Далее вам необходимо определиться с папкой куда будет экспортироваться создаваемый ISO образ, в моем примере это будет каталог E:\OutputISO\FixW2008R2.iso. Обратите внимание, что я сразу задал имя моего ISO. Остается теперь вызвать нашу функцию.
get-childitem "$source_dir" | Create-IsoFile -path E:\OutputISO\FixW2008R2.iso
В результате у нас был успешно создан ISO образ в указанном каталоге, хочу отметить что занимаемое время зависит исключительно из-за размера и количества файлов.
Как видите у нас все получилось. Хочу отметить, что для создания ISO вам не потребуются административные права, все делается штатными средствами. Это был лишь один из вариантов скрипта, разновидностей которого может быть уйма. С вами был Иван Сёмин, автор и создатель IT платформы Pyatilistnik.org.