I am attempting to use a script that shuts down my Hyper-V VMs, copies their VHDs to a target share, then boots them back up. I found the script on spiceworks just a couple days ago. I always receive errors that the system name intended for shutdown is a null value.
General info:
- I have been running powershell as an admin.
- I set my ExecutionPolicy to "RemoteSigned" so that local powershell files will execute.
- I appear to be running PowerShell v 2.0
- I am running HyperV in Server 2008 R2
- I am executing this script directly on the VM host
Below is the script and an explanation of where I encounter the error and exactly what that error is:
$waitstart = 200
$waitshutdown = 120
if ($args[1] -match "0") {
$inputfile=get-content $args[0]
foreach ($guest in $inputfile) {
write-host "Starting $guest"
$vm = gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname='$guest'"
$result = $vm.requeststatechange(2)
if ($result.returnvalue -match "0") {
start-sleep -s $waitstart
write-host ""
write-host "$guest is started" -foregroundcolor green
write-host ""
}
else {
write-host ""
write-host "unable to start $guest" -foregroundcolor red
write-host ""
}}}
if ($args[1] -match "1") {
$inputfile=get-content $args[0]
foreach ($guest in $inputfile) {
write-host "shutting down $guest"
$vm = gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname='$guest'"
$vmname = $vm.name
$vmshut = gwmi -namespace root\virtualization -query "SELECT * FROM Msvm_ShutdownComponent WHERE SystemName='$vmname'"
$result = $vmshut.InitiateShutdown("$true","no comment")
if ($result.returnvalue -match "0") {
start-sleep -s $waitshutdown
write-host ""
write-host "no error while shutting down $guest"
write-host "shutdown of $guest completed" -foregroundcolor green
write-host ""}
else {
write-host ""
write-host "unable to shutdown $guest" -foregroundcolor red
write-host ""
}}}
else {
write-host "USAGE: to shutdown VMs," -nonewline; write-host ".\managehyperV.ps1 c:\hosts.txt 1" -foregroundcolor yellow
write-host "USAGE: to start VMs," -nonewline; write-host ".\managehyperV.ps1 c:\hosts.txt 0" -foregroundcolor yellow
}
The script takes in the argument "1" or "0" to determine whether the VMs in the "guests" text list should be shut down or started.
Running Powershell as an admin I can successfully run the following query:
$vm = gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname='$guest'"
This returns a string of some kind that represents the system name of the VM.
However, the following query always returns a null value:
$vmshut = gwmi -namespace root\virtualization -query "SELECT * FROM Msvm_ShutdownComponent WHERE SystemName='$vmname'"
It seems as though the 'Msvm_ShutdownComponent' class doesn't exist on my system… when I execute the following line:
$result = $vmshut.InitiateShutdown("$true","no comment")
I always receive an error that states "You cannot call a method on a null-valued expression". I have spent about a day and a half trying to find the mistake I am making that causes this, but I can't narrow it down.
Best Answer
I have created a script that meets my needs and I will post it here.
This script performs the following tasks:
This script can operate on remote physical hosts and does not need to be run locally. Be sure to run the script with administrative credentials or it will not work correctly.
I am using Windows Server 2008 R2 and so I don't have access to all the fancy commands available in Windows Server 2012.
Also, this is the ultimate expression of "script kiddie" here; I've mashed together about 4 different scripts and then added some logic on top of it. Forgive the inconsistencies in syntax etc.
This script was hand transcribed from a standalone corporate sysem I use, so it may have a few spelling errors. I haven't tried to execute this script directly. The one on my system seems to work just fine.