Taking Control of VM Sprawl (Part 18)

by [Published on 14 Sept. 2016 / Last Updated on 14 Sept. 2016]

So far in this article series, we have built a really long PowerShell script that compiles a list of the number of virtual machines that were created and deleted over the course of a year. In this article, I want to wrap up the series by exporting all of the data to a report, and by displaying the data on a chart. This was a huge job, and I wrote a lot of new code, but the new code is pretty straightforward.

If you would like to read the other parts in this article series please go to:

The most significant addition to the code was a new function named Display-Output. You can see the function here:

Function Display-Output($Msg){
# Function to display output on the screen and write it to a file.
 
Write-Host $Msg
$Msg | Add-Content C:\Data\VMReport.txt
}

The reason why I created this function is because the Write-Host cmdlet cannot dump output to a file. Data is only written to the screen. As such, I rewrote every line of code within the script that was intended to display text on the screen. Now, instead of displaying that text by using write-host, I am adding the text to a variable named $Msg. I then pass that variable to the $Msg function. The function uses Write-Host to display the variable’s contents on the screen, but also writes the text to a file named C:\Data\VMReport.txt.

You will notice that the function writes the data to the file by using the Add-Content cmdlet rather than the Out-File cmdlet. The Out-File cmdlet overwrites a text file, whereas Add-Content appends an existing file.

I also had to create a block of code to create the report file. Here is what that block of code looks like:

# Create Report File
 
Remove-Item C:\Data\VMReport.txt -ErrorAction SilentlyContinue
$Msg = "Virtual Machine Report"
Write-Host $Msg
$Msg | Out-File C:\Data\VMReport.txt
Display-Output $Msg
$Msg=" "
Display-Output $Msg
$Msg="--------------------------------------------------"
Display-Output $Msg
$Msg="   Host Level VM Creation and Deletion Events"
Display-Output $Msg
$Msg="--------------------------------------------------"
Display-Output $Msg
$Msg=" "
Display-Output $Msg

The first thing that this block of code does is to delete the C:\Data\VMReport.txt file if it already exists. I used the -ErrorAction SilentlyContinue parameter to prevent any error messages from being displayed in the event that the text file does not yet exist.

The next three lines of code are significant because they create the report file. I start out by adding the words Virtual Machine Report to the $Msg variable. However, I do not call the Display-Output function. Instead, I use Write-Host to display the text on screen, and I use the Out-File cmdlet to write the text to the report file. Beyond this point however, any text that needs to be displayed is added to the $Msg variable and sent to the Display-Output function.

Another thing that I did was to create a section of code that calculates the total number of virtual machine creations and deletions across all servers. This block of code not only displays the grand totals, but it also uses a variable named $Trend to calculate the difference between the number of virtual machine creations and virtual machine deletions. By doing so, the script is able to tell you whether you have more or less virtual machines than existed a year ago. Here is what the code looks like:

# Calculate and Display Total Events
 
$TotalCreate = $TotalJanCreateEvents + $TotalFebCreateEvents + $TotalMarCreateEvents + $TotalAprCreateEvents + $TotalMayCreateEvents + $TotalJunCreateEvents + $TotalJulCreateEvents + $TotalAugCreateEvents + $TotalSepCreateEvents + $TotalOctCreateEvents + $TotalNovCreateEvents + $TotalDecCreateEvents
$TotalDelete = $TotalJanDeleteEvents + $TotalFebDeleteEvents + $TotalMarDeleteEvents + $TotalAprDeleteEvents + $TotalMayDeleteEvents + $TotalJunDeleteEvents + $TotalJulDeleteEvents + $TotalAugDeleteEvents + $TotalSepDeleteEvents + $TotalOctDeleteEvents + $TotalNovDeleteEvents + $TotalDecDeleteEvents
 
$Msg=" "
Display-Output $Msg
$Msg="-------------------------------------------"
Display-Output $Msg
$Msg="              Grand Totals"
Display-Output $Msg
$Msg="-------------------------------------------"
Display-Output $Msg
$Msg=" "
Display-Output $Msg
$Msg="Total virtual machine creations in the last year: " + $TotalCreate
Display-Output $Msg
$Msg="Total virtual machine deletions in the last year: " + $TotalDelete
Display-Output $Msg
$Msg=" "
Display-Output $Msg
 
If ($TotalCreate -GT $TotalDelete){
                $Trend = $TotalCreate - $TotalDelete
                $Msg="There are " + $Trend + " more VMs in your organization now than there were a year ago."
                Display-Output $Msg
                }
 
