Ways to tidy up my PowerShell - including making a hash of stuff
Please excuse the bad pun... When I first wrote the function I posted to display the state of virtual machines, I used a construction which has been familiar to programmers since time immemorial.
If X=1 output this If X=2 output that etc
Most modern programming languages, including PowerShell, have some kind of switch construction which is a little tidier but they're still bulky...
I had put constants for each of the states in the .PS1 file which holds all my PowerShell VM functions. But this was more as a way of having a note of them than something I was going to use in my code. I could have written the Start-vm function (in the same post) like this
$VM.RequestStateChange($Running)
and re-coded my display function as
switch ($_.EnabledState) { $Running {"Running"}
$Stopped {"Stopped"}
$Paused {"Paused"}
etc
but it still needs a line for each state. For completely separate reasons I was looking at hash tables. It takes one line to create a hash-table of return codes:
$VMState=@{"Running"=2 ; "Stopped"=3 ; "Paused"=32768 ; "Suspended"=32769 ;
"Starting"=32770 ; "Snapshotting"=32771 ; "Saving"=32773 ; "Stopping"=32774 }
So I changed the way I start and stop machines: one function does the work: expanding arrays, converting strings to computerSystem objects and actually changing the state: like this
Function Set-VMState
{Param ($VM , $state)
if ($VM -is [Array]) {$VM | ForEach-Object {Set-VMState -VM $_ -State $state} }
if ($VM -is [String]) {$VM=(Get-VM -Machinename $VM) }
if ($VM -is [System.Management.ManagementObject]) {$VM.RequestStateChange($State) }
$VM = $null
}
Using the hash Table and then I have Start, Stop and Pause functions like this:
Filter Start-VM
{Param ($VM)
$if ($vm -eq $null) ($vm=$_}
Set-VMState -VM $VM -State $vmStates.running
$VM = $Null
}
I also made a change to accept input from the pipe e.g . Get-VM "James%" | start-VM , there are two changes (a) use a FILTER instead of a FUNCTION and (b) pick up the piped input in $_ . So I've got quite a few functions where I should change this.
[Update, I'm not sure if this is the approved way of Piping, but I quickly learned that I should add the $VM=$Null at the end, other wise when 5 items are piped in function is run 5 times, using the first one each time.]
HashTables are a one-way lookup: $VMstates.running returns the value with a key of "Running" - 2 in the Start-VM filter. If I have "2" and want to get back to "Running" there isn't a built in way(that I know of). However PowerShell has a GetEnumerator which dumps out the whole hash table as Key/value pairs, which that makes it easy to get the name we want.
function Convert-VMStateID
{Param ($ID)
($vmState.GetEnumerator() | where {$_.value -eq $ID}).name
}
and using the choose-list function I showed before before , choose-VM becomes a one liner
Function Choose-VM
{choose-list -data (Get-VM) -fieldList @(@{Label="VM Name"; Expression={$_.ElementName}},
@{Label="State"; Expression={Convert-VMStateID -ID $_.EnabledState}}) }
(In principle it is a one liner ... in practice I'm going to have a -multi switch to allow single or multiple selections.
One other thing I've done in this tidying up exercise is to make sure I name my parameters in scripts. This means I really should go back to my Choose-list function and rename the "Field list" parameter to "Property" to match Powershell's built-in cmdlets (just as I have been trying to use existing Verbs and write my nouns in the singular !). Identifying parameters by position doesn't make for readable code: the following two lines are equivalent, but which would you rather see in a script (not the one you'd rather type at the command line !)
Set-VMState -VM $VM -State $vmStates.running
Set-VMState $VM $vmStates.running
Technorati Tags: Microsoft,Powershell,Windows Server 2008,Hyper-V
Comments
Anonymous
January 01, 2003
In which we see how to set the number of CPUs I started with getting MSVM Computer System objects - whichAnonymous
January 01, 2003
In an earlier post in this series (several posts ago now) I showed how I could use the Msvm_virtualSystemManagementServiceAnonymous
January 01, 2003
I've said a number of times that I think technical people are rarely secure in their own abilities; that