Automating tasks in a virtualized OS

5 décembre 2019 · 4 min read

Or how to perform actions in a virtual machine without leaving the terminal…

From Linux, I was looking for a way to automate the compilation of a software on Windows, and without using Wine which is not an official Microsoft product.

VirtualBox is a multi-platform virtualization software. It comes with VBoxManage, a command line tool for managing virtual machines.

Let’s take a concrete case: here is the execution of a bash script on Linux that performs actions in a Windows 10 virtual machine, in order to compile a software, execute it, take a screenshot and copy it to the host.

Here is the result: we are in a Linux terminal that displays the output of DOS commands !

Compile on Windows with the 'Win10' VM

Starting VM
Waiting for VM "Win10" to power on...
VM "Win10" has been successfully started.

Creating directory c:/users/jeff/desktop/work
Copying main.js
Copying package.json
Copying du dossier app/

yarn install
yarn install v1.19.2
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 49.30s.

yarn run buildwin64
yarn run v1.19.2
$ electron-builder -w --x64
  • electron-builder version=20.44.4
  • loaded configuration file=package.json ("build" field)
  • no native production dependencies
  • packaging       platform=win32 arch=x64 electron=4.2.12 appOutDir=c:\Users\jeff\Desktop\dist\win-unpacked
  • building        target=portable file=c:\Users\jeff\Desktop\dist\app.exe archs=x64
Done in 67.88s.

Starting app in GUI
Screenshot for fun
Copying the app to host OS
Cleanup
Stopping VM
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

Source code of the bash script for the remote control of Windows, which the result is displayed above :

#!/bin/bash

# Automating tasks in a virtualized OS

# directory to create in the guest OS to copy the app to compile
GUEST_PATH="c:/users/jeff/desktop"

# login in guest OK
GUEST_USER="jeff"

# password
GUEST_PASSWD="123456"

echo "Compile on Windows with the 'Win10' VM"
echo # carriage return in the terminal

# Starting VM without graphical user interface
# INFO: to list available VM from your host, type the command: VBoxManage list vms
echo "Starting VM"
VBoxManage startvm "Win10" --type headless
echo

# Creating directory in the VM
echo "Creating directory ${GUEST_PATH}/work"
VBoxManage guestcontrol "Win10" mkdir "${GUEST_PATH}/work" --username $GUEST_USER --password $GUEST_PASSWD

echo "Copying main.js"
VBoxManage guestcontrol "Win10" copyto main.js --target-directory "${GUEST_PATH}/work" --username $GUEST_USER --password $GUEST_PASSWD

echo "Copying package.json"
VBoxManage guestcontrol "Win10" copyto package.json --target-directory "${GUEST_PATH}/work" --username $GUEST_USER --password $GUEST_PASSWD

echo "Copying the host directory app/"
VBoxManage guestcontrol "Win10" mkdir "${GUEST_PATH}/work/app" --username $GUEST_USER --password $GUEST_PASSWD
VBoxManage guestcontrol "Win10" copyto -R app/ --target-directory "${GUEST_PATH}/work/app" --username $GUEST_USER --password $GUEST_PASSWD
echo

# Creating a DOS script that will be executed in the guest OS to install the project dependencies
cat > install.bat <<EOL
@echo off
chdir /d c:\\Users\\jeff\\desktop\\work
yarn install
EOL
VBoxManage guestcontrol "Win10" copyto install.bat --target-directory "${GUEST_PATH}/work" --username $GUEST_USER --password $GUEST_PASSWD

# Creating a DOS script that will be executed in the guest OS to build the project
cat > build.bat <<EOL
@echo off
chdir /d c:\\Users\\jeff\\desktop\\work
yarn run buildwin64
EOL
VBoxManage guestcontrol "Win10" copyto build.bat --target-directory "${GUEST_PATH}/work" --username $GUEST_USER --password $GUEST_PASSWD

# Executing the 1st DOS script
echo "yarn install"
VBoxManage guestcontrol "Win10" run --exe "${GUEST_PATH}/work/install.bat" --username $GUEST_USER --password $GUEST_PASSWD --wait-stdout --wait-stderr
echo

# Executing the 2nd DOS script
echo "yarn run buildwin64"
VBoxManage guestcontrol "Win10" run --exe "${GUEST_PATH}/work/build.bat" --username $GUEST_USER --password $GUEST_PASSWD --wait-stdout --wait-stderr
echo

echo "Starting app in GUI in the VM"
VBoxManage guestcontrol "Win10" start --exe "${GUEST_PATH}/dist/app.exe" --username $GUEST_USER --password $GUEST_PASSWD

# Screenshot (video recording is also available)
echo "Screenshot for fun"
VBoxManage controlvm "Win10" screenshotpng 01.png

echo "Copying the app to host OS"
VBoxManage guestcontrol "Win10" copyfrom -R "${GUEST_PATH}/dist/" ../dist --username $GUEST_USER --password $GUEST_PASSWD

# INFO: to close an app in the guest OS, you must get its process ID and the session ID with the command :
# VBoxManage guestcontrol "Win10" list processes
# To quit the app :
# VBoxManage guestcontrol "Win10" closeprocess --session-id 1 2484

# Cleaning up the directories on host and guest
echo
echo "Cleanup"
rm install.bat
rm build.bat
VBoxManage guestcontrol "Win10" rmdir -R "${GUEST_PATH}/work" --username $GUEST_USER --password $GUEST_PASSWD
VBoxManage guestcontrol "Win10" rmdir -R "${GUEST_PATH}/dist" --username $GUEST_USER --password $GUEST_PASSWD

# Shutting down the VM
echo "Stopping VM"
VBoxManage controlvm "Win10" savestate