Jump to content

Recommended Posts

Posted (edited)

I'd like a VM that I can just copy from the host PC to another PC and keep running it.
The defaults are paths are that the "Virtual Hard Disks" goes somewhere and the setting elsewhere. And I find myself exporting the newly created VM to a set folder, deleting the VM to then import the VM just to have it all in one place.
If I want to move the VM from the current hardware to another hardware, all I have to do ( via this way ) is to copy the folder where the exported ( and registered in place ) is at to the other PC.
Easy-peasy :) 

Do I need help ?, nope. But I coded a "do it for me" so is easier/faster to get done, that to me is not an example script, not even in quality of code, but it gets the job done.

 image.png.e339421711817ef87a78b224ccb3c574.png

The code is down in the next post, so that I can mark it as solved :D 

Edited by argumentum
English

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • Solution
Posted (edited)
#NoTrayIcon
#RequireAdmin

#include <File.au3>
#include <_RunWaitEx.au3> ; https://www.autoitscript.com/forum/index.php?showtopic=212643
#include <Date.au3>

#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=

Global $g_ini = StringTrimRight(@ScriptFullPath, 4) & ".ini"
Global $hForm = 0, $idLog = 0, $g_sGetVMHost

Exit gui()
Func gui()
    Local $hTimer = TimerInit()
    Local $sFormTitle = "Hyper-V - CreateNewVM", $iW = 600, $iH = 400, $iTop = 10, $iLabelWidth = 120, $iInputWidth = 340
    $hForm = GUICreate($sFormTitle, $iW, $iH, -1, -1, BitOR($GUI_SS_DEFAULT_GUI,$WS_MAXIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_TABSTOP))
    GUISetIcon(StringTrimRight(@ScriptFullPath, 4) & ".ico")
    GUISetFont(10)
;~  GUISetBkColor(0x303030) ; for my dark mode theme
    GUICtrlCreateLabel("VM name: ", 10, $iTop, $iLabelWidth, 19, $SS_RIGHT);, $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKTOP+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
    $idVmName = GUICtrlCreateInput("vm-Temp01", $iLabelWidth + 8, $iTop - 1, $iInputWidth, 23, -1, BitOR($WS_EX_CLIENTEDGE, $WS_EX_STATICEDGE))
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)

    $iTop += 27
    GUICtrlCreateLabel("VM Version: ", 10, $iTop, $iLabelWidth, 19, $SS_RIGHT);, $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKTOP+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
    $idVmVersion = GUICtrlCreateCombo("", $iLabelWidth + 8, $iTop - 2, $iInputWidth - 100, 25, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL), $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)
    GUICtrlSetState($idVmVersion, $GUI_DISABLE)

    $idVmVersionHelp = GUICtrlCreateButton("Help", $iW - 110 - 100, $iTop, 80, 23)
    GUICtrlSetTip($idVmVersionHelp, "About virtual machine versions")
    GUICtrlSetResizing(-1, $GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT+$GUI_DOCKWIDTH)

    $idGenerateVm = GUICtrlCreateButton("Generate VM", $iW - 110, $iTop, 100, 25)
    GUICtrlSetResizing(-1, $GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT+$GUI_DOCKWIDTH)
    GUICtrlSetState($idVmVersion, $GUI_DISABLE)

    $iTop += 27
    GUICtrlCreateLabel("VM Generation: ", 10, $iTop, $iLabelWidth, 19, $SS_RIGHT);, $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKTOP+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
    $Combo = GUICtrlCreateCombo("", $iLabelWidth + 8, $iTop - 2, $iInputWidth, 25, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL), $WS_EX_STATICEDGE)
    GUICtrlSetData(-1, "1|2", "2")
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)

    $iTop += 27
    GUICtrlCreateLabel("SwitchName: ", 10, $iTop, $iLabelWidth, 19, $SS_RIGHT);, $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKTOP+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
    $idSwitchName = GUICtrlCreateCombo("", $iLabelWidth + 8, $iTop - 2, $iInputWidth, 25, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL), $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)
    GUICtrlSetState($idSwitchName, $GUI_DISABLE)

    $iTop += 27
    GUICtrlCreateLabel("HDD size (GB): ", 10, $iTop, $iLabelWidth, 19, $SS_RIGHT, $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKTOP+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
    $idVmHddSize = GUICtrlCreateInput(Int(IniRead($g_ini, "Defaults", "VmHddSize", "127")), $iLabelWidth + 8, $iTop - 1, $iInputWidth, 23, -1, BitOR($WS_EX_CLIENTEDGE, $WS_EX_STATICEDGE))
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)

    $iTop += 27
    GUICtrlCreateLabel("Import VMs path: ", 10, $iTop, $iLabelWidth, 19, $SS_RIGHT, $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKTOP+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
    $idVmExportsPath = GUICtrlCreateInput(IniRead($g_ini, "Defaults", "VmExportsPath", "C:\Make\A\Path\For\ExportImport"), $iLabelWidth + 8, $iTop - 1, $iW - $iLabelWidth - 20 , 23, -1, BitOR($WS_EX_CLIENTEDGE, $WS_EX_STATICEDGE))
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)



    $iTop += 27
    $idLog = GUICtrlCreateEdit("", 0, $iTop, $iW, $iH - $iTop)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKBOTTOM)
    GUICtrlSetFont($idLog, 10, 800)

    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

    GUICtrlSetData($idLog, "... please wait ...")
    AdlibRegister(AdlibAddDot, 300)

    $iRet = _RunWaitEx('powershell "Get-VMHost | Select-Object VirtualHardDiskPath, VirtualMachinePath, SupportedVmVersions, InternalNetworkAdapters | ConvertTo-Json | Out-File ''' & @TempDir & '\output-' & $hTimer & '.json''"', @TempDir, @SW_HIDE)
    $g_sGetVMHost = FileRead(@TempDir & '\output-' & $hTimer & '.json')
    FileDelete(@TempDir & '\output-' & $hTimer & '.json')
