Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#Requires -version 4
#Requires -RunAsAdministrator
#Requires -Module Hyper-V
# For detailed information on deploying and managing Nano Server, please go to this link: http://www.aka.ms/nanoserver
Function New-NanoServer {
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
[ValidateScript({
Test-Path -Path $_ -PathType Leaf
})]
[string]$ISO,
[Parameter()]
[ValidateSet('Compute','FailoverCluster','Guest','OEM-Drivers','Storage')]
[string[]] $Package = 'Guest',
[Parameter()]
[ValidateRange(2,253)]
[int32]$VMName=2,
[Parameter(Mandatory)]
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$')]
[string]$IPAddress
)
Begin {
if (
((Get-FileHash -Path $ISO -Algorithm SHA256).Hash -eq '7AF269D9FCB79E31C0AE3859E7F62F68AB91489B386859A6F305289B0285DCEA')
){
Write-Verbose -Message "Get the correct Technical Preview 2 iso file"
} else {
Write-Warning -Message "Don't have the correct ISO of the Technical Preview 2"
break
}
if (-not(Test-Path -Path C:\mount -PathType Container)) {
try {
$null = mkdir C:\mount -Force -ErrorAction Stop -Verbose:$false
Write-Verbose -Message "Successfully created C:\mount"
} catch {
Write-Warning -Message "Failed to create C:\mount directory"
break
}
}
if (Get-NetConnectionProfile -IPv4Connectivity Internet) {
try {
$tmp = [System.IO.Path]::GetTempFileName()
$null = Invoke-WebRequest -Uri 'https://gallery.technet.microsoft.com/scriptcenter/Convert-WindowsImageps1-0fe23a8f/file/59237/6/Convert-WindowsImage.ps1' `
-OutFile $tmp -ErrorAction Stop -Verbose:$false
Unblock-File $tmp -ErrorAction Stop -Verbose:$false
if ((Get-FileHash -Path $tmp -Algorithm SHA1).Hash -eq 'B6B91B7CCFAF0A9E8B07B3A12819F8A6EB28D089') {
Write-Verbose -Message "Successfully downloaded the Convert-WindowsImage.ps1 script requirement"
} else {
Write-Warning -Message "Failed to download the Convert-WindowsImage.ps1 script requirement"
}
} catch {
Write-Warning -Message 'Failed to get the Convert-WindowsImage.ps1 from Internet'
}
} else {
Write-Warning -Message "No Internet connection available"
break
}
if (
-not(
(Get-FileHash -Path ~/Downloads/Convert-WindowsImage.ps1 -Algorithm SHA1 -ErrorAction Ig).Hash -eq '3253A0BBC15089386D123544936E524831348FD4'
)
) {
try {
(Get-Content -Path $tmp -ReadCount 1 -ErrorAction Stop) -replace
[regex]::Escape('$isWin8 = (($os.Version -ge 6.2) -and ($os.BuildNumber -ge $lowestSupportedBuild))'),
'$isWin8 = [version]($os.Version) -ge [version]"6.2"' |
Set-Content -Path ~/Downloads/Convert-WindowsImage.ps1 -Encoding UTF8 -ErrorAction Stop
Write-Verbose -Message "Successfully corrected version handling in Convert-WindowsImage.ps1"
} catch {
Write-Warning -Message "There was a problem when correcting the Convert-WindowsImage.ps1 file for version handling"
}
} else {
Write-Warning -Message "Successfully found a modified Convert-WindowsImage.ps1 file"
}
# Mount iso
# Mount-DiskImage -ImagePath $ISO # seems to be broken, I get FullyQualifiedErrorId : HRESULT 0x80070057,Mount-DiskImage
# Dismount any ISO first using the shell
(Get-Volume | Where { $_.DriveType -eq 'CD-Rom' -and $_.Size -ne 0 }).DriveLetter | ForEach-Object {
if (Test-Path -Path "$($_):") {
(New-Object -ComObject Shell.Application).NameSpace(17).ParseName("$($_):").InvokeVerb('Eject')
}
}
Start-Sleep -Seconds 3
# Mount it using the shell context
(New-Object -ComObject Shell.Application).NameSpace((Split-Path -Path $ISO -Parent)).ParseName((Split-Path -Path $ISO -Leaf)).InvokeVerb('Mount')
Start-Sleep -Seconds 3
# Get its drive letter
$MountedISOLetter = (Get-Volume | Where { $_.DriveType -eq 'CD-Rom' -and $_.Size -ne 0 }).DriveLetter
# Create a DISM folder and populate it
if (-not(Test-Path -Path C:\DISM -PathType Container)) {
try {
$null = mkdir C:\DISM -Force -ErrorAction Stop -Verbose:$false
Write-Verbose -Message "Successfully created C:\DISM"
} catch {
Write-Warning -Message "Failed to create C:\DISM directory"
break
}
}
$HT = @{
Destination = 'C:\DISM';
Force = $true ;
ErrorAction = 'Stop';
Verbose = $false ;
}
'api*downlevel*.dll','*dism*','*provider*' | ForEach-Object {
try {
Copy-Item -Path "$($MountedISOLetter):\sources\$($_)" @HT
} catch {
Write-Warning -Message "Failed to copy files from ISO to C:\DISM"
}
}
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force
# Re-enables automatic mounting of new volumes. Disabling it breaks Convert-WindowsImage.ps1
mountvol /E
}
Process {
$VM = 'Nano{0:000}' -f $VMName
Write-Verbose -Message "Starting to provision Nano server: $VM with IP: $IPAddress"
$NanoVHD = (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$($VM).vhd")
if (Test-Path -Path "$($MountedISOLetter):\") {
# Convert the WIM file to a VHD using the downloaded Convert-WindowsImage.ps1
~/Downloads/Convert-WindowsImage.ps1 -Sourcepath "$($MountedISOLetter):\NanoServer\NanoServer.wim" `
-VHD $NanoVHD -VHDformat VHD -Edition 1 -Verbose:$false
# Mount the VHD
$null = C:\DISM\dism.exe /Mount-Image /ImageFile:$NanoVHD /Index:1 /MountDir:C:\mount
if (Test-Path c:\mount\windows\system32\ntoskrnl.exe) {
Write-Verbose "Successfully mounted $NanoVHD into C:\mount"
# Add packages
$Package | ForEach-Object {
$PackageName = $_
$null,'en-US' | ForEach-Object {
$cab = "$($MountedISOLetter):\NanoServer\Packages\$($_)\Microsoft-NanoServer-$($PackageName)-Package.cab"
$null = C:\DISM\dism.exe /Add-Package /PackagePath:"$cab" /Image:C:\mount
Write-Verbose -Message "Added package $PackageName package from $($MountedISOLetter):\NanoServer\Packages\$($_)"
}
}
# Add post-install script
if (-not (Test-Path -Path C:\mount\Windows\Setup\Scripts -PathType Container)) {
$null = mkdir -Path C:\mount\Windows\Setup\Scripts -Force -Verbose:$false
}
@"
@echo off
:: Define a static IP Address
netsh int ip set address name="Ethernet" source=static address=$IPAddress
cls&echo.
set computername
ping localhost -n 10 >NUL 2>&1
netsh interface show int
netsh interface ipv4 show interfaces
ping localhost -n 10 >NUL 2>&1
netsh int ipv4 show addresses
ping localhost -n 10 >NUL 2>&1
netsh interface ipv4 show ipaddresses
ping localhost -n 10 >NUL 2>&1
netsh interface ipv6 show addresses
"@ |
Out-File -FilePath C:\mount\Windows\Setup\Scripts\SetupComplete.cmd -Encoding ascii
}
$null = C:\DISM\dism.exe /Unmount-Image /MountDir:C:\mount /Commit
if ((dir C:\mount\* ).Count -eq 0) {
Write-Verbose -Message "Successfully dismounted $NanoVHD"
}
New-VM -Name $VM -MemoryStartupBytes 512MB -NoVHD -SwitchName Internal -Generation 1
Add-VMHardDiskDrive -VMName $VM -Path $NanoVHD
Set-Item WSMan:\localhost\Client\TrustedHosts -Value (($IPAddress -split '/')[0]) -Concatenate -Force
Write-Verbose -Message "Finished provisioning Nano server: $VM with IP: $IPAddress"
} else {
Write-Warning -Message "Failed to find mounted ISO drive"
}
}
End {
# Eject the ISO
(Get-Volume | Where { $_.DriveType -eq 'CD-Rom' -and $_.Size -ne 0 }).DriveLetter | ForEach-Object {
if (Test-Path -Path "$($_):") {
(New-Object -ComObject Shell.Application).NameSpace(17).ParseName("$($_):").InvokeVerb('Eject')
}
}
}
} #endof function
$f = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('~/Downloads/en_windows_server_technical_preview_2_x64_dvd_6651466.iso')
New-NanoServer -ISO $f -Package Guest -VMName 2 -Verbose -IPAddress 192.168.137.2/24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.