Skip to content

Instantly share code, notes, and snippets.

@Pyromaniaxxx
Last active October 2, 2016 01:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pyromaniaxxx/79c9d36c37d9eb04896d91e02eab80f3 to your computer and use it in GitHub Desktop.
Save Pyromaniaxxx/79c9d36c37d9eb04896d91e02eab80f3 to your computer and use it in GitHub Desktop.
Create-isoToVHD.ps1
#Requires -Version 5
<#
.Synopsis
Convert iso to VHDX
.DESCRIPTION
ISOファイルからVHDイメージを作成する何か
PowerShell 5.0以降対応
.EXAMPLE
"ConfigFile"未指定の場合はスクリプトと同じフォルダにある"VMTemplate.json"を読み込む
.\Create-isoToVHD.ps1
.EXAMPLE
.\Create-isoToVHD.ps1 -ConfigFile .\VMTemplate_test.json
.NOTE
Required parameter
"ProductKey","SKU","Organization","Owner","Timezone","Locale","InputLocale","Language","ComputerName","DiskSize"
sample VMTemplate.json
{
"ISOFileName":"14393.0.160715-1616.RS1_RELEASE_SERVER_EVAL_X64FRE_JA-JP.ISO",
"VHDconfigurations":[
{
"ProductKey":"xxxxx-xxxxx-xxxxx-xxxxx-xxxxx",
"SKU":"SERVERDATACENTERCORE",
"Organization": "Contoso.com",
"Owner":"S.Hiro",
"Timezone":"Tokyo Standard Time",
"Locale":"ja-jp",
"InputLocale":"0411:00000411",
"Language":"ja-jp",
"ComputerName":"WS2016DCCore",
"DiskSize":20,
"adminPassword":"password"
},
{
"ProductKey":"*",
"SKU":"SERVERSTANDARD",
"Organization": "Contoso.com",
"Owner":"S.Hiro",
"Timezone":"Tokyo Standard Time",
"Locale":"ja-jp",
"InputLocale":"0411:00000411",
"Language":"ja-jp",
"ComputerName":"WS2016Std",
"DiskSize":40,
"adminPassword":"M@sterEr0s",
"Feature":[ "Microsoft-Hyper-V","RSAT-Hyper-V-Tools-Feature","SNMP" ]
},
{
"ProductKey":"*",
"SKU":"SERVERDATACENTER",
"Organization": "Contoso.com",
"Owner":"S.Hiro",
"Timezone":"Tokyo Standard Time",
"Locale":"ja-jp",
"InputLocale":"0411:00000411",
"Language":"ja-jp",
"ComputerName":"WS2016DC",
"DiskSize":120,
"adminPassword":"password",
"Feature":[ "NetFx3","SNMP" ]
}
]
}
#>
param
(
[CmdletBinding()]
[Parameter(Mandatory=$false)]
[String]$ConfigFile = "VMTemplate.json"
)
$Error.Clear();
$ErrorActionPreference = "Stop";
$ScriptPath = $PSScriptRoot;
### Function
#
function Check-Path
{
param
(
[string] $path
)
Process
{
if (!(Test-Path $path))
{
$null = md $path;
}
}
}
#
function Create-Unattend
{
Param
(
$Param,
$XmlPath
)
Process
{
$unattend = [xml]@"
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<servicing></servicing>
<settings pass="specialize">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ComputerName>*</ComputerName>
<RegisteredOrganization>Organization</RegisteredOrganization>
<RegisteredOwner>Owner</RegisteredOwner>
<TimeZone>TZ</TimeZone>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OOBE>
<HideEULAPage>true</HideEULAPage>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<NetworkLocation>Work</NetworkLocation>
<ProtectYourPC>1</ProtectYourPC>
</OOBE>
<UserAccounts>
<AdministratorPassword>
<Value>password</Value>
<PlainText>True</PlainText>
</AdministratorPassword>
</UserAccounts>
</component>
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<InputLocale>ja-jp</InputLocale>
<SystemLocale>ja-jp</SystemLocale>
<UILanguage>ja-jp</UILanguage>
<UILanguageFallback>ja-jp</UILanguageFallback>
<UserLocale>en-us</UserLocale>
</component>
</settings>
</unattend>
"@
$unattend.unattend.settings | Where-Object pass -eq "specialize" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-Shell-Setup"| ForEach-Object {$_.ComputerName = $Param.ComputerName};
$unattend.unattend.settings | Where-Object pass -eq "oobeSystem" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-Shell-Setup"| ForEach-Object {$_.UserAccounts.AdministratorPassword.Value = $Param.adminPassword};
$unattend.unattend.settings | Where-Object pass -eq "specialize" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-Shell-Setup"| ForEach-Object {$_.RegisteredOrganization = $Param.Organization};
if ($Param.ProductKey -ne "*")
{
$Private:Key = $unattend.CreateElement("ProductKey",$unattend.unattend.NamespaceURI)
$Private:Key.InnerText = $Param.ProductKey
$unattend.unattend.settings[0].component.AppendChild($Private:Key)
}
$unattend.unattend.settings | Where-Object pass -eq "specialize" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-Shell-Setup"| ForEach-Object {$_.RegisteredOwner = $Param.Owner};
$unattend.unattend.settings | Where-Object pass -eq "specialize" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-Shell-Setup"| ForEach-Object {$_.TimeZone = $Param.Timezone};
$unattend.unattend.settings | Where-Object pass -eq "oobeSystem" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-International-Core"| ForEach-Object {$_.InputLocale = $Param.InputLocale};
$unattend.unattend.settings | Where-Object pass -eq "oobeSystem" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-International-Core"| ForEach-Object {$_.SystemLocale = $Param.Locale};
$unattend.unattend.settings | Where-Object pass -eq "oobeSystem" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-International-Core"| ForEach-Object {$_.UserLocale = $Param.Locale};
$unattend.unattend.settings | Where-Object pass -eq "oobeSystem" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-International-Core"| ForEach-Object {$_.UILanguage = $Param.Language};
$unattend.unattend.settings | Where-Object pass -eq "oobeSystem" | select -ExpandProperty component | Where-Object name -eq "Microsoft-Windows-International-Core"| ForEach-Object {$_.UILanguageFallback = $Param.Language};
$unattend.Save($XmlPath);
Write-Verbose -Message ("save unattend : $XmlPath");
}
}
#
function Remove-File
{
param
(
[string] $path
)
Process
{
if (Test-Path $path)
{
Remove-Item -Path $path -Force
Write-Verbose -Message ("delete file : $path");
}
}
}
## initialize
$BaseVHDPath = Join-Path $ScriptPath "VHDs";
$VMpath = (Get-VMHost).VirtualMachinePath;
# check ConfigFile
if (!(Test-Path "$PSScriptRoot\$ConfigFile"))
{
Write-Error -Message "$PSScriptRoot\$ConfigFile 構成ファイルが見つかりませんでした。" -Category ObjectNotFound ;
}
else
{
$params = Get-Content -Path "$PSScriptRoot\$ConfigFile" | ConvertFrom-Json;
Write-Verbose -Message ("loading : $PSScriptRoot\$ConfigFile");
}
Check-Path -path $BaseVHDPath;
try
{
Mount-DiskImage (Join-Path $ScriptPath $params.ISOFileName);
Write-Verbose -Message ("mounted : " + $params.ISOFileName);
$DriveLetter = (Get-DiskImage (Join-Path $ScriptPath $params.ISOFileName) | Get-Volume).DriveLetter;
Copy-Item "$($DriveLetter):\NanoServer\NanoServerImageGenerator\Convert-WindowsImage.ps1" "$($ScriptPath)\Convert-WindowsImage.ps1" -Force;
Write-Verbose -Message ("copied : $($ScriptPath)\Convert-WindowsImage.ps1");
. "$ScriptPath\Convert-WindowsImage.ps1"
Write-Verbose -Message ("loading : $ScriptPath\Convert-WindowsImage.ps1");
foreach ($Config in $params.VHDconfigurations)
{
$xmlFile = (Join-Path $BaseVHDPath ($Config.ComputerName + "_unattend.xml"));
$vhdFile = (Join-Path $BaseVHDPath ($Config.ComputerName + "_disk01.vhdx"));
Remove-File -path $xmlFile;
Remove-File -path $vhdFile;
Create-Unattend $Config $xmlFile;
$ConvertWindowsImageParam = @{
SourcePath = "$($DriveLetter):\sources\install.wim"
VHDPath = $vhdFile
SizeBytes = ($Config.DiskSize * 1GB)
VHDFormat = "VHDX"
UnattendPath = $xmlFile
Edition = $Config.SKU
DiskLayout = "UEFI"
RemoteDesktopEnable = $true
}
if ($Config.Feature -ne $null)
{
$ConvertWindowsImageParam.Add("Feature",$Config.Feature);
}
$ConvertWindowsImageParam | FT;
Convert-WindowsImage @ConvertWindowsImageParam;
Write-Verbose -Message ("Convert image : " + $Config.ComputerName);
}
}
finally
{
Dismount-DiskImage (Join-Path $ScriptPath $params.ISOFileName);
Write-Verbose -Message ("dismounted : " + $params.ISOFileName);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment