VMware utility I built - results are wrong after one pass through

I have been writing a powershell utility to help with admin tasks. I will say right now I am a powershell novice, it is not something I have done for a long time, so my apologies on sloppy/archaic coding. I built a menu with ‘switch’ and put all the code I want to run pretty much in the menu. The only way I saw to branch out and do a loop was using functions. In testing the code I finally realized after executing each menu item once if I go back and try previous items they fail (or do not give the intended result). If I kill the ISE and start script again it works. Sometimes output gets cut off (missing the column labels), other times it seems like the code displays the members or properties of an object rather than just the title row and objects below it. Again , sorry if this is bad coding, I wouldn’t ask if I haven’t been beating myself up over this and going nuts. See below:

vCenter VM Utility

#Temp folder setup
$UtilTemp = “c:\temp” + “VMutility-” + (get-date -format “MM-dd-yyyy”)
Write-Host
write-host “–>Temp folder setup”
if (test-path $UtilTemp){
write-host “–>Temp folder exists”
}else {
write-host "–>Creating temp folder at " $UtilTemp
new-item -path $UtilTemp -itemtype directory > $null
}

#Set variables
$dt = get-date -format “MM/dd/yyyy HH:mm”

#Get username and password via popup
$UnamePW = get-credential -message “Please enter your full vCenter Username and Password”
$user = $UnamePW.username
$Creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UnamePW.username ,$UnamePW.password
$pwvsan = $Creds.GetNetworkCredential().Password

#Clear the screen
cls

#Get the vCenter Server to work with
$vServer = Read-Host -Prompt “IP of desired vCenter Server to process”
if ($vServer -as [IPaddress] -as [Bool]){
write-host
} else {mh
write-host “Your entry was not a valid IP address”
exit
}

#Connect to vCenter
Set-PowerCLIConfiguration -InvalidCertificateAction ignore -confirm:$false > $null
connect-viserver -server $vServer -user $user -password $pwvsan > $null

function get-decision {
$EntRet = Read-Host “Press ENTER to return to the menu”
if ($EntRet.length -eq “”) {
show-menu
} else {
get-decision}
}

#Function to display menu
function show-menu {
$menu=@"
1 View vCenter Hosts & statistics
2 Shut down host VM’s
3 Power on host VMs
4 Display VM Guest statistics
5 Display VM snapshots
6 Display datastore statistics
7 Change selected host to process
8 Backup Host and vSwitch configurations
Q Quit

Select a task by number or Q to quit
"@
cls
start-sleep -m 250
write-host
Write-Host “*** VM Utility Menu ***” -ForegroundColor Cyan
write-host
write-host "You have selected vCenter Server: " $vServer -ForegroundColor Green
write-host "You have selected host: " $vhost -ForegroundColor Green
write-host

$sel = Read-Host $menu

Switch ($sel) {
“1” {
Write-Host “View vCenter Hosts and statistics on” $Vserver -ForegroundColor Green
$VChostsStat = get-vmhost
$VChostsStat
start-sleep -m 250
get-decision
}
“2” {
write-host
Write-Host “Shut down host VM’s…” -ForegroundColor Green

#Process completed messages
write-host "VM’s on this host are in file: " $hostfile -ForegroundColor Green
write-host “The following VM’s will be shut down on host:” $vhost -ForegroundColor Green
write-host

#Parse VM’s in the file
$vmnfile = get-content -path $hostfile | select-object -skip 4
foreach ($vm in $vmnfile){
write-host $vm
}
$yesno = Read-Host (“Are you sure you want to power off these VM’s? (y/n)”)
if ($yesno -eq “n”) {
write-host “‘n’ was chosen, returning to the main menu”
start-sleep -S 3
show-menu
} elseif ($yesno -eq “y”) {
#power off VM’s here
write-host “y was chosen”
}
else
{
write-host “Neither ‘y’ or ‘n’ was chosen, returning to the main menu”
start-sleep -S 3
show-menu
}
}
“3” {
write-host
Write-Host “Power on host VMs…” -ForegroundColor Green
#insert your code here
get-decision
}
“4” {
write-host
Write-Host "Displaying VM Guest statistics for host: " $vhost -ForegroundColor Green
$VMstats = get-vmhost -name $vhost | get-vm | Where-Object {$.powerstate -eq ‘PoweredOn’} | Select Name,VMhost,NumCpu,MemoryGB,@{ n=“SpaceUsedGB”; e={[math]::round( $.usedspacegb, 1 )}} | ft
write-host
$vmcount = $VMstats.count
$VMstats
write-host "Total VM’s = " $vmcount

#Write VM statistics to a csv file at $UtilTemp
$statfile = ($UtilTemp + “” + “\VMstats-” + $vhost + “.csv”)
get-vmhost -name $vhost | get-vm | Select Name,VMhost,NumCpu,MemoryGB,@{ n=“SpaceUsedGB”; e={[math]::round( $.usedspacegb, 1 )}} | Export-Csv $statfile -NoTypeInformation
get-decision
}
“5” {
write-host
Write-Host "Displaying VM snapshots for host: "$vhost -ForegroundColor Green
$SNAPvms = get-vmhost -name $script:vhost | get-vm
$sshots = Get-Snapshot -vm $SNAPvms | Select VM, Description, Created, @{ n=“SizeMB”; e={[math]::round( $
.SizeMB, 2 )}} | ft
$sshots
get-decision
}
“6” {
Write-Host “View vCenter datastore statistics…” -ForegroundColor Green
$vDatastore = get-datastore
$vDatastore
start-sleep -m 250
clear-variable “vDatastore”
get-decision
}
“7” {
Write-Host "Change selected host to process: " $vhost -ForegroundColor Green
$VMChangeHost = get-vmhost
$VMChangeHost
get-vhost
start-sleep -m 250
show-menu
}
“8” {
write-host
Write-Host “Backup Host and vSwitch configurations…” -ForegroundColor Green
$gethosts = Get-VMHost | select -expandproperty name
write-host
write-host -ForegroundColor green (“Starting Host backups”)
foreach($esxhost in $gethosts)
{
write-host -foregroundcolor green ("Now backing up Host Configuration–> "+ $esxhost )
Get-VMHostFirmware -VMHost $esxhost -BackupConfiguration -DestinationPath $UtilTemp > $null
}
write-host -foregroundcolor green (“Backup of Host configs is now complete!”)
write-host

#Backup the VDS’s
$getvds = Get-VDSwitch | select -expandproperty name
write-host -foregroundcolor green (“Now backing up Virtual Distributed Switch configurations”)
foreach($VDS in $getVDS)
{
write-host -foregroundcolor green (“Now backing up Virtual Distributed Switch–> “+$VDS )
export-vdswitch -vdswitch $VDS -description “VDS Configuration Backup” -destination ($UtilTemp+””+$VDS+".zip") -Force > $NULL
}
write-host -foregroundcolor green (“Backup of VDS configs is now complete!”)
write-host
get-decision
}
“Q” {
Write-Host “Quitting!” -ForegroundColor Green
}
default {
Write-Host “I don’t understand what you want to do.” -ForegroundColor Yellow
}
}
}

