Utworzyłem skrypt Pythona, który zawiesiłby wszystkie działające maszyny wirtualne VirtualBox, a następnie skonfigurowałem system do uruchamiania skryptu podczas wylogowywania jako zaplanowane zadanie.
Nie wiem, jak niezawodna jest ta metoda. Jak zauważyli inni, istnieją ograniczenia dotyczące czasu oczekiwania systemu na zakończenie zadania Winlogon 7002. Ale ja osobiście nie miałem z tym problemu, dając użyteczne stany zapisu, nawet przy wielu działających maszynach wirtualnych na ponad 4 GB ogólnej pamięci RAM maszyny wirtualnej.
Oto kroki, aby to skonfigurować:
- Pobierz i zainstaluj Python 2.7.x ze strony python.org
- Utwórz plik skryptu python gdzieś w systemie za pomocą Notatnika lub innego edytora zwykłego tekstu (patrz poniżej)
- Otwórz Harmonogram zadań
- Wybierz polecenie Działanie -> Utwórz zadanie podstawowe ... i użyj kreatora, aby utworzyć zadanie z następującymi ustawieniami
- Imię twojego wyboru
- Uruchom zadanie po zarejestrowaniu określonego zdarzenia
- Log: System
- Źródło: Winlogon
- Identyfikator zdarzenia: 7002
- Uruchom program
- Obok programu / skryptu , wprowadź pełną ścieżkę dostępu do
python.exe
, na przykładc:\Python27\python.exe
- Obok opcji Dodaj argumenty podaj pełną ścieżkę do pliku skryptu Pythona, na przykład umieściłem mój w podfolderze folderu moich dokumentów, więc jest to
C:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
- Wybierz Zakończ.
Teraz maszyny wirtualne VirtualBox powinny zostać zawieszone przy wylogowaniu / ponownym uruchomieniu / zamknięciu.
Skrypt Pythona do zamykania systemu znajduje się poniżej:
# A script to suspend all running VirtualBox VMs
import os
import subprocess
import sys
class VM(object):
def __init__(self, name, uuid):
self.name = name
self.uuid = uuid
def __repr__(self):
return "VM(%r,%r)" % (self.name, self.uuid)
class VBoxRunner(object):
def __init__(self):
program_files = os.environ["ProgramW6432"]
vbox_dir = os.path.join(program_files, "Oracle", "VirtualBox")
self.vboxmanage_filename = os.path.join(vbox_dir, "VBoxManage.exe")
def vbox_run(self, *args):
subprocess.check_call([self.vboxmanage_filename] + list(args))
def vbox_run_output(self, *args):
return subprocess.check_output([self.vboxmanage_filename] + list(args))
def list(self, running=True):
if running:
list_cmd = "runningvms"
else:
list_cmd = "vms"
return [self.parse_vm_list_entry(x) for x in self.vbox_run_output("list", list_cmd).strip().split("\n")]
def suspend_all(self):
success = True
stopped_some_vms = False
vms = self.list(running=True)
for vm in vms:
if vm is None:
continue
# noinspection PyBroadException
try:
self.suspend_vm(vm)
except:
success = False
else:
stopped_some_vms = True
if not stopped_some_vms:
self.message("No running vms")
return success
@staticmethod
def parse_vm_list_entry(x):
""":type x: str"""
if not x.startswith('"'):
return None
end_pos = x.find('"', 1)
if end_pos == -1:
return None
name = x[1:end_pos]
assert x[end_pos + 1: end_pos + 3] == " {"
assert x.endswith("}")
uuid = x[end_pos + 2:]
return VM(name, uuid)
@staticmethod
def message(msg):
print >>sys.stderr, msg
def suspend_vm(self, vm):
assert isinstance(vm, VM)
self.vbox_run("controlvm", vm.uuid, "savestate")
def main():
vr = VBoxRunner()
success = vr.suspend_all()
if not success:
sys.exit(1)
if __name__ == "__main__":
main()