PowerCLI Tutorial: A Guide for Newbies Managing VMware

Dave Pinkawa

Read more posts by this author.

PowerCLI by VMWare is becoming the ubiquitous interface for hypervisor virtualization administrators of ESXi supported hardware. Learning how to manage VMware via PowerShell and PowerCLI is a strong addition to your toolkit. In this PowerCLI tutorial, you’re going to learn how to do just that.

In this tutorial, you will learn:

  • the basics of connecting to VMware infrastructure with PowerCLI
  • familiarize yourself with cmdlets for working with VMware objects
  • empower yourself with the knowledge to explore
  • manage VMware further via PowerCLI

Let’s get to it!

What You Need to Have and Know

Before you get too far in this PowerCLI tutorial, it’s always important to ensure you and I are both on the same page. For this article, I’m going to be assuming that:

  • You have basic PowerShell experience.  You don’t have to be a PowerShell expert, by any means, but any PowerShell familiarity you have will serve you well.
  • You have a VMware ESXi host or vCenter appliance for connecting to and testing
  • You’re working on a Windows (Or Mac / Linux) workstation
  • You have PowerCLI already installed and are connected. If not, check out this PowerCLI installation article.

I’ll be using PowerCLI v 11.4.0. I will be working from a Windows 10 workstation with Windows PowerShell 5.1, but you’re welcome to use PowerShell 6 instead as there’s feature parity for this tutorial.

Gather Information on ESXi Hosts with PowerCLI

Before you dive into the virtual layer of our vSphere environment, it is a good idea to review the physical hardware layer. VMware PowerCLI provides a cmdlet directly for this purpose, to gather detailed information called Get-VMHost.

While you’re connected to your vCenter server or ESXi host, run the following cmdlet.

PS51> Get-VMHost

Since I am connected to a vCenter Server Appliance which is managing two separate ESXi hosts, I am provided with some basic information about the hosts being managed. The Get-VMHost allows you to review the hardware capabilities of your virtualization hosts. But, by default, Get-VMHost doesn’t return all the information it can.

If you pipe the Get-VMHost cmdlet to Format-List, you will get console output for all information about the given hosts.

Get-VMHost | Format-List
Get-VMHost | Format-List

Alternatively, you can be pickier and only select individual properties on the VMHost object you’re working with like:

PS51> Get-VMHost | format-list -Property State,LicenseKey,Version

Leveraging this more verbose output will provide an even greater view of the underlying hardware running your virtualized workloads. Some of the information, in particular, would be:

  • License validation info
  • CPU/Memory totals
  • Hardware vendor model
  • DNS hostname

After review, this can be compiled into a CSV file perhaps using the Export-CSV cmdlet.

Inspecting VMs with PowerCLI

Let’s now dive into another topic in this PowerCLI tutorial by reviewing virtual hosts is reviewing which virtual machines are currently present on a given ESXi host.

The Get-VM command is a handy command you can use to review VM information.

PS51> Get-VMHost -Name <Host FQDN> | Get-VM

The output of this cmdlet will look something like below:

PS51> Get-VMHost -Name <Host FQDN> | Get-VM
PS51> Get-VMHost -Name | Get-VM

The output above provides a full status list of currently running VMs on a given host. If you were to choose to not specify an individual host, as I have done above, you’ll receive a table of information for each subsequent host and the VMs on each.

If you are ever troubleshooting an issue and need to know the number of virtual machines on a given host or have a need to use VMware PowerCLI to gather ESXi host information, you can use these cmdlets going forward. The reporting functionality you have at your fingertips is starting to expand!

Inspecting Virtual Switches with PowerCLI

For those of us charged with configuring or administering the virtual networks of a vCenter cluster, there is a full range of networking cmdlets for any use case. If you wish to see the virtual switches configured in your vSphere environment, you will use the following:

PS51> Get-VirtualSwitch

Depending on the number of virtual networks and virtual switches you have, your resulting list may be quite large. In my case, as you see below, I have a single DSwitch which is a Distributed Virtual Switch.

