VirtualBox VM auto-shutdown

04 January 2014 (updated 20 September 2018)

So I've decided to really try Vagrant again - there's just this annoyance that makes it very inconvenient: on Windows, VirtualBox doesn't graciously shutdown your VMs. Logged off? Aborted VM. Shutdown in rush? You probably forgot to take care of those VMs. Want to worder every time about why some service doesn't start at boot? Want to recover that mongo database every time you forgot to sudo shutdown or vagrant halt? I certainly do not.

There's a mysterious IMachine::autostopType property in the vboxapi but it appears that it's not supported on Windows :(

So the plan is to create some tool to make those VMs get a nice, gracious ACPI shutdown. And if ACPI shutdown not possible then suspend them.

I've tried to make logoff scripts to run vagrant halt but it appears that by the time the script is run the VMs are already killed. Bummer.

Because the VMs are started by Vagrant under the user's account we cannot use any Windows Service based solution [1].

So, the plan *

Is going to be like this:

  • Have some sort of process that runs in the background.
  • Have a notification area icon (to see that it's running and maybe disable it).
  • When process is sent WM_ENDSESSION, WM_QUERYENDSESSION, WM_QUIT, WM_CLOSE or anything that might look like a logoff/shutdown event then shamelessly block and patiently wait for all the VMs to shutdown.
  • Make the process get the close messages first (set priority using SetProcessShutdownParameters).
  • For each VM the shutdown process is going to be like this:
    • Unpause if VM paused.
    • Send ACPI shutdown signal, wait for a state change for 10 seconds
    • If machine still running then suspend it, wait again till it changes state.

I've implemented it here - give it shot!

Install *

Here's what you need to run it:

  • Download somewhere there are write permissions (it will create a logfile unless you specify it a different path).
  • Python 2.7 with same architecture as VirtualBox - if you have 64bit system most probably you'll need a 64-bit Python (I've used the COM api - it doesn't allow cross arch interop for now [3]). This could change by using the command line API if anyone really wanted this. Anyone can fix it - it's just some Python code.
  • Install pywin32 - same architecture/reason as above. [2]
  • Install the vboxapi package. Running python install in c:\Program Files\Oracle\VirtualBox\sdk\install\ did the trick for me. I wonder why they have this useless pypi package with no distributions ...

Now just run shell:startup and put the file in there.

Note *

I've tested this on Windows 8.1 but there's no reason it wouldn't run on older versions (or be something that cannot be fixed easily).

Obligatory screenshot *

Screenshot of VirtualBoxAutoShutdownTray

[1] - not what we need and looks like it's unmaintained too!
[2]64-bit or 32-bit pywin32.

This entry was tagged as python virtualbox windows