How can I run a VirtualBox machine as a service on Windows XP ?

Note that the currently accepted answer (Molly7244) actually starts the VM when you login - not when you boot the machine. It is not, in other words, a service.

For an actual service that runs when the machine boots, I use two scripts (originally from here) in conjunction with cygwin (cygrunsrv). Makes use of the VBoxHeadless mode as mentioned elsewhere on this page.

The first script runs your VM via VBoxHeadless; it gets the name of the right VM to run (and other info such as your VBOX home directory) from environment variables. The second script installs a service for a particular VM (by using cygrunsrv to call the first script with the right env. vars set). Finally there's a third file which contains common functions. If you put all of these into a directory together, you can install a new vm like so:

$ VBOX_USER_HOME="/path/to/.VirtualBox/" vboxd-install MyVMName 3333

And then start the service with "net start vboxd-MyVMName" or "cygrunsrv -S vboxd-MyVMName".

Here is the VM-running script, "vboxd":

#!/bin/bash
# from http://forums.virtualbox.org/viewtopic.php?f=1&t=23536

##
## Manages start / stop of VirtualBox virtual machines
##

## load common functions
basedir="$(readlink -f $(dirname $0))"
source "$basedir/.libcommon" || exit 1

## parse arguments
parseArg vmName "$1" "$VBOXD_VM_NAME"
parseArg vmPort "$2" "$VBOXD_VM_PORT"

VBOX_INSTALL_PATH="$(cygpath "$VBOX_MSI_INSTALL_PATH")"

## define signal handler
function onHalt {
    warn "Stopping virtual machine '$vmName'"
    "$VBOX_INSTALL_PATH/VBoxManage" controlvm "$vmName" savestate
    exit 0
}

## install signal handler; cygrunsrv uses SIGTERM by default
trap 'onHalt' TERM

## hardcode this path if you like; it's required for VBox* utils to
## find the correct VirtualBox.xml config file and is usually set
## during a call to vboxd-install.
#export VBOX_USER_HOME="$USERPROFILE\\.VirtualBox"

## default VBoxHeadless port specification
portSpec="-e \"TCP/Ports=$vmPort\""

## determine vm state
info "Querying virtual machine '$vmName' state"
vmState=$( \
    "$VBOX_INSTALL_PATH/VBoxManage" showvminfo "$vmName" \
    | grep '^State:' \
    | sed 's/State: *//' )
info "Virtual machine '$vmName' is $vmState"

## if vm state is saved, we can't specify port without an exception,
## as port spec requires modification of the (immutable) saved machine
## state. See http://www.virtualbox.de/ticket/3609
if  [ "${vmState##saved}" != "$vmState" ]; then
    ## state is saved; clear port specification
    warn "Port specification is not allowed for saved vms"
    portSpec=""
fi

## start the VM
info "Starting virtual machine '$vmName' on port $vmPort"
"$VBOX_INSTALL_PATH/VBoxHeadless" -s "$vmName" $portSpec &

## record pid of VBoxHeadless child process and wait on it
pid="$!"
info "Waiting on VBoxHeadless child process $pid"
wait "$pid"

And here is the installer script, "vboxd-install":

#!/bin/bash
# http://forums.virtualbox.org/viewtopic.php?f=1&t=23536

##
## Registers a VirtualBox virtual machine to start as a service via cygrunsrv
##

## load common functions
basedir="$(readlink -f $(dirname $0))"
source "$basedir/.libcommon" || exit 1

## test for presence of cygrunsrv utility
if [ ! -x "$(which cygrunsrv)" ]; then
    die "Utility 'cygrunsrv' is not in path"
fi

## test VirtualBox configuration
if [ -z "$VBOX_USER_HOME" ]; then
    die "Required environment variable 'VBOX_USER_HOME' is undefined. " \
     "Please ensure this variable is set to point to the directory " \
     "containing your VirtualBox.xml configuration file."
fi
configFile=$(cygpath -u "$VBOX_USER_HOME\\VirtualBox.xml")
if [ ! -e "$configFile" ]; then
    die "VirtualBox configuration file '$(cygpath -w $configFile)' not found"
fi

## parse arguments
parseArg vmName "$1"
parseArg vmPort "$2"
parseArg vmUser "$3" "SYSTEM"