In an Enterprise vSphere implementation where there are many ESXi hosts in a cluster, DSwitches simplify the deployment of virtual switches and port groups across a multitude of hosts with the same configuration. This saves on the manual labor of creating identical network configurations on each host manually, and is a great way to scale your cluster!


Finding VMs Attached to a Virtual Network with PowerCLI

While attempting to narrow down the scope of an issue, you may wonder which VMs are connected to which networks. To figure that out, you can use the Get-VirtualPortGroup command. Let’s learn about this cmdlet in this PowerCLI tutorial.

A port group is essentially a virtual network. To display all port groups, run Get-VirtualPortGroup without any parameters. You should then see a listing of all virtual port groups present in your vSphere environment.


To find all of the VMs inside of that port group (DPortGroup in my case), you can run the below script. Be sure to replace the value DPortGroup with the name of your Virtual Port Group.

PS51> Get-VM | Where-Object { ($PSItem | Get-NetworkAdapter | where {$_.networkname -match "DPortgroup"})}

In this one-liner, we are getting a list of all virtual machines that exist in this vCenter appliance, and then filtering with the Where-Object cmdlet to get only those VMs with a network name that matches our Port Group.

Getting VMs with only a specific port group
Getting VMs with only a specific port group

With this output, you’ll be able to define what machines are connected and configured for each network.

When asked to locate and analyze which VMs are connected to a particular network in VMware you will now be empowered to provide a PowerCLI reporting solution to this question.

Getting OS Version Information on your VMs with PowerCLI

The bulk of administrative work inside of VMware is done at the virtual machine level. You’re likely to receive countless requests for tasks like retrieving a list of all hard drive sizes on VMs or getting guest OS versions for all your servers among others.

These tasks are cumbersome at scale. PowerCLI is able to streamline these with a few important cmdlets to add to your arsenal so let’s cover them in this PowerCLI tutorial.

You may have been asked at some point in time, “How many Ubuntu servers do we have in our VMware cluster?”. You might have then spent way too much time clicking around in vCenter looking for an answer. PowerCLI can streamline this process by looking at the VM objects in vCenter and applying some PowerShell magic on the output.

Take a look at the following script that pulls together VM information. This snippet uses the Get-View command which we will go into a bit later but for now, you should know that it is an advanced way to retrieve VMware object properties. In this case, we’re gathering nested properties that are most easily retrieved in this method.

PS51> Get-VM | 
      Sort-Object -Property Name |
      Get-View -Property @("Name", "Config.GuestFullName", "Guest.GuestFullName") |
      Select-Object -Property Name, @{N="Configured OS";E={$_.Config.GuestFullName}}, @{N="Running OS";E={$_.Guest.GuestFullName}}

The above code is retrieving a  list of virtual machines via the PowerCLI Get-VM cmdlet, sorting said list with the PowerShell Sort-Object cmdlet, and then retrieving some of the object properties using the PowerCLI Get-View cmdlet.

Running this in my environment yields the result below. You can see the name of the VM in vCenter, the Configured OS which is how VMware’s virtual hardware is set to interpret the guest operating system, and the actual Running OS that represents the actual OS.

Finding VMs based on various criteria
Finding VMs based on various criteria

With the VMs replicant and Scriptrunner are powered off in the cluster, you will not be able to see the Running OS value for them. The OS is gathered by the VMware Tools service. If it’s not available, PowerCLI cannot pull the operating system information.

Creating CSV Reports with PowerCLI

VMware Tools is an in-guest service for both Windows and Linux VMs that provides the hypervisor additional information and administrative capabilities. Most commonly this will provide clean-shutdown, operating system information, and higher resolution console viewing of the VMs.

A convenient way to report on and provide this information would be to pipe the above script into the Export-CSV  cmdlet. Export-Csv will create a CSV file with the same information you see in the console.