#Funtion to get the host you want to work with
#Remember to make a variable global use ‘script:’
function get-vhost {
#Get the host to work with, creates $hostfile
write-host
$script:vhost = Read-Host -Prompt “IP of desired ESXi host to process”
if ($vhost -as [IPaddress] -as [Bool]){
write-host “Processing selected host…”
$script:hostfile = $UtilTemp + “” + (“Host-” + $vhost + “.txt”)
} else {
write-host “Your entry was not a valid IP address”
exit
}
#Get the VM’s on the specified host
$hostvms = get-vmhost -name $vhost | get-vm | Where-Object {$_.powerstate -eq ‘PoweredOn’}
$vmcount = $hostvms.count

#Wite host VM’s to a file
$fileheader = ("*** The total number of powered on VM’s on host " + $vhost + " = " + $vmcount + " ***")
$dt | out-file $hostfile
Add-Content $hostfile “”
$fileheader | out-file $hostfile -append
Add-Content $hostfile “”
$hostvms.name | out-file $hostfile -append

}

#Get the host to work with
get-vhost

#Display menu
show-menu

exit

#Ensure no connections are present
#disconnect-viserver -server $vserver -force -confirm:$false

#Clean up
disconnect-viserver -server $vserver -confirm:$false
clear-variable -name “user”
clear-variable -name “pwvsan”

If there is a better way to insert code let me know!FRUSTRATED!

 

Alan, welcome to Powershell.org. Please take a moment and read the very first post on top of the list of this forum: Read Me Before Posting! You’ll be Glad You Did!.

When you post code, error messages, sample data or console output format it as code, please.
In the “Text” view you can use the code tags “PRE”, in the “Visual” view you can use the format template “Preformatted”. You can go back edit your post and fix the formatting - you don’t have to create a new one.
Thanks in advance.

That’s a lot of code. I think it’s beyond the scope a forum to debug or refactor such a bit complete script. You might start with a smaller version of your script and when this smaller version works as expected you add more functions to it.

No, I get it . I know it’s a lot to ask but I have been beating my head against the wall and getting very frustrated. All the code did start out as workable little pieces and then I put the individual pieces in to the main program. I’m convinced it has to do with powershell scopes to a degree. I restart the ISE and the code works again. Running it in a command window yields the same results of not working correctly.

If I have to I’ll break it all apart again. This is more keep busy work than anything but trying to fill my time.

…Alan