;~  ConsoleWrite(@CRLF & $g_sGetVMHost & @CRLF)
    GuiPopulate_idVmVersion($idVmVersion)
    GuiPopulate_idSwitchName($idSwitchName)

    AdlibUnRegister(AdlibAddDot)
    GUICtrlSetData($idLog, "Ready")

    GUICtrlSetState($idVmVersion, $GUI_ENABLE)
    GUICtrlSetState($idSwitchName, $GUI_ENABLE)



    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                GUISetState(@SW_HIDE)
                IniWrite($g_ini, "Defaults", "VmVersion", GUICtrlRead($idVmVersion))
                IniWrite($g_ini, "Defaults", "SwitchName", GUICtrlRead($idSwitchName))
                IniWrite($g_ini, "Defaults", "VmHddSize", GUICtrlRead($idVmHddSize))
                IniWrite($g_ini, "Defaults", "VmExportsPath", GUICtrlRead($idVmExportsPath))
                GUIDelete()
                Exit

            Case $idVmVersionHelp
                ShellExecute("https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/deploy/upgrade-virtual-machine-version-in-hyper-v-on-windows-or-windows-server")

            Case $idGenerateVm
                $sNewVmName = GUICtrlRead($idVmName)
                $sNewVmHddSize = GUICtrlRead($idVmHddSize)
                $sNewVmExportsPath = GUICtrlRead($idVmExportsPath)
                GUICtrlSetState($idGenerateVm, $GUI_DISABLE)
                GUICtrlSetData($idLog, "... running ...")
                AdlibRegister(AdlibAddDot, 1000)
                $sRet = NewVmAsImport($sNewVmName, $sNewVmHddSize, $sNewVmExportsPath)
                AdlibUnRegister(AdlibAddDot)
                GUICtrlSetData($idLog, $sRet)
                If _RunWaitEx_LastExtended() Then GUICtrlSetData($idLog, @CRLF & @CRLF & _RunWaitEx_LastStdout() & @CRLF & _RunWaitEx_LastStderr() & @CRLF, 1)
                GUICtrlSetState($idGenerateVm, $GUI_ENABLE)
        EndSwitch
    WEnd
EndFunc   ;==>gui

Func GuiPopulate_idVmVersion($idVmVersion)
    Local $sTemp, $sDefault, $aArray = StringSplit($g_sGetVMHost, "[]", 0)
    For $n = 1 To UBound($aArray) - 2
        If StringInStr($aArray[$n], '"SupportedVmVersions"') Then
            $sTemp = StringReplace(StringStripWS(StringReplace($aArray[$n + 1], ",", "|"), 8), '"', '')
            $sDefault = StringLeft($sTemp, StringInStr($sTemp, "|") - 1)
            ExitLoop
        EndIf
    Next ; https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/deploy/upgrade-virtual-machine-version-in-hyper-v-on-windows-or-windows-server
    $sDefault = IniRead($g_ini, "Defaults", "VmVersion", "8.0")
    If Not StringInStr('|' & $sTemp & '|', '|' & $sDefault & '|') Then $sDefault = ""
    GUICtrlSetData($idVmVersion, $sTemp, $sDefault)
