Search notes:
VirtualBox: Unattended OS installation with PowerShell
Variables
Before the unattended installation is started, a few
variables are defined.
Note the two values for $userName
and $fullUserName
.
This
script must be
dot sourced so that the defined variables are set in the
current scope as opposed to the child code.
#
# Add Virtual Box bin-path to PATH environment variable if necessary:
#
if ( (get-command VBoxManage.exe -errorAction silentlyContinue) -eq $null) {
$env:path="C:\Program Files\Oracle\VirtualBox;$env:path"
}
# $vmName = 'Win10Preview'
$vmName = 'Windows10'
# $vmName = 'Ubuntu-desktop-22.04.1'
# $vmName = 'Debian-11.6.0'
#
# Location of installation ISO file:
#
# $isoFile = "$home\VirtualBox\ISOs\Windows10_InsiderPreview_Client_x64_en-us_19035.iso"
$isoFile = "$home\VirtualBox\ISOs\Windows-10.iso"
# $isoFile = "$home\VirtualBox\ISOs\ubuntu-22.04.1-desktop-amd64.iso"
# $isoFile = "$home\VirtualBox\ISOs\debian-11.6.0-amd64-netinst.iso"
if (-not (test-path $isoFile)) {
"$isoFile does not exist"
return
}
#
# VBoxManage.exe unattended detect --iso=$isoFile
#
#
# VBoxManage list ostypes
#
$osType='Windows10_64'
# $osType='Ubuntu_64'
# $osType='Debian_64'
$vmPath="$home\VirtualBox VMs\$vmName"
#
# Default user name is vboxuser
#
$userName = 'tq84'
$fullUserName = 'Tee Queue Eighty-Four'
#
# Default password is changeme
#
$password='theSecret'
#
# Some Memory sizes
#
$hdSizeMb = 65536
$memSizeMb = 16384
$vramMb = 128 # Must be in range 0 … 256 (Mb) - GUI allows max of 128 only.
#
# Number of CPUs
#
$nofCPUs = 4
#
# Path of shared folder
#
$sharedFolder = "$home\VirtualBox\sharedFolder"
Remove last creation
I already might have created a
virtual machine with the same name, especially when testing this scenario. So delete this
VBoxManage controlvm $vmName poweroff
VBoxManage unregistervm $vmName --delete
rmdir -recurse $vmPath
# rmdir -recurse $sharedFolder
Detect OS of given .iso
VBoxManage.exe unattended detect --iso=$isoFile
The output of this command includes a line with the OS TypeId of the iso's operating system:
...
OS TypeId = WindowsNT_64
...
I'd think I should be using this value for the parameter --ostype
when creating the virtual machine definition file, but it turns aout that Windows10_64
is better.
BTW, a list of supported OS types can be shown with
VBoxManage list ostypes
Create the virtual machine definition file
The following step creates a new XML virtual machine definition file with the file extension .vbox
.
In this example, the file created is $vmPath\$vmName.vbox
.
VBoxManage createvm --name $vmName --ostype $osType --register
if (! (test-path $vmPath\$vmName.vbox)) {
echo "I expected a .vbox"
return
}
Add a hard disk
A hard disk is needed. The --size
parameter is in megabytes.
The value of this parameter is set in variables.ps
VBoxManage createmedium --filename $vmPath\hard-drive.vdi --size $hdSizeMb
if (! (test-path $vmPath\hard-drive.vdi)) {
echo "I expected a .vdi"
return
}
This step creates the .vdi
file $vmPath\hard-drive.vdi
.
Add SATA controller and attach hard disk to it
The hard disk needs a
SATA storage controller to which it can be attached.
VBoxManage storagectl $vmName --name 'SATA Controller' --add sata --controller IntelAHCI
VBoxManage storageattach $vmName --storagectl 'SATA Controller' --port 0 --device 0 --type hdd --medium $vmPath/hard-drive.vdi
Add IDE controller and virtual DVD drive
The .iso
file with the OS to be installed needs to be mounted via an IDE controller.
VBoxManage storagectl $vmName --name 'IDE Controller' --add ide
VBoxManage storageattach $vmName --storagectl 'IDE Controller' --port 0 --device 0 --type dvddrive --medium $isoFile
Enable APIC
VBoxManage modifyvm $vmName --ioapic on
Specify boot order of devices
Configure the boot device order for the VM.
A virtual machine has 4 slots from which it tries to boot from. The following command specifies their order:
VBoxManage modifyvm $vmName --boot1 dvd --boot2 disk --boot3 none --boot4 none
Memory
Memory is needed by both, the
RAM and video processor. Their sizes can be specified in one go with the
--memory
and
--vram
options of
VBoxManage modifyvm
:
VBoxManage modifyvm $vmName --memory $memSizeMb --vram $vramMb
Specify (host) location of a shared folder
In order to be able to exchange files between the guest and the host, the (already existing) folder on the host is specified:
# $null = mkdir $sharedFolder
VBoxManage sharedfolder add $vmName --name shr --hostpath $sharedFolder --automount
Enable clipboard content sharing
Allow
clipboard content to be shared between host and guest in both directions.
VBoxManage modifyvm $vmName --clipboard-mode bidirectional
VBoxSVGA
VBoxManage modifyvm $vmName --graphicscontroller vboxsvga
Number of CPUs
VBoxManage modifyvm $vmName --cpus $nofCPUs
The current number of CPUs can be queried like so
VBoxManage VBoxManage showvminfo $vmName --machinereadable | findstr cpus=
Specify an unattended installation
I specify the desire for an unattended installation of the operating system.
The --post-install-command
specifies a command to be executed by A:\VBOXPOST.CMD
after it has executed E:\vboxadditions\VBoxWindowsAdditions.exe /S
.
VBoxManage unattended install $vmName `
--iso=$isoFile `
--user=$userName `
--password=$password `
--full-user-name=$fullUserName `
--install-additions `
--time-zone=CET `
# --post-install-command='VBoxControl guestproperty set installation_finished y'
TODO: Among others, the command also emits the following interesting lines which leads to the assumption that the installation can be controlled with more XML-configuration or cmd files:
scriptTemplatePath = C:\Program Files\Oracle\VirtualBox\UnattendedTemplates\win_nt6_unattended.xml
postInstallScriptTemplatePath = C:\Program Files\Oracle\VirtualBox\UnattendedTemplates\win_postinstall.cmd
List virtual machines
The new virtual machine is shown to be registered.
VBoxManage list vms
Remove menus
I don't want any menus in the the window that shows the content of the virtual machine.
VBoxManage setextradata $vmName GUI/RestrictedRuntimeMenus ALL
Start the virtual machine
The unattended installation is triggered by starting the unattended installation.
VBoxManage startvm $vmName
Specify the size of the screen
VBoxManage controlvm $vmName setvideomodehint 1200 900 32
I also tried the following commands to specify the screen size, yet without any positive result:
VBoxManage setextradata $vmName CustomVideoMode 1600x900x32
VBoxManage controlvm $vmName setvideomodehint 1920 1080 32
VBoxManage controlvm $vmName setscreenlayout primary 0 0 1600 1200 24
Wait for installation to be finished
The following command waits until the specified property is set. It is supposed to be set after the installation of the VirtualBox is finished. However, in my environment, it turned out that the property was always set before Windows was installed. So, the idea is good, but the implementation is imperfect.
VBoxManage guestproperty wait $vmName installation_finished
The property that was set is also visible with
VBoxManage guestproperty enumerate $vmName
TODO
Should
ACPI be enabled by default (compare
VBoxManage modifyvm --acpi [on|off]
)
Should nested VT-x/AMD-v be enabled?
Should 3D acceleration be turned on?