If ($TotalCreate -LT $TotalDelete){
                $Trend = $TotalDelete - $TotalCreate
                $Msg="There are " + $Trend + " fewer VMs in your organization now than there were a year ago."
                Display-Output $Msg
                }
 
$Msg=" "
Display-Output $Msg

Finally, I added some code that was designed to plot all of the data onto a chart. This code is almost identical to what I showed you in one of the earlier articles in this series. The biggest change has been to the $DataSource1 and $DataSource2 variable assignments. You can see those two lines of code below:

$DataSource1 = [ordered]@{July=$TotalJulCreateEvents; August=$TotalAugCreateEvents; September=$TotalSepCreateEvents; October=$TotalOctCreateEvents; November=$TotalNovCreateEvents; December=$TotalDecCreateEvents; January=$TotalJanCreateEvents; February=$TotalFebCreateEvents; March=$TotalMarCreateEvents; April=$TotalAprCreateEvents; May=$TotalMayCreateEvents; June=$TotalJunCreateEvents}
 
$DataSource2 = [ordered]@{July=$TotalJulDeleteEvents; August=$TotalAugDeleteEvents; September=$TotalSepDeleteEvents; October=$TotalOctDeleteEvents; November=$TotalNovDeleteEvents; December=$TotalDecDeleteEvents; January=$TotalJanDeleteEvents; February=$TotalFebDeleteEvents; March=$TotalMarDeleteEvents; April=$TotalAprDeleteEvents; May=$TotalMayDeleteEvents; June=$TotalJunDeleteEvents}

These two lines of code set up hash tables containing the month names, and the number of virtual machines that were created or deleted during those months. While this sounds simple enough (and it is), there are two things that I need to point out.

First, notice that the word Ordered appears just before the hash table. The reason why this is necessary, is because the information will be plotted on the chart in a random order unless we tell PowerShell that we want the data to be ordered. Since we are creating a line chart, we want the data to reflect a chronological order, and therefore need to keep the data in order.

The other thing that I want to point out is that the data begins with July. The reason for this is because I am writing this article in June of 2016. Therefore, my date range begins in July of 2015 and continues on through June of 2016. July appears at the beginning of the hash table, because the July 2015 data is the oldest.

Most of the other changes that I have made to the code exist only to clean up the output and make it more presentable. So with that said, here is the final code in its entirety:

Function Display-Output($Msg){
# Function to display output on the screen and write it to a file.
 
Write-Host $Msg
$Msg | Add-Content C:\Data\VMReport.txt
}
 
 
Function Get-MyData($Server){
#Function to get VM log data information
 
 
$MySession = New-PSSession -ComputerName $Server
 
 
#Initialize Variables
 
Invoke-Command -Session $MySession -ScriptBlock {
 
                #January
 
                $NumJanCreateEvents = ‘0’
                $JanCreateEvents = ''
                $NumJanDeleteEvents = ‘0’
                $JanDeleteEvents = ''
                $JanStartDate = ‘01/01/2016 12:00:00 AM’
                $JanEndDate = ‘01/30/2016 11:59:59 PM’
 
                #February
 
                $NumFebCreateEvents = ‘0’
                $FebCreateEvents = ''
                $NumFebDeleteEvents = ‘0’
                $FebDeleteEvents = ''
                $FebStartDate = ‘02/01/2016 12:00:00 AM’
                $FebEndDate = ‘02/29/2016 11:59:59 PM’
 
                #March
 
                $NumMarCreateEvents = ‘0’
                $MarCreateEvents = ''
                $NumMarDeleteEvents = ‘0’
                $MarDeleteEvents = ''
                $MarStartDate = ‘03/01/2016 12:00:00 AM’
                $MarEndDate = ‘03/30/2016 11:59:59 PM’
 
                #April
 
                $NumAprCreateEvents = ‘0’
                $AprCreateEvents = ''
                $NumAprDeleteEvents = ‘0’
                $AprDeleteEvents = ''
                $AprStartDate = ‘04/01/2016 12:00:00 AM’
                $AprEndDate = ‘04/30/2016 11:59:59 PM’
 
                #May
 
                $NumMayCreateEvents = ‘0’
                $MayCreateEvents = ''
                $NumMayDeleteEvents = ‘0’
                $MayDeleteEvents = ''
                $MayStartDate = ‘05/01/2016 12:00:00 AM’
                $MayEndDate = ‘05/31/2016 11:59:59 PM’
 
                #June
 
                $NumJunCreateEvents = ‘0’
                $JunCreateEvents = ''
                $NumJunDeleteEvents = ‘0’
                $JunDeleteEvents = ''
                $JunStartDate = ‘06/01/2016 12:00:00 AM’
                $JunEndDate = ‘06/30/2016 11:59:59 PM’
 
                #July
 
                $NumJulCreateEvents = ‘0’
                $JulCreateEvents = ''
                $NumJulDeleteEvents = ‘0’
                $JulDeleteEvents = ''
                $JulStartDate = ‘07/01/2015 12:00:00 AM’
                $JulEndDate = ‘07/31/2015 11:59:59 PM’
 
                #August
 
                $NumAugCreateEvents = ‘0’
                $AugCreateEvents = ''
                $NumAugDeleteEvents = ‘0’
                $AugDeleteEvents = ''
                $AugStartDate = ‘08/01/2015 12:00:00 AM’
                $AugEndDate = ‘08/31/2015 11:59:59 PM’
 
                #September
 
                $NumSepCreateEvents = ‘0’
                $SepCreateEvents = ''
                $NumSepDeleteEvents = ‘0’
                $SepDeleteEvents = ''
                $SepStartDate = ‘09/01/2015 12:00:00 AM’
                $SepEndDate = ‘09/30/2015 11:59:59 PM’
 
                #October
 
                $NumOctCreateEvents = ‘0’
                $OctCreateEvents = ''
                $NumOctDeleteEvents = ‘0’
                $OctDeleteEvents = ''
                $OctStartDate = ‘10/01/2015 12:00:00 AM’
                $OctEndDate = ‘10/31/2015 11:59:59 PM’
 
                #November
 
                $NumNovCreateEvents = ‘0’
                $NovCreateEvents = ''
                $NumNovDeleteEvents = ‘0’
                $NovDeleteEvents = ''
                $NovStartDate = ‘11/01/2015 12:00:00 AM’
                $NovEndDate = ‘11/30/2015 11:59:59 PM’
 
                #December
 
                $NumDecCreateEvents = ‘0’
                $DecCreateEvents = ''
                $NumDecDeleteEvents = ‘0’
                $DecDeleteEvents = ''
                $DecStartDate = ‘12/01/2015 12:00:00 AM’
                $DecEndDate = ‘12/31/2015 11:59:59 PM’
               
                }
 
 
 
 
# January 2016
 
$JanCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$JanStartDate;EndTime=$JanEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumJanCreateEvents = $JanCreateEvents.count
$JanDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$JanStartDate;EndTime=$JanEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumJanDeleteEvents = $JanDeleteEvents.count
 
 
# February 2016
 
 
$FebCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$FebStartDate;EndTime=$FebEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumFebCreateEvents = $FebCreateEvents.count
$FebDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$FebStartDate;EndTime=$FebEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumFebDeleteEvents = $FebDeleteEvents.count
 
 
# March 2016
 
 
$MarCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$MarStartDate;EndTime=$MarEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumMarCreateEvents = $MarCreateEvents.count
$MarDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$MarStartDate;EndTime=$MarEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumMarDeleteEvents = $MarDeleteEvents.count
 
# April 2016
 
 
$AprCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$AprStartDate;EndTime=$AprEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumAprCreateEvents = $AprCreateEvents.count
$AprDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$AprStartDate;EndTime=$AprEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumAprDeleteEvents = $AprDeleteEvents.count
 
# May 2016
 
 
$MayCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$MayStartDate;EndTime=$MayEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumMayCreateEvents = $MayCreateEvents.count
$MayDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$MayStartDate;EndTime=$MayEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumMayDeleteEvents = $MayDeleteEvents.count
 
# June 2015
 
 
$JunCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$JunStartDate;EndTime=$JunEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumJunCreateEvents = $JunCreateEvents.count
$JunDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$JunStartDate;EndTime=$JunEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumJunDeleteEvents = $JunDeleteEvents.count
 
# July 2015
 
 
$JulCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$JulStartDate;EndTime=$JulEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumJulCreateEvents = $JulCreateEvents.count
$JulDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$JulStartDate;EndTime=$JulEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumJulDeleteEvents = $JulDeleteEvents.count
 
# August 2015
 
 
$AugCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$AugStartDate;EndTime=$AugEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumAugCreateEvents = $AugCreateEvents.count
$AugDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$AugStartDate;EndTime=$AugEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumAugDeleteEvents = $AugDeleteEvents.count
 
# September 2015
 
 
$SepCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$SepStartDate;EndTime=$SepEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumSepCreateEvents = $SepCreateEvents.count
$SepDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$SepStartDate;EndTime=$SepEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumSepDeleteEvents = $SepDeleteEvents.count
 
# October 2015
 
 
$OctCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$OctStartDate;EndTime=$OctEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumOctCreateEvents = $OctCreateEvents.count
$OctDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$OctStartDate;EndTime=$OctEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumOctDeleteEvents = $OctDeleteEvents.count
 
# November 2015
 
 
$NovCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$NovStartDate;EndTime=$NovEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumNovCreateEvents = $NovCreateEvents.count
$NovDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$NovStartDate;EndTime=$NovEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumNovDeleteEvents = $NovDeleteEvents.count
 
# December 2015
 
 
$DecCreateEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13002;StartTime=$DecStartDate;EndTime=$DecEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumDecCreateEvents = $DecCreateEvents.count
$DecDeleteEvents = Invoke-Command -Session $MySession -ScriptBlock {Get-WinEvent –FilterHashTable @{LogName=”Microsoft-Windows-Hyper-V-VMMS-Admin”;ID=13003;StartTime=$DecStartDate;EndTime=$DecEndDate} -ErrorAction 'SilentlyContinue'}
$Global:NumDecDeleteEvents = $DecDeleteEvents.count
 
 
 
# Monthly Output
 
$Msg=" "
Display-Output $Msg
 
$Msg="Server: " + $Server
Display-Output $Msg
 
$Msg="--------------------------------"
Display-Output $Msg
 
$Msg="January Create Events: " + $NumJanCreateEvents
Display-Output $Msg
$Msg="January Delete Events: " + $NumJanDeleteEvents
Display-Output $Msg
 
$Msg="February Create Events: " + $NumFebCreateEvents
Display-Output $Msg
$Msg="February Delete Events: " + $NumFebDeleteEvents
Display-Output $Msg
 
$Msg="March Create Events: " + $NumMarCreateEvents
Display-Output $Msg
$Msg="March Delete Events: " + $NumMarDeleteEvents
Display-Output $Msg
 
$Msg="April Create Events: " + $NumAprCreateEvents
Display-Output $Msg
$Msg="April Delete Events: " + $NumAprDeleteEvents
Display-Output $Msg
 
$Msg="May Create Events: " + $NumMayCreateEvents
Display-Output $Msg
$Msg="May Delete Events: " + $NumMayDeleteEvents
Display-Output $Msg
 
$Msg="June Create Events: " + $NumJunCreateEvents
Display-Output $Msg
$Msg="June Delete Events: " + $NumJunDeleteEvents
Display-Output $Msg
 
$Msg="July Create Events: " + $NumJulCreateEvents
Display-Output $Msg
$Msg="July Delete Events: " + $NumJulDeleteEvents
Display-Output $Msg
 
$Msg="August Create Events: " + $NumAugCreateEvents
Display-Output $Msg
$Msg="August Delete Events: " + $NumAugDeleteEvents
Display-Output $Msg
 
$Msg="September Create Events: " + $NumSepCreateEvents
Display-Output $Msg
$Msg="September Delete Events: " + $NumSepDeleteEvents
Display-Output $Msg
 
$Msg="October Create Events: " + $NumOctCreateEvents
Display-Output $Msg
$Msg="October Delete Events: " + $NumOctDeleteEvents
Display-Output $Msg
 
$Msg="November Create Events: " + $NumNovCreateEvents
Display-Output $Msg
$Msg="November Delete Events: " + $NumNovDeleteEvents
Display-Output $Msg
 
$Msg="December Create Events: " + $NumDecCreateEvents
Display-Output $Msg
$Msg="December Delete Events: " + $NumDecDeleteEvents
Display-Output $Msg
 
$Msg=" "
Display-Output $Msg
}
 
 
 
 
 
 
#Script Body
 