PS51> Get-VM | Sort-Object -Property Name | Get-View -Property @("Name", "Config.GuestFullName", "Guest.GuestFullName") |
Select -Property Name, @{N="Configured OS";E={$_.Config.GuestFullName}}, @{N="Running OS";E={$_.Guest.GuestFullName}} | Export-CSV C:\report.csv -NoTypeInformation 

After running the above code, you should then be able to open the CSV file with Excel to review the report.

CSV file of VM information
CSV file of VM information

Inspecting Virtual Hard Disks with PowerCLI

The Get-Harddisk command is another useful command to know. The Get-HardDisk cmdlet allows you to inspect information about virtual hard disks attached to VMs.

For example, to query information about the virtual hard disk attached to the exchange1 VMs, you could run the following:

PS51> Get-VM -Name exchange1 | Get-HardDisk | Format-List
query information about the virtual hard disk attached to the exchange1 VMs
Querying information about the virtual hard disk attached to the exchange1 VMs

Some of this information may be redundant, such as the capacity in KB vs. GB. But there is value in knowing the StorageFormat (thin/thick provisioning types). And knowing the VMDK file name.

For example, ff you see a common issue and all VM hard disks reside on the same datastore volume, this knowledge may expedite troubleshooting.

Inspecting Virtual Network Adapters with PowerCLI

In addition to reviewing hard disk information of your virtual machines, you may also want to check on the virtual network adapters. To check on these properties for a single VM, you can use the Get-NetworkAdpter cmdlet.

PS51> Get-NetworkAdapter -VM myVM

While you had hunted earlier in this port for all VMs residing in the same network, this time you only want to see the adapters connected to a particular VM.


This is useful if troubleshooting VMs that have multiple network adapters connected. You can quickly and at a glance determine if those adapters are connected to the proper networks.

Running PowerShell Scripts in VMs with Invoke-VMScript

Using the Invoke-VMScript, you can also run PowerShell code directly inside of the VM; no network connectivity necessary. If you have ever used PowerShell Direct within a Hyper-V environment, this will be a similar experience.

Instead of creating a PowerShell Remoting session or using the Invoke-Command cmdlet over the network, the Invoke-VMScript cmdlet can send commands directly to the VM without normal WinRM or SSH connectivity.

As an example, perhaps you’d like to perform a simple directory listing on a VM called exchange1. To do so, you would pass dir C:\ as the value for the ScriptText parameter as shown below.

PS51> Invoke-VMScript -VM exchange1 -ScriptText "dir C:\"

The results are as if you had run the commands from the VM console itself. Invoke-VMScript then relays all of the output the command that was run on the VM returns.


While this is a basic example, you can get as complicated as you would like. This PowerCLI cmdlet allows you to specify batch, PowerShell, or Bash types within the ScriptText parameter.

You can get more advanced as well. Below you can see how to use Invoke-VMScript to run PowerShell code using a separate $script variable for the ScriptText parameter input. This allows us to create more customized script input for the VM to process.

PS51> $script = 'Get-Disk'

$guestCredential = Get-Credential

Invoke-VMScript -ScriptText $script -VM VM -GuestCredential $guestCredential  -ScriptType Powershell

The ScriptText parameter value needs to a string. This is why the $script variable has the single-outer-quotes as a necessity.

You may have also noticed the use of the GuestCredential parameter. This parameter is used to authenticate into the VM operating system. This parameter is especially useful if you want to run the script as a different account.

Your script in action should result in output similar to below.

Running a script on a VM with Invoke-VMScript
Running a script on a VM with Invoke-VMScript

The result of this script provides us with the VM’s disk information. Based on that, you should know it’s a remote VM because of the VMware Virtual Disk as the friendly name of the drive.

Getting Advanced with Get-View

You may have seen some of the basic cmdlets return a property called ExtensionData. You can find this property by piping many PowerCLI cmdlets to the PowerShell Get-Member cmdlet.  If you were wondering what that was, now’s your chance to find out.

The next step in this venture is understanding the Get-View cmdlet. VMware PowerCLI leverages many different queries to the VM to provide the pretty and simple output of Get-VM. But there is a lot under the hood that is only accessible by using the Get-View cmdlet.