EndFunc

Func GuiPopulate_idSwitchName($idSwitchName)
    Local $sTemp = "", $sDefault = "", $aTemp, $aArray = StringSplit($g_sGetVMHost, "[]", 0)
    For $n = 1 To UBound($aArray) - 2
        If StringInStr($aArray[$n], '"InternalNetworkAdapters"') Then
            $aTemp = StringSplit($aArray[$n + 1], @CRLF, 1)
            ExitLoop
        EndIf
    Next
    For $n = 1 To UBound($aTemp) - 2
        If StringInStr($aTemp[$n], '"SwitchName":') Then
            If StringLen($sTemp) Then $sTemp &= "|"
            $sTemp &= GetTheJsonValue($aTemp[$n])
            If $sDefault = "" Then $sDefault = $sTemp
        EndIf
    Next
    $sDefault = IniRead($g_ini, "Defaults", "SwitchName", $sDefault)
    If Not StringInStr('|' & $sTemp & '|', '|' & $sDefault & '|') Then $sDefault = ""
    GUICtrlSetData($idSwitchName, $sTemp, $sDefault)
EndFunc

Func GetTheJsonValue($sStr)
    Local $aArray = StringSplit($sStr, '"')
    Return $aArray[$aArray[0] - 1]
EndFunc

Func AdlibAddDot()
    GUICtrlSetData($idLog, ".", 1)
EndFunc