#Initialize Variables
$TotalJanCreateEvents = '0'
$TotalJanDeleteEvents = '0'
$TotalFebCreateEvents = '0'
$TotalFebDeleteEvents = '0'
$TotalMarCreateEvents = '0'
$TotalMarDeleteEvents = '0'
$TotalAprCreateEvents = '0'
$TotalAprDeleteEvents = '0'
$TotalMayCreateEvents = '0'
$TotalMayDeleteEvents = '0'
$TotalJunCreateEvents = '0'
$TotalJunDeleteEvents = '0'
$TotalJulCreateEvents = '0'
$TotalJulDeleteEvents = '0'
$TotalAugCreateEvents = '0'
$TotalAugDeleteEvents = '0'
$TotalSepCreateEvents = '0'
$TotalSepDeleteEvents = '0'
$TotalOctCreateEvents = '0'
$TotalOctDeleteEvents = '0'
$TotalNovCreateEvents = '0'
$TotalNovDeleteEvents = '0'
$TotalDecCreateEvents = '0'
$TotalDecDeleteEvents = '0'
 
 
 
# Create Report File
 
CLS
Remove-Item C:\Data\VMReport.txt -ErrorAction SilentlyContinue
$Msg = "Virtual Machine Report"
Write-Host $Msg
$Msg | Out-File C:\Data\VMReport.txt
Display-Output $Msg
$Msg=" "
Display-Output $Msg
$Msg="--------------------------------------------------"
Display-Output $Msg
$Msg="   Host Level VM Creation and Deletion Events"
Display-Output $Msg
$Msg="--------------------------------------------------"
Display-Output $Msg
$Msg=" "
Display-Output $Msg
 
 
# Collect VM Information
 
