Im Zuge des leidigen Themas (siehe hier [bei den Updates]), das ein virtualisierter Terminalserver nicht mehr ohne weiteres neustartet, nachdem es zu RDP-Verbindungsproblemen kam, musste eine hoffentlich nur vorläufige andere Lösung her, wie man den automatischen nächtlichen Neustart doch irgendwie lösen kann.

Bevor das Problem auftrat wurde schlicht mit einer Aufgabe innerhalb des virtuellen Computers um 04:00 Uhr in der früh der Neustart mittels

shutdown -r -f -t 0

ausgelöst. Seitdem das nicht mehr geht, wird das Ganze vom Hyper-V Host aus durchgeführt.

Die erste Skript-Version sah dabei so aus:

@echo off

rem Konfiguration

 set VMname=WTS02

rem VM herunterfahren

 start powershell Stop-VM -Name "%VMname%" -Force 

rem Pause

 timeout /t 360

rem Pruefen, ob die VM (immer) noch laueft
rem Falls ja, dann mit Gewalt (Restart-VM) neustarten.
rem Falls nein, normal (Start-VM) starten.

 ping "%VMname%" -4 -n 1 | find "TTL"

 rem Errorlevel:
 rem 0 ist Online
 rem 1 ist Offline

 if %errorlevel%==0 (
 powershell Restart-VM "%VMname%" -Force
 exit
 )

 if %errorlevel%==1 (
 powershell Start-VM "%VMname%"
 )

Man gibt dem virtuellen Computer erst noch die Chance normal herunterzufahren und anschl. neu zu starten. Ist der virtuelle Computer nach fünf Minuten immer noch anpingbar (was in diesem Fehlerfall wirklich noch funktioniert, nur alles andere nicht mehr), dann “zieh’ ihm den Stecker”.

Das funktionierte aber nur sporadisch. Hyper-V bemängelte das der virtuelle Computer bereits in einem Status wäre und dieser nicht geändert werden könne. Dabei macht es keinen Unterschied ob man “Restart-VM” oder “Stop-VM” oder eine Kombi aus beidem verwendet:

Restart-VM : Der Status von "WTS02" konnte nicht ge„ndert werden.
Der Vorgang kann nicht ausgefhrt werden, solange sich dieses Objekt im derzeitigen Status befindet.
In Zeile:1 Zeichen:1
+ Restart-VM WTS02 -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Restart-VM], VirtualizationException
+ FullyQualifiedErrorId : InvalidState,Microsoft.HyperV.PowerShell.Commands.RestartVM
Stop-VM : Der Status von "WTS02" konnte nicht ge„ndert werden.
Der Vorgang kann nicht ausgefhrt werden, solange sich dieses Objekt im derzeitigen Status befindet.
In Zeile:1 Zeichen:1
+ Stop-VM WTS02 -TurnOff -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Stop-VM], VirtualizationException
+ FullyQualifiedErrorId : InvalidState,Microsoft.HyperV.PowerShell.Commands.StopVM

Der Teil des Skript der mit einer Kombi versuchte den virtuellen Computer  herunterzufahren bzw. neu zu starten sind übrigens so aus:

setlocal enabledelayedexpansion

:loop

ping "%VMname%" -4 -n 1 | find "TTL"

rem Errorlevel:
rem 0 ist Online
rem 1 ist Offline

if %errorlevel%==0 (
taskkill /im powershell.exe /f
powershell Restart-VM "%VMname%" -Force
if !errorlevel! gtr 0 (
timeout /t 30
taskkill /im powershell.exe /f
powershell Stop-VM "%VMname%" -TurnOff -Force
if !errorlevel! gtr 0 goto loop
timeout /t 10 
powershell Start-VM "%VMname%"
)
)

if %errorlevel%==1 (
powershell Start-VM "%VMname%"
)

Die “taskkill”-Anweisungen waren zudem nötig, da auch die Powershell-Befehle hängen blieben.

Mitunter hing der virtuelle Computer dermaßen, das einem nur noch übrig blieb, den korrespondieren “vmwp.exe”-Prozess z.B. via Task-Manager oder Process Explorer abzuschießen. Nicht schön, aber auf alles andere folgte keine Reaktion mehr.

Damit nun Hyper-V von der Status-Änderung nichts mitbekommt und im Fehlerfall dann eben “Restart-VM” funktioniert musste dies etwas anders gelöst werden. Mit dem nachfolgenden Skript wird zunächst die Herunterfahren-Anweisung direkt an das Betriebssystem innerhalb des virtuellen Computers gesendet, wenn das klappt ist alles gut, wenn nicht, dann wieder “zieh’ ihm den Stecker”:

@echo off

rem Konfiguration

 set VMname=WTS02

rem VM herunterfahren
rem Bewusst nicht ueber Hyper-V Powershell, da es im Fehlerfall nicht weiter geht

 net use \\%VMname% <Kennwort> /user:WTS02\Administrator /persistent:no

 shutdown /m \\%VMname% /s /f /t 0

 net use \\%VMname% /d

rem Pause

 timeout /t 360

rem Pruefen, ob die VM (immer) noch laueft
rem Falls ja, dann mit Gewalt (Restart-VM) neustarten.
rem Falls nein, normal (Start-VM) starten.

 ping %VMname% -4 -n 1 | find "TTL"

 rem Errorlevel:
 rem 0 ist Online
 rem 1 ist Offline

 if %errorlevel%==0 powershell Restart-VM %VMname% -Force
 if %errorlevel%==1 powershell Start-VM %VMname%

Der Vollständigkeit halber sei erwähnt, es geht hier um einen stand-alone Hyper-V als auch stand-alone Terminalserver, mit anderen Worten: Arbeitsgruppe.