## if vmUser is not SYSTEM, update userSpec
userSpec="--interactive"
if [ "$vmUser" != "SYSTEM" ]; then
    ## "interactive" option disallowed when user is specified
    userSpec="--user \"$vmUser\""
fi

## install the service
cygrunsrv \
    --install "vboxd-$vmName" \
    --path "$basedir/vboxd" \
    --env "VBOXD_VM_NAME=$vmName" \
    --env "VBOXD_VM_PORT=$vmPort" \
    --env "VBOX_USER_HOME=$VBOX_USER_HOME" \
    --desc "VirtualBox virtual machine '$vmName' on port $vmPort" \
    $userSpec \
    --type auto \
    --termsig TERM \
    --shutsig TERM \
    --neverexits \
    --preshutdown \
    || die "Failed to install service"

And, finally, here is the ".libcommon" script referenced by both of these:

# -*-shell-script-*-
# from http://forums.virtualbox.org/viewtopic.php?f=1&t=23536

SCRIPT="$(basename $0)"
BASEDIR="$(readlink -f $(dirname $0))"
[ -z "$LOGLEVEL" ] && LOGLEVEL=2
[ -z "$LOGDATEFORMAT" ] && LOGDATEFORMAT="%Y-%m-%d %H:%M:%S "

function log {
    local now=""
    [ -n "$LOGDATEFORMAT" ] && now=$(date +"$LOGDATEFORMAT")
    echo "$SCRIPT $now$@" >&2
}

function debug {
    [ "$LOGLEVEL" -lt 3 ] && return
    log "[DEBUG] $@"
}

function info {
    [ "$LOGLEVEL" -lt 2 ] && return
    log "[INFO]  $@"
}

function warn {
    [ "$LOGLEVEL" -lt 1 ] && return
    log "[WARN]  $@"
}

function error {
    log "[ERROR] $@"
}

function die {
    error "$@"
    exit 1
}

function parseArg {
    local _name="$1"
    local _value="$2"
    local _default="$3"
    if [ -z "$_value" ]; then
        if [ -z "$_default" ]; then
            die "Required argument '$_name' is undefined"
        fi
     if [ "$_default" = "*EMPTY*" ]; then
         _value=""
     else
            _value="$_default"
     fi
    fi
    debug "$_name=\"$_value\""
    eval "$_name=\"$_value\""
}

This solution works great for me; hopefully you'll have similar luck.


Looks like the simplest answer at this point is VBoxVMService. I haven't tried it yet, I'll try to remember to come here and update the answer if/when I do.


Agreed on VBoxVMService. It is really easy to set up and seems to be working well. You can find a how to on setting it up here:

http://www.windows-noob.com/forums/index.php?/topic/4931-have-virtualbox-vms-start-as-a-service-on-a-windows-host/

****EDIT**** As per the request below, a summary of the link. Although the solution worked for me, the credit goes to Peter Upfold - http://peter.upfold.org.uk/

  • Install Virtualbox and setup the VM to accept RDP sessions.
  • Download and install VBoxVmService into C:\vms. Just Google VBoxVmService for a download link (sorry, not enough rep to post more than 2 links).
  • Edit VBoxVmService's ini file under C:\vms:

[Settings]

ServiceName=VBoxVmService

VBOX_USER_HOME=C:\Users\Administrator.VirtualBox

RunAsUser=.\Administrator

UserPassword=enteryourpasswordhere

RunWebService=no

PauseShutdown=5000

[Vm0] VmName=name of the vm in VirtualBox

ShutdownMethod=savestate

AutoStart=yes

  • Substitute in the VBOX_USER_HOME with the .VirtualBox folder in the correct user's home directory, as well as the RunAsUser and UserPassword directives, and set the name of the target virtual machine in the VirtualBox app in VmName. You can also add additional [Vmx] sections after [Vm0] with other virtual machines to start when the machine boots.

  • When you are happy with your configuration, from an Administrator-enabled Command Prompt, run the following command to install the service. Once the service is installed, you can remove your user password from the INI file, as it is saved in the Service configuration:

C:\vms\VmServiceControl.exe -i

  • Now, you must reboot the computer before attempting to start the service for the first time, or it will be unable to locate the VMs.

  • Upon reboot, the service should start (subject to the 'Automatic (Delayed Start)' delay) and your VMs will be started upon boot.