$Servers = @("Hyper-V-1", "Hyper-V-2", "Hyper-V-3", "Hyper-V-4", "Prod1", "Prod2")
                ForEach ($Server in $Servers) {
 
                                $ServerName = $Server
                                Get-MyData $ServerName
                                $TotalJanCreateEvents = [int]$TotalJanCreateEvents + [int]$NumJanCreateEvents
                                $TotalJanDeleteEvents = [int]$TotalJanDeleteEvents + [int]$NumJanDeleteEvents
                                $TotalFebCreateEvents = [int]$TotalFebCreateEvents + [int]$NumFebCreateEvents
                                $TotalFebDeleteEvents = [int]$TotalFebDeleteEvents + [int]$NumFebDeleteEvents
                                $TotalMarCreateEvents = [int]$TotalMarCreateEvents + [int]$NumMarCreateEvents
                                $TotalMarDeleteEvents = [int]$TotalMarDeleteEvents + [int]$NumMarDeleteEvents
                                $TotalAprCreateEvents = [int]$TotalAprCreateEvents + [int]$NumAprCreateEvents
                                $TotalAprDeleteEvents = [int]$TotalAprDeleteEvents + [int]$NumAprDeleteEvents
                                $TotalMayCreateEvents = [int]$TotalMayCreateEvents + [int]$NumMayCreateEvents
                                $TotalMayDeleteEvents = [int]$TotalMayDeleteEvents + [int]$NumMayDeleteEvents
                                $TotalJunCreateEvents = [int]$TotalJunCreateEvents + [int]$NumJunCreateEvents
                                $TotalJunDeleteEvents = [int]$TotalJunDeleteEvents + [int]$NumJunDeleteEvents
                                $TotalJulCreateEvents = [int]$TotalJulCreateEvents + [int]$NumJulCreateEvents
                                $TotalJulDeleteEvents = [int]$TotalJulDeleteEvents + [int]$NumJulDeleteEvents
                                $TotalAugCreateEvents = [int]$TotalAugCreateEvents + [int]$NumAugCreateEvents
                                $TotalAugDeleteEvents = [int]$TotalAugDeleteEvents + [int]$NumAugDeleteEvents
                                $TotalSepCreateEvents = [int]$TotalSepCreateEvents + [int]$NumSepCreateEvents
                                $TotalSepDeleteEvents = [int]$TotalSepDeleteEvents + [int]$NumSepDeleteEvents
                                $TotalOctCreateEvents = [int]$TotalOctCreateEvents + [int]$NumOctCreateEvents
                                $TotalOctDeleteEvents = [int]$TotalOctDeleteEvents + [int]$NumOctDeleteEvents
                                $TotalNovCreateEvents = [int]$TotalNovCreateEvents + [int]$NumNovCreateEvents
                                $TotalNovDeleteEvents = [int]$TotalNovDeleteEvents + [int]$NumNovDeleteEvents
                                $TotalDecCreateEvents = [int]$TotalDecCreateEvents + [int]$NumDecCreateEvents
                                $TotalDecDeleteEvents = [int]$TotalDecDeleteEvents + [int]$NumDecDeleteEvents
                                }
 
 
 
 
 
 
 