You’re likely to see a lot of scripts using this cmdlet. It would behoove you to spend some time getting used to seeing this cmdlet in action. To familiarize yourself, use the Get-View cmdlet to get some virtual machine information (exchange1 in this example).

You can see the Filter options of this cmdlet require the use of a PowerShell hashtable and not individual string values. Be aware when building your own unique scripts!

PS51> Get-View -ViewType VirtualMachine -Filter @{"Name" = "myVMName"}

The result of the command above is a lot of nested configuration information and method options for taking actions against the VM or getting object properties.


If you use the same script above and send the output to a variable, you can inspect those nested options with dot notation. Here you can see and retrieve all of that additional information of the guest operating system, that you may want to report on via PowerCLI.

PS51> $VM = Get-View -ViewType VirtualMachine -Filter @{"Name" = "myVMName"}
PS51> $VM.Guest
Using Get-View with the Filter Parameter
Using Get-View with the Filter Parameter

Perhaps you’d like to select a single property. If so, you could run the following to narrow down an individual value.

PS51> $VM.Guest.GuestFullName

There are many Get-View options for all types of VMware objects. Feel free to explore all of these options and review this informative article from VMware that goes in-depth on this powerful cmdlet!

VMware Code Capture – Learn from your Clicks

If you’d like to take advantage of PowerCLI but would rather not build code by typing, Code Capture in vCenter is here for you. Code Capture is a new developer tool that acts similarly to the Active Directory Administrative Center. Let’s cover Code Capture in this PowerCLI tutorial.

This tool records all actions you take within the GUI. It then transforms all of those actions and provides you with PowerCLI scripts.

By default, Code Capture is not turned on. To turn it on, open up your vCenter appliance and navigate to  Menu –> Developer Center as shown below.

Navigating to the Developer Center menu item in vSphere
Navigating to the Developer Center menu item in vSphere

Once at the Developer Center tab, toggle the Enable Code Capture option.

Enabling code capture
Enabling code capture

When you enable Code Capture, you will then see a red Record button within your vCenter header. Once enabled, whenever you wish to have an action recorded and turned into PowerCLI output you must record the GUI activity by hitting the record button.

Code capture enabled indicator
Code capture enabled indicator

The red record button will appear next to your logged on user section of vCenter so that you can now record at any time.

To demonstrate Code Capture, go through the New Virtual Machine creation wizard.

  1. Click on the Record button to begin recording. This will cause the red Record button to begin pulsing.
  2. Right-click your VMware host, and Create a New Virtual Machine. Run through the resulting wizard creating a new virtual machine with all default values.
  3. Once the virtual machine is created, click on the record button and stop your recording.

The resulting output may be slightly more verbose than anticipated. The output even includes all actions of browsing the GUI before creating the VM. But you should see a section denoted in the comments starting with CreateVM_Task. This is where the code begins to create a VM.

Below is a portion of the CreateVM_Task output of the New VM Wizard process in the GUI via Code Capture:

Developer Center generated code
Developer Center generated code

This output can be a little overwhelming, but it exposes you directly to the number of configuration options available to your virtual machines. Depending on your own needs, you’re now empowered to make adjustments in your own scripts and customize to your heart’s content.

The Code Capture utility isn’t limited just to VM creation. It can also build code for networking changes, small VM modifications, or host configuration changes. By being able to review the PowerCLI output of GUI actions you can take a shortcut on your journey to infrastructure deployed as code.

PowerCLI Tutorial Summary

In this article, you covered a lot of ground. Nice job! I hope that you’ve realized the power that PowerCLI brings to managing VMware infrastructure.

There are a lot of cmdlets in PowerCLI for a wide range of product bases but we only covered a few here. Be sure to stay tuned to this blog for more articles on this awesome tool!

Further Reading

Subscribe to Stay in Touch

Never miss out on your favorite ATA posts and our latest announcements!

Looks like you're offline!