I have a VirtualBox machine with Windows XP on a Windows XP Host.

How can I start VirtualBox as a service, so I can get a virtual machine under the hood, and I don't have to start VirtualBox in order to access my virtual machine (via VNC from the network)?

I found that VirtualBox Manage might be the way to go, but since I'm a beginner with this, I don't know where to start.

Any ideas?


Create a Shortcut to C:\Program Files\innotek VirtualBox\VBoxManage.exe

After the quotation marks enter: startvm <your virtual machine name>


“C:\Program Files\innotek VirtualBox\VBoxManage.exe” startvm XP

Copy/Move the shortcut to your startup folder.

p.s.: if you want to delay the Virtual Machine until your system is fully booted, you can do this in XP via Startup Delayer.

  • It appears to works fine, Is there anyway to "hide" the window for the virtual machine also, so it be running more like a windows service? – Jhonny D. Cano -Leftware- Jan 5 '10 at 19:41
  • running VBox as a service will not hide the window. you can minimize it automatically to the system tray with AWM though: eusing.com/WindowManager/WindowManager.htm – Molly7244 Jan 5 '10 at 19:59
  • 15
    checkout "VBoxHeadless" for launching VM's with no UI. You will need to use RDP if you want to see the VM's screen. – Mark Porter Jan 5 '10 at 20:25
  • 13
    This is not a service. This only runs VBox when you log in - not when the machine is powered on. VBoxHeadless is the way to go for running as a service. See my answer below (which I'm about to improve per Aaron Copley's comment). – John Hart Apr 10 '12 at 17:41
  • The answer has nothing to do with running as a service. The startup happen after a user logon, completely different that the services behavior. – Felice Pollano Jan 25 '16 at 10:10

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":

# 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"


## 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"

## 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
info "Waiting on VBoxHeadless child process $pid"
wait "$pid"

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

# 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"

## 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."
configFile=$(cygpath -u "$VBOX_USER_HOME\\VirtualBox.xml")
if [ ! -e "$configFile" ]; then
    die "VirtualBox configuration file '$(cygpath -w $configFile)' not found"

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

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

## install the service
cygrunsrv \
    --install "vboxd-$vmName" \
    --path "$basedir/vboxd" \
    --env "VBOXD_VM_NAME=$vmName" \
    --env "VBOXD_VM_PORT=$vmPort" \
    --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"
     if [ "$_default" = "*EMPTY*" ]; then
    debug "$_name=\"$_value\""
    eval "$_name=\"$_value\""

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

  • 4
    +1 for "not a service"... -1 for linking to the solution rather than including it in the answer. Vote is null. :) Consider revising to include the solution as link rot is detrimental to the longevity of this answer. – Aaron Copley Jan 3 '12 at 22:07

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.

  • 1
    it does not work with 4.2.x though – Archimedes Trajano Sep 12 '13 at 18:05
  • 2
    @ArchimedesTrajano I've tried the current version (4.1) with VirtualBox 4.3.6 and it runs well. The project's page claims it was "rewritten almost from scratch". – Melebius Apr 7 '14 at 13:17
  • 1
    Yup I just tested it last night and it works! Just remember to REBOOT. – Archimedes Trajano Apr 7 '14 at 20:43

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:


****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:








[Vm0] VmName=name of the vm in VirtualBox



  • 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.

  • 1
    Can you summarize the link within your answer in case it goes dead? – jonsca Aug 13 '13 at 10:44
  • Post edited as requested. – RooiWillie Aug 13 '13 at 11:58
  • does this work on the 4.2.x version of VirtualBox? – Archimedes Trajano Sep 12 '13 at 18:07
  • These instructions probably apply to some older version, the current version of VBoxVmService (4.1) is easier to set up and it'll guide you through the process. – Melebius Apr 7 '14 at 9:24

Just offering this as another option:

Use the builtin Windows command 'sc' to create a service. Combine this with 'vboxheadless' will get you to where you want to be.

Untested with vboxheadless specifically, but I did create a test service that runs calc.exe. You should be doing something like this:

sc create servicenamehere start= auto binPath= "C:\path\to\vboxheadless.exe --startvm name"

Refer to the documentation for sc for more information. Note: Those spaces after the equal sign are intentional.

  • This will start the service correctly, but will crash the VM when the service is stopped -- VBoxHeadless can't correctly interpret the service stop control, so Windows will wait until the timeout and then forcibly kill the process, which is less than ideal. See other answers for wrapper scripts to prevent that happening. – Aaron Miller Oct 1 '12 at 15:30
  • Thanks for the comment. Hopefully, this is submitted to the developers as a bug fix/feature request. – Aaron Copley Oct 2 '12 at 13:05

