Using PowerShell to locate a Hyper-V virtual machine

Hyper-V is a dynamic environment, and virtual machines can easily move from one host to another. Sometimes though, you may need to know which Hyper-V host a particular VM is running on so that you can perform some sort of management task against the VM. PowerShell makes it relatively easy to locate a single VM among a large number of Hyper-V hosts.

Finding a Hyper-V VM: The quick and dirty method

There are a few different ways of getting the job done, and the method that you will need to use will vary depending on how many hosts you have, and on how often you need to locate a specific VM. If you are just looking for a quick and dirty way to find a particular VM, then you can use a command like this one:

Get-VM -ComputerName ,, -VMName -ErrorAction SilentlyContinue | Select-Object VMName, ComputerName

If you were to run this command in real life, then you would replace <Host1>, <Host2>, and <Host3> with the names of your Hyper-V hosts (IP addresses only work under very specific circumstances). You would also replace <virtual machine name> with the name of the virtual machine that you are looking for.

When you run this command, it checks each of your Hyper-V hosts to see if the specified virtual machine exists. If the virtual machine does not exist on a particular host, then PowerShell hides the error message that would normally be displayed. If the virtual machine does exist, then PowerShell displays the virtual machine name and the name of the host on which the VM resides. You can see an example of this in the figure below.

Hyper-V
As you can see in the figure, this technique works really well. Even so, there are a couple of disadvantages to using this method. First of all, the command requires you to type in the names or IP addresses of your Hyper-V hosts. That’s probably not a big deal if you only have a few hosts, but if you have more than three or four hosts, then this can quickly become a tedious chore.

The other disadvantage of this approach is that the command gives us the required information, but it doesn’t do anything with it. This approach would be a lot more useful if the VM name and the hostname were both written to variables so that we could run additional commands. For example, maybe we want to establish a remote session with the host or initiate a live migration or something like that. The whole thing could be automated if we could put the VM name and the name of its host into variables.

Utilizing a text file

One way of saving yourself some typing is to create a text file containing the names of your Hyper-V hosts. You can then tell PowerShell to read the names from this file so that you don’t have to type them each time.

For the purposes of this article, I have created a file named C:\Scripts\HostList.txt. This file lists the name or IP address of each of my Hyper-V hosts. Each host appears on a separate line. I then wrote a short script that does exactly the same thing as the command that I showed you earlier, except that it pulls the hostnames from my text file. Here is what the script looks like:

$HyperVHosts = Get-Content 'c:\scripts\HostList.txt'
ForEach ($IndividualHost in $HyperVHosts)
{
Get-VM -ComputerName $IndividualHost -VMName <Virtual Machine Name> -ErrorAction SilentlyContinue | Select-Object VMName, ComputerName
}

The first line of code tells PowerShell to read the file’s contents into a variable named $HyperVHosts. I then created a loop that examines each host listed within the text file. The host that is currently being checked is referenced by the variable $IndividalHost. You can see my code and the script’s output in the next figure.

Hyper-V
Using variables

So far we have solved the problem of having to type a long list of hosts, but we still need to place the VM name and the name of its current host into variables that we can use for other purposes. If you look at the previous screen capture, you can see that I have hardcoded the name of the VM that I am looking for, but it would be just as easy to accept the VM name as input.

I accomplished this by adding one line of code to the beginning of the script:

$VM = Read-Host “Please enter the name of the virtual machine that you are looking for.”

This line prompts the user to enter a virtual machine name, and then writes that name to a variable called $VM. I then referenced this variable in the Get-VM command. You can see the script and its output in the figure below.

So now we have a variable that contains the virtual machine name. The last thing that we need to do is write the name of the virtual machine’s host to a variable. Here is how it’s done:

$VM = Read-Host "Please enter the name of the virtual machine that you are looking for."
$HyperVHosts = Get-Content 'c:\scripts\HostList.txt'
ForEach ($IndividualHost in $HyperVHosts)
{
Get-VM -ComputerName $IndividualHost -VMName $VM -ErrorAction SilentlyContinue | Tee-Object -Variable Temp | Out-Null
$VMHost = $Temp.ComputerName
}
Write-Host "The virtual machine " $VM " is hosted on " $VMHost

As you can see, I have significantly modified the Get-VM command. Initially, the Get-VM command tries to retrieve the specified VM from the host server that is currently being checked. Errors are also being suppressed, just as before. However, now I am using the Tee-Object command to write the output to a variable. I then appended the Out-Null cmdlet to prevent the results of the Get-VM cmdlet from being displayed onscreen.

The Tee-Object cmdlet creates a variable called $Temp, which contains the contents of the Get-VM cmdlet. Within the same loop, I am also creating a variable called $VMHost. This variable is assigned the contents of $Temp.ComputerName, which at some point will store the name of the host that is running the specified VM. You can see the script and its output in the figure below.

Final check

The script that I have created is simple enough that you shouldn’t have too much trouble with it. If you do run into problems though, there are three things that you should check.

1. Make sure that the host list text file lists hosts by name, not IP address.
2. Make sure that the computer on which you are running PowerShell can resolve the hostnames.
3. Make sure that all of the hosts (and the machine on which the script is running) are running similar versions of Windows. I ran into problems when I ran the script on a Windows Server 2016 machine, but the VM that I specified was hosted on Windows Server 2012 R2 Hyper-V.

Featured image: Pixabay

About The Author

1 thought on “Using PowerShell to locate a Hyper-V virtual machine”

  1. What is the use of Tee-Object when you ‘out-null’ the other fork of the tee? Wouldn’t it be easier to just assign it directly to a variable…

    $VMHost = (Get-VM -ComputerName $IndividualHost -VMName $VM -ErrorAction SilentlyContinue).ComputerName

    …then you don’t need the line that follows either…

    $VMHost = $Temp.ComputerName

    …since you’ve already grabbed that property in the first command.

    Also, if build your host list into an array object…

    $HyperVHosts = @(“host01″,”host02″,”host03”)

    …you don’t need the ForEach loop since the computername property of Get-VM will accept an array of string values.

    $VM = Read-Host “Please enter the name of the virtual machine that you are looking for.”
    $HyperVHosts = @(“host01″,”host02″,”host03”)
    $VMHost = (Get-VM -ComputerName $HyperVHosts -VMName $VM -ErrorAction SilentlyContinue).ComputerName
    Write-Host “The virtual machine ” $VM ” is hosted on ” $VMHost

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