James O'Neill's blog

Windows Platform, Virtualization and PowerShell with a little Photography for good measure.

Getting to grips with Hyper-V's API

Getting to grips with Hyper-V's API

  • Comments 4
  • Likes

It's only 7 months since I first installed Powershell. Hard to believe that last week I saw a copy of the OCS res kit with my name on the cover as a result of the PowerShell scripts I wrote, and worth remembering before criticizing other people's scripts.

Over on Ben Armstrong's blog he has applied his virtualization expertise to showing how to use the newly published WMI management interface, posting samples using VB and "VB in powershell syntax" for example

$VMs = gwmi -class "MSVM_ComputerSystem" -namespace "root\virtualization" -computername "."
foreach ($VM in $VMs){
if ($VM.Caption -match "Microsoft Virtual Computer System"){
write-host "=================================="
write-host "VM Name: " $VM.ElementName
write-host "VM GUID: " $VM.Name
write-host "VM State: " $VM.EnabledState } }
Ben says he finds it easier to read that way, but I thought I'd show how we could do it in Powershell style. An If inside a for loop ? filter before looping 
VMs = (get-wmiobject -class "MSVM_ComputerSystem" -namespace "root\virtualization") | 
             where {$_.caption -match "Virtual"}
Or better, use the WMI Query Syntax to only return the objects you want
$VMs = get-wmiobject -namespace "root\virtualization" -query `
"SELECT * FROM Msvm_ComputerSystem WHERE Caption Like '*virtual*' "
The bit of Ben's code which says he's not been immersed in PowerShell is the for loop with write statements inside. It shouts "FORMAT-Table"
$VMs | Format-Table -autosize ElementName, Name, Enabledstate
If you prefer a list format you can always use Format-list, and if you want more helpful heading names you can use  @{Label="VM GUID"; expression={$_.Name}} as a field
$VMs | Format-Table -autosize @{Label="VM Name"; expression={$_.ElementName}} ,
@{Label="VM GUID"; expression={$_.Name}} , Enabledstate
In fact you could go step futher and expand the value in enabledState to text
@{Label="State"; expression={switch ($_.EnabledState) { 2 {"Running"} 3 {"Stopped"}
32768 {"Paused"} 32769 {"Suspended"} 32770 {"Starting"} 32771 {"Snapshotting"} 32773 {"Saving"} 32774 {"Stopping"} } }}
Of course I'll often take the approach "Variables! We don't need no stinking variables" and pipe the Get-WMIObject into Format-Table. But it's useful sometimes - like in choose functions I tend to write for many objects ...
Function Choose-VM
{$global:Counter=-1
 $VMs = get-wmiobject -namespace "root\virtualization" -query `
          "SELECT * FROM Msvm_ComputerSystem WHERE Caption Like '%virtual%' "
 Format-Table -inputobject $VMS @{ Label = "ID"; Expression={($global:counter++) }} ,
                                @{Label="VM Name"; expression={$_.ElementName}} ,
                                @{Label="VM GUID"; expression={$_.Name}} ,
                                @{Label="State"; expression={switch ($_.EnabledState) { 2 {"Running"} 3 {"Stopped"} 
                                                  32768 {"Paused"} 32769 {"Suspended"} 32770 {"Starting"}
                                                  32771 {"Snapshotting"} 32773 {"Saving"} 32774 {"Stopping"} } }} | out-host
$VMs[ [int[]](Read-Host "Which ones? ").Split(",")]}

Ben did a second post to show starting a virtual machine  - to do this I can just use

(choose-vm ) | foreach-object {$_.requestStateChange(2)} 

You could use anything which returns Msvm_ComputerSystem WMI objects and you can stop or pause one a machine just by requesting a different state to change to.  Shutting down a machine just by setting it's state to 3 for stopped is the virtual equivalent of hitting the power switch. The hyper-v integration components include one to trigger a clean shutdown and Ben shows how that can be used; here's my version

(choose-vm ) | foreach-object { (get-wmiobject -namespace "root\virtualization" -query `
               "SELECT * FROM Msvm_ShutdownComponent WHERE SystemName='$($_.name)' ").InitiateShutdown($true,"Because I said so") }

 

Comments
  • ... In which we find VMs, them choose one, start them, stop them , and connect to them. I spent more

  • Please excuse the bad pun... When I first wrote the function I posted to display the state of virtual

  • In which we see how to set the number of CPUs I started with getting MSVM Computer System objects - which

  • Arlindo just pointed me to a new ebook written by my friend Ilse Van Criekinge . Ilse won speaker idol

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment