Search notes:

VirtualBox: Setting up an individual environment on a guest virtual machine with Powershell

After creating a guest virtual machine (for example with an unattended OS installation), it needs to be configured so as to be usable for its user or users.
When seeting up such an environment, I'd like to automate as many tasks as possible. For this purpose, I found the (command line command) VBoxManage executable to be an invaluable tool. With VBoxManage, the guest can be administered and configured to quite an extent.
I hope, this article can demonstrate some basic usages and features of VBoxManage.

Variables

In addition to the variables that were needed for the creation of the virtual machine, I also need to specify the following two variables:
$vmNameClone='Win10-test-env'
$instDir="c:\users\$username\Software-to-be-installed"
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/variables-clone.ps1

Create a clone

I don't want to work on a pristine installation of a OS, so I clone the virtual machine.
Before I can create the clone, the «original» virtual machine should be shut down. This is possible with
C:\> shutdown -s -t 0
TODO: It's probably easier to save the current state of the VM to disk and then stop the VM before cloning it:
VBoxManage controlvm $vmName savestate
This command, to be executed on the guest, can be started from the host like so:
VBoxManage guestcontrol $vmName run --username $userName --password $password -- shutdown.exe -s -t 0
After the guest OS is shut down, I can clone the VM:
VBoxManage clonevm $vmName --name=$vmNameClone --register
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/create-clone.ps1

Start up the cloned VM

Start the cloned virtual machine.
As the OS was shutdown, it also boots up.
VBoxManage startvm $vmNameClone
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/start-clone.ps1

Run executables in System32 directory

An executable in the C:\Windows\System32 directory can be run like so:
#
#   Executing an executable on the guest.
#   Note: the .exe suffix is mandatatory (on Windows, of course)
#   
#   Note also: the VBoxService service (which somehow was installed on the
#   guest) needs to run in order of this command to work
#

VBoxManage guestcontrol $vmNameClone run --exe ipconfig.exe --username $userName --password $password
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/run-ipconfig.ps1

Run executables with arguments

It turns out, running executables that need to be given arguments is not as straightforward.
I am not sure what the first argument (WHATISTHIS) is good for. I guess it is a UNIX thingy.
VBoxManage guestcontrol $vmNameClone run --exe cmd.exe  --username $userName --password $password WHATISTHIS /c echo foo bar baz
VBoxManage guestcontrol $vmNameClone run --exe ping.exe --username $userName --password $password WHATISTHIS 172.17.192.1
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/run-cmd-with-arguments.ps1

Run executables in other directories

Executables that are not located in C:\Windows\System32, such as powershell_exe, need be specified with their full path:
VBoxManage guestcontrol $vmNameClone run C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe --username $userName --password $password -- -command get-date
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/run-powershell.ps1

Mapping a drive

With the ability to call executables and passing parameters, we're able to mount (map with net use) a shared folder to a letter.
When I created the virtual machine, I already specified the (host) location for a shared folder. This shared folder is accessible under the virtual server \\vboxsvr:
VBoxManage guestcontrol $vmNameClone run --username $userName --password $passWord -- net.exe use x: \\vboxsvr\shr
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/map-drive.ps1

Run batch file via mapped/shared folder

On the guest, I can now use this mapped/shared folder to run batch files that are physically located on the hos:
VBoxManage guestcontrol $vmNameClone run   --exe "X:\aBatchFile.bat"   --username $userName --password $password               DUMMY foo bar baz
VBoxManage guestcontrol $vmNameClone run   --exe "X:\aBatchFile.bat"   --username $userName --password $password -E VAR=aValue DUMMY foo bar baz
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/run-batch-file.ps1

Create a directory

VBoxManage guestcontrol $vmNameClone mkdir    --username $userName --password $password $instDir
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/create-directory.ps1

Copy file(s) from the host to the guest

VBoxManage guestcontrol $vmNameClone copyto --username $userName --password $password --target-directory $instDir "$(get-location)\anotherBatchFile.bat"
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/copy-from-host-to-guest.ps1

Run the copied batch file

Execute the copied batch file.
It produces anotherBatchFile.log.
VBoxManage guestcontrol $vmNameClone run  --username $userName --password $password --exe  "$instDir\anotherBatchFile.bat"
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/run-copied-batch-file.ps1

Copy file(s) from the guest to the host

The log file that was produced is now copied from the guest to the host:
VBoxManage guestcontrol $vmNameClone copyfrom --username $userName --password $password --target-directory "$(get-location)\copiedFromGuest.log" "$instDir\anotherBatchFile.log"
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/copy-from-guest-to-host.ps1

Take a snapshot

I take a snapshot in case I mess something up.
VBoxManage snapshot $vmNameClone take after-installation
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/take-snapshot.ps1

Revert to a snapshot

As far as I can tell, the way to revert to a previous snapshot seems to be:
VBoxManage controlvm $vmNameClone pause
# VBoxManage controlvm $vmNameClone savestate  // no need to save state, takes too long as we're going to throw away the current state of the machine anyway.
VBoxManage controlvm $vmNameClone poweroff
VBoxManage snapshot  $vmNameClone restore after-installation
VBoxManage startvm   $vmNameClone
Github repository about-VirtualBox, path: /command-line/PowerShell/setting-up-environment/revert-to-snapshot.ps1

Index