func GetRegisteredVmNameList() ([]string, error) {
	cmd := exec.Command("VBoxManage", "list", "vms")
	var out bytes.Buffer
	cmd.Stdout = &out

	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return nil, err
	}
	if exitStatus.ExitCode != 0 {
		return nil, fmt.Errorf("VBoxManage list vms failed with exitCode=%d", exitStatus.ExitCode)
	}

	var vmNames []string
	re := regexp.MustCompile(`^"(IE[\d.]+ - Win[\d.]+)"`)
	scanner := bufio.NewScanner(&out)
	for scanner.Scan() {
		line := scanner.Text()
		values := re.FindAllStringSubmatch(line, 1)
		if values != nil {
			vmName := values[0][1]
			vmNames = append(vmNames, vmName)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("Error during reading output of VBoxManage list vms: %s", err)
	}

	return vmNames, nil
}
func DoesVmExist(vmName string) (bool, error) {
	cmd := exec.Command("VBoxManage", "showvminfo", vmName)
	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return false, err
	}
	if exitStatus.ExitCode == 0 {
		return true, nil
	} else {
		return false, nil
	}
}
func StartVm(vmName string) error {
	cmd := exec.Command("VBoxManage", "startvm", vmName, "--type", "gui")
	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return err
	}
	if exitStatus.ExitCode == 0 {
		return nil
	} else {
		return fmt.Errorf("VBoxManage startvm \"%s\" failed with exitCode=%d", vmName, exitStatus.ExitCode)
	}
}
func takeSnapshot(vmName, snapshotName string) error {
	cmd := exec.Command("VBoxManage", "snapshot", vmName, "take", snapshotName)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return err
	}
	if exitStatus.ExitCode == 0 {
		return nil
	} else {
		return fmt.Errorf("VBoxManage snapshot for VM \"%s\" failed with exitCode=%d", vmName, exitStatus.ExitCode)
	}
}
func SetClipboardMode(vmName, clipboardMode string) error {
	cmd := exec.Command("VBoxManage", "controlvm", vmName, "clipboard", clipboardMode)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return err
	}
	if exitStatus.ExitCode == 0 {
		return nil
	} else {
		return fmt.Errorf("VBoxManage controlvm for setting clipboard mode of VM \"%s\" failed with exitCode=%d", vmName, exitStatus.ExitCode)
	}
}
func attachGuestAdditionsMedia(vmName string) error {
	cmd := exec.Command("VBoxManage", "storageattach", vmName, "--storagectl", "IDE", "--port", "1", "--device", "0", "--type", "dvddrive", "--medium", "additions")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return err
	}
	if exitStatus.ExitCode == 0 {
		return nil
	} else {
		return fmt.Errorf("VBoxManage storageattach for VM \"%s\" failed with exitCode=%d", vmName, exitStatus.ExitCode)
	}
}
func importVm(ovaFilename string) error {
	cmd := exec.Command("VBoxManage", "import", ovaFilename)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return err
	}
	if exitStatus.ExitCode == 0 {
		return nil
	} else {
		return fmt.Errorf("VBoxManage import \"%s\" failed with exitCode=%d", ovaFilename, exitStatus.ExitCode)
	}
}
func configVmMemory(vmName string) error {
	osVersion := getOSVersionFromVMName(vmName)
	var cmd *exec.Cmd
	if osVersion == "WinXP" || osVersion == "Vista" {
		cmd = exec.Command("VBoxManage", "modifyvm", vmName, "--memory", "1024")
	} else if osVersion == "Win7" || osVersion == "Win8" || osVersion == "Win8.1" || osVersion == "Win10" {
		cmd = exec.Command("VBoxManage", "modifyvm", vmName, "--memory", "2048", "--vram", "128")
	} else {
		return fmt.Errorf("Unsupported os version: %s", osVersion)
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	exitStatus, err := executil.Run(cmd)
	if err != nil {
		return err
	}
	if exitStatus.ExitCode == 0 {
		return nil
	} else {
		return fmt.Errorf("VBoxManage import \"%s\" failed with exitCode=%d", vmName, exitStatus.ExitCode)
	}
}