Taking Control of VM Sprawl (Part 12)

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

In my previous article in this series, I showed you how you could use PowerShell to create a graphical chart. Graphical charts are great for being able to spot long term trends such as virtual machine creation and deletion. My goal now is to show you how to put everything together and create a chart that reflects virtual machine creation and deletion on a month by month basis for an entire year.

Let me just say up front that this is going to be a tedious and somewhat complicated process. We already have a PowerShell script that lists and counts recent virtual machine creation and deletions. The problem is that this script doesn’t filter these events by date range. The other problem is that the data in our chart script is hard coded. We need to capture some live data from the event logs, filter it by date and by event type, and then somehow turn that data into a chart.

In preparing for this task, I am reminded of the old saying that the best way to eat an elephant is by taking one bite at a time. As such, I am going to break this process down by task rather than actually building the entire script up front and then trying to explain what it does.

So let’s get started. If you think back to Part 10 of this series, you will recall that this is our script for retrieving virtual machine creation and deletion events from the event log:


$CreateEvents = Get-WinEvent –LogName Microsoft-Windows-Hyper-V-VMMS-Admin | Where {$_.ID –eq “13002”}

$DeleteEvents = Get-WinEvent –LogName Microsoft-Windows-Hyper-V-VMMS-Admin | Where {$_.ID –eq “13003”}

Write-Host “There were ” -NoNewLine; Write-Host $CreateEvents.count -NoNewLine; Write-Host ” virtual machines created.”

Write-Host “There were ” -NoNewLine; Write-Host $DeleteEvents.count -NoNewLine; Write-Host ” virtual machines deleted.”

Write-Host ” “


#Get-WinEvent -LogName Microsoft-Windows-Hyper-V-VMMS-Admin | Where {$_.ID -EQ “13002”} | ForEach-Object -Process {

$CreateEvents | ForEach-Object -Process {

Write-Host ” “

$ObjSID = $_.UserID.Value;

# $ObjSID

$Object = New-Object System.Security.Principal.SecurityIdentifier ($ObjSID)

$ObjUser = $Object.Translate([System.Security.Principal.NTAccount])


Write-Host “By: ” -NoNewLine; Write-Host $ObjUser.value


As you can see in Figure A, the script reports the total number of virtual machines created and the total number of virtual machines deleted, and then displays the actual event log entries.

Figure A: This is what the script does right now.

Obviously, this is some helpful information, but if we are going to build a chart that shows these events on a month by month basis then we are going to have to find a way of filtering these events by date.

With that being the case, the first thing that I want to do is to show you how to look for a specific event type within a certain time range. The first thing that you need to understand about doing so is that PowerShell requires you to use a very specific format for the date and time. Suppose for instance that you wanted to examine December 30, 2015 at noon. The way that this date and time would have to be entered is:

12/30/2015 12:00:00 PM

My experience has been that if you are trying to build a PowerShell report that is based on date ranges then the easiest thing to do is to enter the dates into variables. That way it becomes relatively easy to change the date and time used by the report and the command strings aren’t quite as long as they would be if you had hard coded the dates. Let me show you what I mean.

Let’s pretend that I am interested in seeing all of the occurrences of Event ID 5973 that have occurred within the Application log between December 29, 2015 and December 30, 2015. The first thing that I would probably want to do is to commit these dates to some variables. I might for example, do something like this:

$StartDate = ‘12/29/2015 12:00:00 AM’

$EndDate = ‘12/30/2015 11:59:59 PM’

My start date starts at midnight on the 28th (technically the 29th), and my end date is set to one second before midnight on the 30th. That way, I can capture any occurrences of the events that might have occurred on either day, regardless of time. Now I can plug the $StartDate and $EndDate values into my Get-WinEvent command, along with the log name and the event ID that I am interested in. The command looks something like this:

Get-WinEvent –FilterHashTable @{LogName=”Application”;ID=5973;StartTime=$StartDate;EndTime=$EndDate}

You can see what this entire process looks like in Figure B.

Figure B: I have retrieved instances of Event 5973 occurring in the Application log within a specific date range.

We could easily use the technique that I just showed you to adapt our script to look at a specific date range. For instance, we might want to look at virtual machine creation for this week. If the ultimate goal is to create a report that details virtual machine creation and deletion for the last year however, then this approach is inadequate by itself. We need to look at more than one date range.

There are countless ways to approach this challenge. If this were a production environment then the best method would probably be to create a script that counts backward from the current date in order to examine key date ranges from the last year. I strongly considered writing such a script, but ultimately decided against it because I didn’t want to have to introduce any more complexity than I am already adding to the script.

My approach is going to be to hard code several date ranges. It isn’t the most elegant way of doing things, and it results in more lines of code being written, but I think that this method will be the easiest to understand. So with that said, I am going to be creating a whopping 48 variables! Yes, you read that correctly. We need 48 new variables. Why so many? Well, our script is going to be examining 12 months’ worth of event logs and we are going to need four variables for each month.

The first variable will be the month start date. The second variable will be the month end date. The third variable will store the number of virtual machines created in that month, and the fourth variable will store the number of virtual machines deleted in that month. That’s a lot of variables for sure, but in the end I think that the code will be a lot easier to follow than it would be if I had used some sort of cryptic calculation to extract event log entries for various date ranges.


My plan for next time is to convert my existing script to be date specific. I am going to break down virtual machine creation and deletion events by month and then plot those events on a chart. I also plan to extend the script so that we can examine events across multiple servers. By doing so, we can get a big picture of the virtual machine creation and deletion trends on an organization wide basis.

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

About The Author

Leave a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top