$Msg=" "
Display-Output $Msg
$Msg="-------------------------------------------------"
Display-Output $Msg
$Msg="       Total VM Creation and Deletion Events"
Display-Output $Msg
$Msg="-------------------------------------------------"
Display-Output $Msg
$Msg=" "
Display-Output $Msg
$Msg="Total January Create Events: " + $TotalJanCreateEvents
Display-Output $Msg
$Msg="Total January Delete Events: " + $TotalJanDeleteEvents
Display-Output $Msg
$Msg="Total February Create Events: " + $TotalFebCreateEvents
Display-Output $Msg
$Msg="Total February Delete Events: " + $TotalFebDeleteEvents
Display-Output $Msg
$Msg="Total March Create Events: " + $TotalMarCreateEvents
Display-Output $Msg
$Msg="Total March Delete Events: " + $TotalMarDeleteEvents
Display-Output $Msg
$Msg="Total April Create Events: " + $TotalAprCreateEvents
Display-Output $Msg
$Msg="Total April Delete Events: " + $TotalAprDeleteEvents
Display-Output $Msg
$Msg="Total May Create Events: " + $TotalMayCreateEvents
Display-Output $Msg
$Msg="Total May Delete Events: " + $TotalMayDeleteEvents
Display-Output $Msg
$Msg="Total June Create Events: " + $TotalJunCreateEvents
Display-Output $Msg
$Msg="Total June Delete Events: " + $TotalJunDeleteEvents
Display-Output $Msg
$Msg="Total July Create Events: " + $TotalJulCreateEvents
Display-Output $Msg
$Msg="Total July Delete Events: " + $TotalJulDeleteEvents
Display-Output $Msg
$Msg="Total August Create Events: " + $TotalAugCreateEvents
Display-Output $Msg
$Msg="Total August Delete Events: " + $TotalAugDeleteEvents
Display-Output $Msg
$Msg="Total September Create Events: " + $TotalSepCreateEvents
Display-Output $Msg
$Msg="Total September Delete Events: " + $TotalSepDeleteEvents
Display-Output $Msg
$Msg="Total October Create Events: " + $TotalOctCreateEvents
Display-Output $Msg
$Msg="Total October Delete Events: " + $TotalOctDeleteEvents
Display-Output $Msg
$Msg="Total November Create Events: " + $TotalNovCreateEvents
Display-Output $Msg
$Msg="Total November Delete Events: " + $TotalNovDeleteEvents
Display-Output $Msg
$Msg="Total December Create Events: " + $TotalDecCreateEvents
Display-Output $Msg
$Msg="Total December Delete Events: " + $TotalDecDeleteEvents
Display-Output $Msg
 
 
 
 
# Calculate and Display Total Events
 
 
 
$TotalCreate = $TotalJanCreateEvents + $TotalFebCreateEvents + $TotalMarCreateEvents + $TotalAprCreateEvents + $TotalMayCreateEvents + $TotalJunCreateEvents + $TotalJulCreateEvents + $TotalAugCreateEvents + $TotalSepCreateEvents + $TotalOctCreateEvents + $TotalNovCreateEvents + $TotalDecCreateEvents
$TotalDelete = $TotalJanDeleteEvents + $TotalFebDeleteEvents + $TotalMarDeleteEvents + $TotalAprDeleteEvents + $TotalMayDeleteEvents + $TotalJunDeleteEvents + $TotalJulDeleteEvents + $TotalAugDeleteEvents + $TotalSepDeleteEvents + $TotalOctDeleteEvents + $TotalNovDeleteEvents + $TotalDecDeleteEvents
 
$Msg=" "
Display-Output $Msg
$Msg="-------------------------------------------"
Display-Output $Msg
$Msg="              Grand Totals"
Display-Output $Msg
$Msg="-------------------------------------------"
Display-Output $Msg
$Msg=" "
Display-Output $Msg
$Msg="Total virtual machine creations in the last year: " + $TotalCreate
Display-Output $Msg
$Msg="Total virtual machine deletions in the last year: " + $TotalDelete
Display-Output $Msg
$Msg=" "
Display-Output $Msg
 
If ($TotalCreate -GT $TotalDelete){
                $Trend = $TotalCreate - $TotalDelete
                $Msg="There are " + $Trend + " more VMs in your organization now than there were a year ago."
                Display-Output $Msg
                }
 
If ($TotalCreate -LT $TotalDelete){
                $Trend = $TotalDelete - $TotalCreate
                $Msg="There are " + $Trend + " fewer VMs in your organization now than there were a year ago."
                Display-Output $Msg
                }
 
$Msg=" "
Display-Output $Msg
 
 
 
# Create Chart
 