If the vboxd scripts are giving you as much trouble as they did me, you might want to try this; it's a rather simpler solution, implemented in Perl, which provides the same functionality. Specifically, the VM starts up with the system (assuming the service is set to start automatically, which is the default), and goes down cleanly when the service is stopped.

Major differences from the vboxd solution, aside from being considerably simpler to deal with in my experience, are that this script doesn't pass a VRDE port setting to VBoxHeadless, and that the VM shutdown is handled via "acpipowerbutton" rather than "savestate".

If this doesn't suit your purposes, it's easy enough to change; in the first case, add '-e "TCP/Ports=[,port...]"' to the VBoxHeadless command line string ($cmd), and in the second case, just change "acpipowerbutton" to "savestate" in the SIGTERM handler.

Here's the Perl script:

 # Service wrapper for VirtualBox VM.

 use strict;

 # Windows-style path pointing to your VirtualBox home directory
 # (i.e., where your VirtualBox.xml lives)
 my $vboxhome = 'c:\\Documents and Settings\\Aaron\\.VirtualBox';

 # Cygwin path pointing to the VirtualBox install directory
 my $vboxpath = '/cygdrive/c/Program Files/Oracle/VirtualBox';

 # Name or UUID of your virtual machine
 my $vmname = '{83dfb4b1-4243-4a07-9d37-9df5573792d8}';

 $ENV{'VBOX_USER_HOME'} = $vboxhome;

 my $exit_handler = sub {
    print "Caught SIGTERM; shutting down VM.\n";
    exec("'$vboxpath/VBoxManage.exe' controlvm $vmname acpipowerbutton");

 $SIG{TERM} = $exit_handler;

 print "[debug] pid $$\n";

 # Command line for VBoxHeadless - add your VRDE port here if you want one
 my $cmd = "'$vboxpath/VBoxHeadless.exe' --startvm $vmname 2>&1 1>/dev/null";
 print "[debug] $cmd\n";

 print "VM died unexpectedly; exiting.\n";

And here's the cygrunsrv command line I used to install the Windows service:

 cygrunsrv --install '<service-name>' --desc '<description>' \
  --path '/usr/bin/perl' --args '<full-path-to-service-script>' \
  --chdir '<path-to-service-script-dir>' --termsig TERM --shutsig TERM \
  --preshutdown --interactive

From there, it should just be a matter of issuing 'sc start <service-name>', and you should be good to go -- remember that, by default, cygrunsrv services log to /var/log/<service-name>.log, so if anything misbehaves, that's the first place to look for a reason why.

One thing to keep in mind is that, when you run the VM this way, it will run under the built-in SYSTEM account, rather than your own. This being the case, you won't be able to administer the VM via the VirtualBox console while it's running as a service; it will appear to be in the "Powered off" state, and you won't be able to get to its settings. (Trying to power on the VM while it's running as a service is not recommended -- I don't know what will happen, but at best it'll be a no-op, and at worst it'll hose your VM.) If you need to change the VM's settings or access the console, stop the service first (and wait for VBoxHeadless.exe to exit), and then configure it/power it up in the VirtualBox console as you normally would.

You could probably solve this problem by installing a second interactive service to run the VirtualBox console; since that would run the console under the SYSTEM account as well, it'd most likely be able to see and manage the running VM. I haven't had a need to do that myself, so I'm not sure it would work, but I don't see a reason why it wouldn't. (If you try it, I'd appreciate a comment to this answer, letting me know how it worked out for you. Thanks!)

Hope this helps!

  • Your script is simpler, but requires Perl and hard-codes several properties that the vboxd script accepts as parameters. According to virtualbox.org/manual/ch07.html, by not accepting the VRDE port, VBoxHeadless will not run the VM (it just blocks indefinitely) if the VM is set to use the default port which another RDP server is using. vboxd-install is helpful because it conveniently hides argument details of cygrunsrv. I do agree, though, that acpipowerbutton is a better "stop" option than savestate. – Derek Mahar Oct 18 '16 at 15:30
  • @DerekMahar Take it for whatever it's worth, I suppose. Since it doesn't work on anything newer than XP, I doubt that's a whole lot in any case. ¯\_(ツ)_/¯ Thanks for the feedback! – Aaron Miller Oct 18 '16 at 17:20
  • Aaron Miller, do you mean your script or vboxd doesn't work on any Windows newer than XP? I presume you mean your script because I did get vboxd to work on Windows 10 with VirtualBox 5.1.6. – Derek Mahar Oct 18 '16 at 18:18
  • @DerekMahar I mean my script, not vboxd. – Aaron Miller Oct 18 '16 at 20:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.