Hi, All

I have a script that should allow me to shut down VM’s, but it’s giving me grief.

The script looks like this:

$waitstart = 200 
$waitshutdown = 120 
 
if ($args[1] -match "on") { 
$inputfile=get-content $args[0] 
foreach ($guest in $inputfile) { 
write-host "Starting '$guest'"
#THE LINE BELOW HAS PROBLEMS!
$vm = gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname='$guest'"
$result = $vm.requeststatechange(2) 
if ($result.returnvalue -match "on") { 
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 "off") { 
$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 "off") { 
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:\scripts\hosts.txt off" -foregroundcolor yellow 
write-host "USAGE: to start VMs," -nonewline; write-host ".\managehyperV.ps1 c:\scripts\hosts.txt on" -foregroundcolor yellow 
} 

And it should work, apart from the line I indicated as not working:

$vm = gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname='$guest'"

So I looked further into it, and could get awn output of the query, as long as I don’t try to define the elementname bit (I’ve listed the host here, plus one of the Guests I’m trying to manipulate):

PS C:\Scripts> gwmi -namespace root\virtualization -query "select * from msvm_computersystem"

__GENUS                       : 2
__CLASS                       : Msvm_ComputerSystem
__SUPERCLASS                  : CIM_ComputerSystem
__DYNASTY                     : CIM_ManagedElement
__RELPATH                     : Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="SUPPORT"
__PROPERTY_COUNT              : 29
__DERIVATION                  : {CIM_ComputerSystem, CIM_System, CIM_EnabledLogicalElement, CIM_LogicalElement...}
__SERVER                      : SUPPORT
__NAMESPACE                   : root\virtualization
__PATH                        : \\SUPPORT\root\virtualization:Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="SUPPORT"
AssignedNumaNodeList          : 
Caption                       : Hosting Computer System
CreationClassName             : Msvm_ComputerSystem
Dedicated                     : 
Description                   : Microsoft Hosting Computer System
ElementName                   : SUPPORT
EnabledDefault                : 2
EnabledState                  : 2
HealthState                   : 5
IdentifyingDescriptions       : 
InstallDate                   : 
Name                          : SUPPORT
NameFormat                    : 
OnTimeInMilliseconds          : 
OperationalStatus             : {2}
OtherDedicatedDescriptions    : 
OtherEnabledState             : 
OtherIdentifyingInfo          : 
PowerManagementCapabilities   : 
PrimaryOwnerContact           : 
PrimaryOwnerName              : 
ProcessID                     : 
RequestedState                : 12
ResetCapability               : 1
Roles                         : 
Status                        : 
StatusDescriptions            : {OK}
TimeOfLastConfigurationChange : 
TimeOfLastStateChange         : 
PSComputerName                : SUPPORT

__GENUS                       : 2
__CLASS                       : Msvm_ComputerSystem
__SUPERCLASS                  : CIM_ComputerSystem
__DYNASTY                     : CIM_ManagedElement
__RELPATH                     : Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="DDE47CAF-EC2E-4E1D-8A0E-FBACA72D6E7F"
__PROPERTY_COUNT              : 29
__DERIVATION                  : {CIM_ComputerSystem, CIM_System, CIM_EnabledLogicalElement, CIM_LogicalElement...}
__SERVER                      : SUPPORT
__NAMESPACE                   : root\virtualization
__PATH                        : \\SUPPORT\root\virtualization:Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="DDE47CAF-EC2E-4E
                                1D-8A0E-FBACA72D6E7F"
AssignedNumaNodeList          : {}
Caption                       : Virtual Machine
CreationClassName             : Msvm_ComputerSystem
Dedicated                     : 
Description                   : Microsoft Virtual Machine
ElementName                   : VMSUPP-WIN7-MI7
EnabledDefault                : 2
EnabledState                  : 3
HealthState                   : 5
IdentifyingDescriptions       : 
InstallDate                   : 20140610111150.000000-000
Name                          : DDE47CAF-EC2E-4E1D-8A0E-FBACA72D6E7F
NameFormat                    : 
OnTimeInMilliseconds          : 0
OperationalStatus             : {2}
OtherDedicatedDescriptions    : 
OtherEnabledState             : 
OtherIdentifyingInfo          : 
PowerManagementCapabilities   : 
PrimaryOwnerContact           : 
PrimaryOwnerName              : 
ProcessID                     : 0
RequestedState                : 12
ResetCapability               : 1
Roles                         : 
Status                        : 
StatusDescriptions            : {Operating normally}
TimeOfLastConfigurationChange : 20141217085039.102211-000
TimeOfLastStateChange         : 20141217102712.000000-000
PSComputerName                : SUPPORT

So that bit looks correct, right?
Moving forward (and I think the Spiceworks WYSIWYG doesn't like so many text boxes!) I tried to refine it a little more:

```
PS C:\Scripts> gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname=VMSUPP-WIN7-MI7"
gwmi : Invalid query "select * from msvm_computersystem where elementname=VMSUPP-WIN7-MI7"
At line:1 char:1
+ gwmi -namespace root\virtualization -query "select * from msvm_computersystem wh ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

PS C:\Scripts> gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname="VMSUPP-WIN7-MI7""
Get-WmiObject : A positional parameter cannot be found that accepts argument 'VMSUPP-WIN7-MI7'.
At line:1 char:1
+ gwmi -namespace root\virtualization -query "select * from msvm_computersystem wh ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetWmiObjectCommand

```

And it's at this point that my meager skills run out.

I tried Get-vm, but am told it doesn't exist as a command, so can't use that, despite using Powershell 3.0.

Anyone got any ideas?

4 Spice ups

Hmmm. OK, it worked when I used the name, and not the variable, but also when I used the CORRECT quotes!

PS C:\Scripts> gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname='VMSUPP-WIN7-MI7'"

__GENUS                       : 2
__CLASS                       : Msvm_ComputerSystem
__SUPERCLASS                  : CIM_ComputerSystem
__DYNASTY                     : CIM_ManagedElement
__RELPATH                     : Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="DDE47CAF-EC2E-4E1D-8A0E-FBACA72D6E7F"
__PROPERTY_COUNT              : 29
__DERIVATION                  : {CIM_ComputerSystem, CIM_System, CIM_EnabledLogicalElement, CIM_LogicalElement...}
__SERVER                      : SUPPORT
__NAMESPACE                   : root\virtualization
__PATH                        : \\SUPPORT\root\virtualization:Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="DDE47CAF-EC2E-4E1D-8A0E-FBACA72D6E
                                7F"
AssignedNumaNodeList          : {}
Caption                       : Virtual Machine
CreationClassName             : Msvm_ComputerSystem
Dedicated                     : 
Description                   : Microsoft Virtual Machine
ElementName                   : VMSUPP-WIN7-MI7
[SNIP]

But still not working if I plug it into the script and use the $guest variable, which is pulled from a text file, which simply reads: vmsupp-win7-mi7

What error do you get when using the variable? What server version is this?

I’m doing a few checks here but the class name changed in win 8.1 so I can’t debug your exact code

Sorry…

Win server 2008 R2, with the updated Powershell 3.0

However… I THINK it’s now working! I changed the " to ’ and it seems t be turning things off and on again - Except it reports that it can’t.

I guess that’s the two variables at the top being too short? What is that measured in? MS?

All that write host hurts my eyes, I think the whole script can be shortened and improved.

2 Spice ups

HEH! That wouldn’t surprise me, Bill…

Sorry for the pain in the eyes!

I think my next step is to have it generate the text file of those machines which are actually running…

So I don’t have to prepare a list of servers I want to work with… and to automate it a little further.

But everyone has to start somewhere, right?

I have some ideas, will post later, I’m on my phone at the moment.

1 Spice up

What I was getting when I ran was a carriage return in the variable which made the query invalid but glad to see you got it working.

I think I would still look at getting the native hyper-v commands working, they do make things much easier, in fact that whole script could probably be done on about 5 lines.

2 Spice ups

Possibly that’ll come when I’ve upgraded to Server 2012… :slight_smile:

I’m not sure it’s the case here, but in quite a few cmdlets the items in a query string are case sensitive. Have you tried using “ElementName” instead of “elementname”?

1 Spice up

I can confirm it’s not case sensitive in this case…

See these as to why you should re-consider using Write-Host in this fashion:

http://jeffwouters.nl/index.php/2014/01/write-host-the-gremlin-of-powershell/

http://powershell.org/wp/forums/topic/write-host-a-no-no/

What Might be a better option:

2 Spice ups
If( $vm.EnabledState -ne 2) {
    $result = $vm.requeststatechange(2) 
    if ($result.returnvalue -eq 4096 -or $result.returnvalue -eq 0) { 

I am really fuzzy on this. I’m sure there is a different way to go about this, but you said the hyper-v cmdlets aren’t working, so, going with your code. ‘on’ isn’t a value that will be in $result.returnvalue. According to this: RequestStateChange method of the Msvm\_ComputerSystem class | Microsoft Learn , your only valid values are going to be 0 and 4096 to indicate that the method is actually starting the vm. Also, you need to check the status before you start the vm, as you will error out if you don’t.

Also, you are assuming the VM is started after 200 seconds. You should really loop there, or something, and do the WMI call again to check the enabled state again.

That is why it is reporting incorrectly. The same logic applies to the section where you want to turn the vms off.

1 Spice up

And you could just manage that with the hyper-v cmdlets from an RSAT machine, right?

1 Spice up
write-host "Starting '$guest'"

Is this portion of the script displaying the correct guest?

It didn’t work the first time with the name in the variable because you used single quotes on this line:

$vm = gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname='$guest'"

Do not wrap the $guest variable in single quotes on powershell will think you want that exact text as the string ‘$guest’ not ‘VMSUPP-WIN7-MI7’

The line should read:

$vm = gwmi -namespace root\virtualization -query "select * from msvm_computersystem where elementname=$guest"
1 Spice up

And this is exactly what I meant in my post above. If you were to run this write-host command you would see:

Starting $guest

because you wrapped it in single quotes, when you are expecting it to be:

Starting VMSUPP-WIN7-MI7

4 Spice ups

Yes it was/is… :slight_smile:

To all who helped, THANK YOU!

I can’t give out as many ‘helpful posts’ as I might like, but tried to spread the love around a bit!

1 Spice up