$DataSource1 = [ordered]@{July=$TotalJulCreateEvents; August=$TotalAugCreateEvents; September=$TotalSepCreateEvents; October=$TotalOctCreateEvents; November=$TotalNovCreateEvents; December=$TotalDecCreateEvents; January=$TotalJanCreateEvents; February=$TotalFebCreateEvents; March=$TotalMarCreateEvents; April=$TotalAprCreateEvents; May=$TotalMayCreateEvents; June=$TotalJunCreateEvents}
$DataSource2 = [ordered]@{July=$TotalJulDeleteEvents; August=$TotalAugDeleteEvents; September=$TotalSepDeleteEvents; October=$TotalOctDeleteEvents; November=$TotalNovDeleteEvents; December=$TotalDecDeleteEvents; January=$TotalJanDeleteEvents; February=$TotalFebDeleteEvents; March=$TotalMarDeleteEvents; April=$TotalAprDeleteEvents; May=$TotalMayDeleteEvents; June=$TotalJunDeleteEvents}
 
 
 
 
 
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")
 
 
 
$scriptpath = Split-Path -parent $MyInvocation.MyCommand.Definition
 
# chart object
   $chart1 = New-object System.Windows.Forms.DataVisualization.Charting.Chart
   $chart1.Width = 1000
   $chart1.Height = 1000
   $chart1.BackColor = [System.Drawing.Color]::White
 
# title
   [void]$chart1.Titles.Add("Virtual Machines Created and Deleted")
   $chart1.Titles[0].Font = "Arial,13pt"
   $chart1.Titles[0].Alignment = "topLeft"
 
# chart area
   $chartarea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
   $chartarea.Name = "ChartArea1"
   $chartarea.AxisY.Title = "Virtual Machines"
   $chartarea.AxisX.Title = "Time"
   $chartarea.AxisY.Interval = 1
   $chartarea.AxisX.Interval = 1
   $chart1.ChartAreas.Add($chartarea)
 
# legend
   $legend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend
   $legend.name = "Legend1"
   $chart1.Legends.Add($legend)
 
 
# Virtual Machines Created data series
   [void]$chart1.Series.Add("VM_Created")
   $chart1.Series["VM_Created"].ChartType = "Line"
   $chart1.Series["VM_Created"].BorderWidth  = 3
   $chart1.Series["VM_Created"].IsVisibleInLegend = $true
   $chart1.Series["VM_Created"].chartarea = "ChartArea1"
   $chart1.Series["VM_Created"].Legend = "Legend1"
   $chart1.Series["VM_Created"].color = "Green"
   $Chart1.Series["VM_Created"].Points.DataBindXY($DataSource1.keys, $DataSource1.Values)
 
# Virtual machines deleted data series
   [void]$chart1.Series.Add("VM_Deleted")
   $chart1.Series["VM_Deleted"].ChartType = "Line"
   $chart1.Series["VM_Deleted"].IsVisibleInLegend = $true
   $chart1.Series["VM_Deleted"].BorderWidth  = 3
   $chart1.Series["VM_Deleted"].chartarea = "ChartArea1"
   $chart1.Series["VM_Deleted"].Legend = "Legend1"
   $chart1.Series["VM_Deleted"].color = "Blue"
   $Chart1.Series["VM_Deleted"].Points.DataBindXY($DataSource2.keys, $DataSource2.Values)
 
# display the chart on a form
 
$Form = New-Object Windows.Forms.Form
$Form.Text = "VM Sprawl"
$Form.Width = 1000
$Form.Height = 1000
$Form.controls.add($Chart1)
$Form.Add_Shown({$Form.Activate()})
$Form.ShowDialog()
 
# Save Chart
$chart1.SaveImage("C:\Data\Chart.png","png")

So, what happens when I run the script? Well, the output is written to the screen as it was before. You can see a partial output shown below.

Image
This is what you see on screen when the script runs.

PowerShell also displays a graphical view of the virtual machine creation and deletion events in a separate window. You can see what this looks like in the image below.

Image
PowerShell also creates a chart of the data.

Finally, PowerShell creates two files. The very last line of code in the script saves the chart to a .PNG file. The file is called C:\Data\Chart.png. The report file is saved as C:\Data\VMReport.txt. You can see the full text of the report from my servers below:

Virtual Machine Report
Virtual Machine Report
 
--------------------------------------------------
   Host Level VM Creation and Deletion Events
