Help improve and/or fix Hyper v host and its VMs restart script

Hello All,

Not a scripting guy here. I ended up with a script, which shutdown all VMs and then restart the Hyper V. I am making use of Syncro’s RMM automation so that when all VMs are shutdown then RMM trigger a reboot of the Hyperv Host. This is intention but not working. Issue I am having

Script gets stuck in progress even after an hour. Script timeout limit is set to 15 minutes and runs as System. No RMM alert is triggered from the script

Please see script below

Import-Module $env:SyncroModule -WarningAction SilentlyContinue

$listVM = (Get-VM | Where-Object {$_.State -eq 'Running'}).Name

$vmOff = (Get-VM | Where-Object {$_.State -eq 'Off'}).Count

$jobList = @()

$ResultArray = @()

$vmRun = $listVM.Count

$totalVMs = $vmRun + $vmOff

Log-Activity -Message "There are $vmRun VMs running and $vmOff VMs not running. Total of $totalVMs VMs" -EventName "Maintenance"

Foreach ($vm in $listVM) {
    
    $scriptblock = {

        Stop-VM "$($args[0])" -Force
        Write-Host "$($args[0]) shutdown complete."
    }   
    
    $jobList += Start-Job -ScriptBlock $scriptblock -ArgumentList $vm  
}

Wait-Job -Job $jobList | Out-Null

foreach($job in $jobList)
{
    $ResultArray += Receive-Job -Job $job
}

$jobList | Remove-Job

$ResultArray

$checkAllVM = (Get-VM | Where-Object {$_.State -eq "Off"}).Count

if($checkAllVM -eq $totalVMs)
{
    Log-Activity -Message "All $($vmRun) running VMs were shutdown" -EventName "Maintenance"

    if($bill -eq "Yes"){

        Rmm-Alert -Category 'Hyper-V_Maintenance' -Body 'VMs were shutdown'
        Write-Host "Billing was enabled"
    }
    else
    {
        Rmm-Alert -Category 'Hyper-V_Maintenance' -Body 'NB - VMs were shutdown'
        Write-Host "Billing was disabled"
    }
    <#
    .DESCRIPTION
        Script does not restart the host. Rather generates Alert which triggers restart of the Host.
        Issue was Script would still be active after the restart of the host and the VMs shutdowm gets triggered again!!!
        #Start-Sleep -Seconds 5
        #shutdown /r /t 5 /d p:1:1
    #>
    [Environment]::Exit(0)


}
else {

    Write-Output "One of the VMs is still running"
    Rmm-Alert -Category 'Hyper-V_Maintenance_Aborted' -Body 'Restart of HyperV aborted. One of the VMs still running'
    [Environment]::Exit(1)
}

Any help with be appreciated.

Run the script on the machine itself so you can see what’s happening. The script timeout does not kill the script, it just stops waiting for output and lets the agent move on to another task/script. I’m not sure why this script is needed at all, though, Hosts restart just fine by themselves pausing and restarting the VM’s automatically assuming you have the settings set.
EDIT: I wasn’t thinking clearly, the script does get killed, however the last command will continue regardless, so the script will close but the hung command persists til reboot/completion.

Thanks @isaacg very much appreciated. I have not used this feature out of fear I guess. Will do a test run. This would be a perfect solution.

Check your shutdown options on VMs. Hyper-V does a great job of pausing or shutting down VMs when it needs to reboot, and will not hard kill a VM unless set to do so, or the shutdown timeout is exceeded. I don’t have the link handy but my memory is that the hyper-v shutdown time limit by default is something like 4 hours.

It is recomeneded that anything with a Database (Domain Controllers, SQL Servers etc) always be set to shut down instead of pausing. It’s also not a bad idea to set the VMs to “Always start” instead of resuming state at shutdown.

@jordanritz and @isaacg . Thanks for the advice. I shall change the config to Shutdown on each VM rather the default option of “Save”.