Func GetMe($sJson, $sStr, $sNext = Default)
    Local $iPos1 = StringInStr($sJson, '"' & $sStr & '"')
    If $sNext = Default Then
        Local $iPos2 = StringInStr($sJson, '"', 0, 1, $iPos1 + StringLen($sStr) + 3)
        Local $iPos3 = StringInStr($sJson, '"', 0, 1, $iPos2 + 1)
        Return StringReplace(StringReplace(StringMid($sJson, $iPos2, $iPos3 - $iPos2 + 1), '"', ''), '\\', '\')
    EndIf
    Return StringInStr($sJson, ' "' & $sNext & '"') ; meh  =/
EndFunc   ;==>GetMe

Func NewVmAsImport($sNewVmName = Default, $sNewVmHddSize = Default, $sNewVmExportsPath = Default)
    If Not IsAdmin() Then Return SetError(1, @ScriptLineNumber, "This script RequireAdmin !")
    Local $iRunEm = 1, $iRet, $sRun, $sVmName = "MyTestVM"
    Local $sRunDir = @TempDir
    Local $sRunShow = @SW_HIDE
    Local $sVmVersion = "8.0"
    Local $sSwitchName = "External 10G"
    Local $sVmGeneration = 2
    Local $hTimer = TimerInit()

    If FileExists($sNewVmExportsPath & "\" & $sNewVmName) Then Return SetError(1, @ScriptLineNumber, "VmName """ & $sNewVmName & """  exists in importPath """ & $sNewVmExportsPath & """ !")

    $iRet = _RunWaitEx('powershell "Get-VMHost | Select-Object VirtualHardDiskPath, VirtualMachinePath, SupportedVmVersions, InternalNetworkAdapters | ConvertTo-Json | Out-File ''' & $sRunDir & '\output-' & $hTimer & '.json''"', $sRunDir, $sRunShow)
    Local $sJson = FileRead(@TempDir & '\output-' & $hTimer & '.json')
    FileDelete(@TempDir & '\output-' & $hTimer & '.json')
    If $iRunEm And @extended Then Return SetError(1, @ScriptLineNumber, "Get-VMHost failed")

    $sJson = $g_sGetVMHost

    Local $sVirtualHardDiskPath = GetMe($sJson, "VirtualHardDiskPath") ; D:\\HV-defaults\\Virtual Hard Disks
    If Not FileExists($sVirtualHardDiskPath) Then Return SetError(1, @ScriptLineNumber, "VirtualHardDiskPath """ & $sVirtualHardDiskPath & """ don't exist ?!")
    Local $sVirtualMachinePath = GetMe($sJson, "VirtualMachinePath") ; D:\\HV-defaults\\Hyper-V
    If Not GetMe($sJson, "SupportedVmVersions", $sVmVersion) Then Return SetError(2, @ScriptLineNumber, "Bad Version !")
    If Not GetMe($sJson, "InternalNetworkAdapters", $sSwitchName) Then Return SetError(2, @ScriptLineNumber, "Bad SwitchName !")
    If $sNewVmName <> Default Then $sVmName = $sNewVmName
    If $sVmName = "" Then Return SetError(2, @ScriptLineNumber, "Needs a VM name !")
    Local $sVmHddSize = "127GB"
    If $sNewVmHddSize <> Default Then
        If Int($sNewVmHddSize) < 1 Then Return SetError(2, @ScriptLineNumber, "Wrong a VM HDD size !")
        $sVmHddSize = $sNewVmHddSize & "GB"
    EndIf

    Local $sVmExportsPath = "D:\HV-defaults\FreshExport"
    If $sNewVmExportsPath <> Default Then $sVmExportsPath = $sNewVmExportsPath
    Local $sVmID = ""
    Local $aArray = _FileListToArrayRec($sVmExportsPath & "\" & $sVmName, "*.vmcx", 1, 1)
    For $n = 1 To UBound($aArray) - 1
        $sVmID = $sVmExportsPath & "\" & $sVmName & "\" & $aArray[$n]
        ConsoleWrite('>' & $sVmExportsPath & "\" & $sVmName & "\" & $aArray[$n] & '<' & @CRLF)
        ExitLoop
    Next

    If $sVmID <> "" Then Return SetError(3, 0, "VM already exists")

    If Not FileExists($sVmExportsPath) Then Return SetError(4, @ScriptLineNumber, "VM export folder don't exists")

    $sRun = "powershell ""New-VM -Name '" & $sVmName & "' -MemoryStartupBytes 4GB -NewVHDPath '" & $sVmName & ".vhdx' -NewVHDSizeBytes " & $sVmHddSize & _
            " -Generation " & $sVmGeneration & " -SwitchName '" & $sSwitchName & "' -Version " & $sVmVersion & " "
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)
    If $iRunEm And @extended Then Return SetError(11, @ScriptLineNumber, "VM: New-VM failed")

    $sRun = "powershell ""Set-VM -VMName '" & $sVmName & "' -CheckpointType Production"""
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)

    $sRun = "powershell ""Set-VM -VMName '" & $sVmName & "' -AutomaticStartDelay 120""" ; https://virtualizationdojo.com/hyper-v/customize-vm-powershell/
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)

    $sRun = "powershell ""Set-VM -VMName '" & $sVmName & "' -AutomaticCheckpointsEnabled $False"""
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)

    $sRun = "powershell ""Set-VM -VMName '" & $sVmName & "' -Notes 'Created with \""" & StringTrimRight(@ScriptName, 4) & "\"" on " & _NowCalc() & "'"
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)

    $sRun = "powershell ""Export-VM -Name '" & $sVmName & "' -Path '" & $sVmExportsPath & "'"""
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)
    If $iRunEm And @extended Then Return SetError(12, @ScriptLineNumber, "VM: Export-VM failed")

    $sRun = "powershell ""Remove-VM -Name '" & $sVmName & "' -Force"""
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)
    If $iRunEm And @extended Then Return SetError(13, @ScriptLineNumber, "VM: Remove-VM failed")

    $aArray = _FileListToArrayRec($sVmExportsPath & "\" & $sVmName, "*.vmcx", 1, 1)
    For $n = 1 To UBound($aArray) - 1
        $sVmID = $sVmExportsPath & "\" & $sVmName & "\" & $aArray[$n]
        ConsoleWrite('>' & $sVmExportsPath & "\" & $sVmName & "\" & $aArray[$n] & '<' & @CRLF)
        ExitLoop
    Next

    $sRun = "powershell ""Import-VM -Path '" & $sVmID & "'"""
    If $iRunEm Then $iRet = _RunWaitEx($sRun, $sRunDir, $sRunShow)
    ConsoleWrite($sRun & @CRLF & '$iRet = ' & $iRet & ' - @error = ' & @error & ' - @extended = ' & @extended & @CRLF & @CRLF)
    If $iRunEm And @extended Then Return SetError(14, @ScriptLineNumber, "VM: Import-VM failed")

    If FileGetSize($sVirtualHardDiskPath & "\" & $sVmName & ".vhdx") = 4194304 Then ; .vhdx is new (4,194,304 bytes)
        FileDelete($sVirtualHardDiskPath & "\" & $sVmName & ".vhdx")
    EndIf

    Return SetError(0, @ScriptLineNumber, $sVmName & " is ready.")
EndFunc   ;==>NewVmAsImport

 

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...