--------------------------------------------------
 
 
Server: Hyper-V-1
--------------------------------
January Create Events: 0
January Delete Events: 0
February Create Events:
February Delete Events: 2
March Create Events:
March Delete Events:
April Create Events: 0
April Delete Events: 0
May Create Events: 0
May Delete Events: 0
June Create Events: 2
June Delete Events: 0
July Create Events: 0
July Delete Events: 0
August Create Events: 0
August Delete Events: 0
September Create Events: 0
September Delete Events: 0
October Create Events: 0
October Delete Events: 0
November Create Events: 5
November Delete Events: 0
December Create Events: 0
December Delete Events: 0
 
 
Server: Hyper-V-2
--------------------------------
January Create Events: 0
January Delete Events: 0
February Create Events: 4
February Delete Events: 5
March Create Events: 2
March Delete Events:
April Create Events: 0
April Delete Events: 0
May Create Events: 0
May Delete Events: 0
June Create Events: 0
June Delete Events: 0
July Create Events: 0
July Delete Events: 0
August Create Events: 0
August Delete Events: 0
September Create Events: 0
September Delete Events: 0
October Create Events: 0
October Delete Events: 0
November Create Events: 3
November Delete Events: 3
December Create Events: 0
December Delete Events: 0
 
 
Server: Hyper-V-3
--------------------------------
January Create Events: 0
January Delete Events: 0
February Create Events:
February Delete Events:
March Create Events: 2
March Delete Events:
April Create Events: 0
April Delete Events: 0
May Create Events: 0
May Delete Events: 0
June Create Events: 2
June Delete Events:
July Create Events: 0
July Delete Events: 0
August Create Events: 0
August Delete Events: 0
September Create Events: 0
September Delete Events: 0
October Create Events: 0
October Delete Events: 0
November Create Events: 0
November Delete Events: 0
December Create Events: 0
December Delete Events: 0
 
 
Server: Hyper-V-4
--------------------------------
January Create Events: 36
January Delete Events: 31
February Create Events: 6
February Delete Events: 0
March Create Events: 3
March Delete Events: 5
April Create Events:
April Delete Events: 0
May Create Events:
May Delete Events: 0
June Create Events: 3
June Delete Events:
July Create Events: 0
July Delete Events: 0
August Create Events: 0
August Delete Events: 0
September Create Events: 0
September Delete Events: 0
October Create Events: 0
October Delete Events: 0
November Create Events: 0
November Delete Events: 0
December Create Events: 0
December Delete Events: 0
 
 
Server: Prod1
--------------------------------
January Create Events: 0
January Delete Events: 0
February Create Events: 0
February Delete Events: 0
March Create Events: 0
March Delete Events: 0
April Create Events: 0
April Delete Events: 0
May Create Events: 0
May Delete Events: 2
June Create Events: 0
June Delete Events: 0
July Create Events: 0
July Delete Events: 0
August Create Events: 0
August Delete Events: 0
September Create Events: 0
September Delete Events: 0
October Create Events: 0
October Delete Events: 0
November Create Events:
November Delete Events: 3
December Create Events: 0
December Delete Events: 0
 
 
Server: Prod2
--------------------------------
January Create Events: 0
January Delete Events: 0
February Create Events: 0
February Delete Events: 0
March Create Events: 0
March Delete Events: 0
April Create Events: 0
April Delete Events: 0
May Create Events: 0
May Delete Events:
June Create Events: 0
June Delete Events: 0
July Create Events: 0
July Delete Events: 0
August Create Events: 0
August Delete Events: 0
September Create Events: 0
September Delete Events: 0
October Create Events: 0
October Delete Events: 0
November Create Events: 0
November Delete Events: 0
December Create Events: 0
December Delete Events: 0
 
 
-------------------------------------------------
       Total VM Creation and Deletion Events
-------------------------------------------------
 
Total January Create Events: 36
Total January Delete Events: 31
Total February Create Events: 10
Total February Delete Events: 7
Total March Create Events: 7
Total March Delete Events: 5
Total April Create Events: 0
Total April Delete Events: 0
Total May Create Events: 0
Total May Delete Events: 2
Total June Create Events: 7
Total June Delete Events: 0
Total July Create Events: 0
Total July Delete Events: 0
Total August Create Events: 0
Total August Delete Events: 0
Total September Create Events: 0
Total September Delete Events: 0
Total October Create Events: 0
Total October Delete Events: 0
Total November Create Events: 8
Total November Delete Events: 6
Total December Create Events: 0
Total December Delete Events: 0
 
-------------------------------------------
              Grand Totals
-------------------------------------------
 
Total virtual machine creations in the last year: 68
Total virtual machine deletions in the last year: 51

There are 17 more VMs in your organization now than there were a year ago.

Wrapping it up...

This has been one of the longest article series that I have ever written, and a lot of work has gone into creating the script. My sincere hope is that you not only find the script to be useful, but that you will also build onto it in a way that allows it to display even more information that is relevant to your own organization’s needs.

If you would like to read the other parts in this article series please go to:

See Also


The Author — Brien M. Posey

Brien M. Posey avatar

Brien Posey is an MCSE and has won the Microsoft MVP award for the last few years. Brien has written well over 4,000 technical articles and written or contributed material to 27 books.