Taking Control of VM Sprawl (Part 6)

by [Published on 28 July 2015 / Last Updated on 28 July 2015]

This article continues the discussion of VM sprawl control by looking at some techniques for extracting event log information using PowerShell.

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

In the previous article in this series, I began showing you that it is possible to access the Windows event logs using nothing but native PowerShell. The techniques that I showed you in that article were more of a proof of concept than something that you would actually use if you wanted to use PowerShell to track VM creation. In this article, I want to continue the discussion by showing you how to access individual events and event details and how to examine those items across multiple Hyper-V servers.

For the purposes of this article, I want to forget all about Hyper-V and show you some general techniques for processing event logs. Once I have covered the fundamentals I will turn my attention back toward Hyper-V.

So with that said, I want to start out by showing you the information that you can extract from an event log. To do so, I am going to display the most recent event from the System log. This requires two commands to be used. The first line of code retrieves the event log entry that we need and the second line of code displays the entry. The code looks like this:

$MyLog = Get-EventLog –Log System –Newest 1

$MyLog | Format-List –Property *

As you can see in the code above we are referencing the System log, requesting the newest log entry, and then displaying the available properties for that log entry. You can see what this looks like in Figure A.

Figure A: This is the most recent entry from the System log.

As you can see, there is plenty of information that we can display. If we wanted to we could even filter the list so that only specific properties were displayed. For example, we might choose to display the Event ID, the entry type, and the message. If for example we wanted to see this information for the five most recent events in the System log, we could do so by using the following commands:

$MyLog = Get-EventLog –Log System –Newest 5

$MyLog | Format-List –Property EventID, EntryType, Message

You can see the resulting data shown in Figure B.

Figure B: Here are the five most recent entries from the System log.

Of course Hyper-V deployments usually make use of failover clusters. This implies a couple of different things. First, it implies that there are multiple Hyper-V servers. Second, it implies that the virtual machine’s location is completely dynamic. A virtual machine could be created on one host and then immediately moved to another host. Just because a VM resides on a particular host today does not mean that it will be there tomorrow. As such, it is necessary to perform queries across multiple hosts.

The method that you will need to use in order to query multiple servers will vary depending on the number of servers that make up your Hyper-V deployment and whether or not your Hyper-V hosts adhere to a strict naming convention.

If you only have a few Hyper-V servers or if you don’t follow a naming convention, then you are probably going to be best off referencing the server names within the script that you create. This is actually pretty easy to do. I have two Hyper-V servers that are named Prod1 and Prod2. Suppose for a moment that I wanted to display the ten most recent entries in the System logs of servers Prod1 and Prod2. I could do so by entering the following commands:

$MyLog = Get-EventLog –Log System –ComputerName prod1, Prod2 –Newest 5

$Myog | Format-List –Property MachineName, EventID, EntryType, Message

This works exactly like the commands that we had used previously except for two minor changes. First, I added the ComputerName parameter followed by the names of the servers that I wanted to query. Second, I added MachineName to the list of properties so that we could tell where each result was coming from.

You can see what these commands look like in action in Figure C.

Figure C: These event log entries are coming from multiple servers.

The method that I just used works well enough for small Hyper-V deployments, but a single clustered Hyper-V deployment can include over 60 servers. You really don’t want to have to manually type all of those server names every time you run a line of code. If you use naming conventions for your Hyper-V servers that differentiate those servers from other servers in your organization, then you don’t have to manually enter server names. Instead, you can reference the servers through an Active Directory query (the Hyper-V servers must all be Active Directory joined).

The trick is to perform a query that retrieves a list of servers and then assign the query results to a variable. You can then reference that variable when you provide the ComputerName switch rather than entering computer names manually. This is a lot easier to do than it sounds. Let me show you how it works:

In my own organization my Hyper-V lab servers are named Hyper-V-1, Hyper-V-2, Hyper-V-3, etc. Since the names are so similar I can instruct PowerShell to search the Active Directory for computers with names “like” Hyper-V. This can be done using the Get-ADComputer command.

The problem with running this command is that it returns a lot of properties that we don’t need. Not only do we not need these extra properties, they actually get in the way of us achieving the desired result. The key to getting exactly the information that we need is to use ForEach followed by {$_.Name}. Doing so causes only the server’s name to be returned. The actual command that we will be using is:

$Computer= Get-ADComputer –Filter ‘Name –Like “Hyper-V*”’ –Properties Name | ForEach {$_.Name}

If we then type $Computer (which is the name of the variable to which we assigned the list of server names), we should see a list of the Hyper-V servers. You can see what this looks like in Figure D.

Figure D: PowerShell has returned a list of my Hyper-V servers.

Now I can append the commands to retrieve the event log entries from the various servers. These commands are very similar to what I showed you earlier. The commands are:

$MyLog = Get-EventLog –Log System –ComputerName $Computer –Newest 5

$Myog | Format-List –Property MachineName, EventID, EntryType, Message

You will notice in the first line of code that I have replaced Prod1 and Prod2 with the $Computer variable. The nice thing about using this approach is that as long as you continue to adhere to your previously established naming convention for Hyper-V servers, the script will always display results that reflect all of the Hyper-V servers that currently exist. Of course you don’t necessarily have to include all of your Hyper-V servers. It is probably going to be more effective to work with the Hyper-V servers that belong to a particular cluster rather than including every Hyper-V server in the entire organization.


In this article, I have begun showing you how to pull event log entries from multiple Hyper-V servers and display those log entries through PowerShell. In the next article in this series, I want to show you some more things that you can do using the Get-EventLog command. My plan is to show you how to you how to display some relevant statistics from the event logs and how to filter the logs to display only the log entries that are relevant to getting a handle on VM sprawl.

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.


Featured Links