PowerCLI Cheatsheet
TL;DR commands, snippets, functions, etc that I have found useful while screwing around with creating & configuring VMs and managing ESXi with PowerCLI. I also finished my function that automates creation & configuration of new VMs in ESXi. It’s on our GitHub here.
Welcome to Part XIV of our cheatsheet series compiled from various courses, labs, stuff we did at work, Google, etc.
Part I: Mimikatz cheatsheet
Part II: Set-Acl cheatsheet
Part III: Get-Acl cheatsheet
Part IV: Enumerating AD cheatsheet
Part V: Windows reverse shells cheatsheet
Part VI: MS Graph PowerShell cheatsheet
Part VII: Hash cracking cheatsheet
Part VIII: The Credential Theft Shuffle
Part IX: SACLs & Querying Collected Logs
Part X: Setting up a simple AD lab in Azure
Part XI: Hyper-V cheatsheet
Part XII: Migrating to openSUSE LEAP
Part XIII: Automating VM creation in ESXi with PowerCLI
Part XIV: PowerCLI cheatsheet
Part XV: Automating VM creation in ESXi with Ansible
Background
I normally only write about things I like and would recommend, the one exemption to that being TryHackMe’s PT1 exam. Hence if I’m writing TryHackMe walkthroughs, a review of a hands on exam like CRTP, a Hyper-V cheatsheet, etc it’s because I like the thing and would highly recommend it to almost anyone.
I say that because I do not recommend VMware or any of their products, while this is a cheatsheet regarding using PowerCLI to manage ESXi.
However my work still uses VMware for now. License renewal hasn’t come up yet after all and most of my co-workers only know VMware. Since work still uses it I have been screwing around with it at home because I like screwing around in non-production environments and because … well it’s still my job to know at least some VMware.
VMware still gives their Player, Workstation, and ESXi away for free, even post Broadcom. However as everyone who has read any of my howtos and cheatsheets knows I like real Hypervisors that I can manage from the CLI. This means Player and Workstation are out for my purposes for much of anything beyond running a Kali VM for TryHackMe use.
VMware also gives PowerCLI away for free but there’s a catch; one cannot actually use PowerCLI to manage ESXi without a license.
This is not a supported TTP obviously, but if you really wants to use PowerCLI to its fullest you can do a Google search for
insite:github.com esxi keyand find a key which will then allow one to screw around in their home lab.
Admin notes
You can run ESXi in VMware Player on your desktop PC if you don’t have a refurbished server or two in a desk high rack in the corner of your storage room. I did this for the first year or two I was home labbing and it worked well enough.
I later upgraded to running ESXi directly on a refurbished HP server and then a year or two after that upgraded the home lab to it’s current version; two centrally managed Hyper-V hosts running on refurbished HP Proliant DL360 G8 servers.
I really like this specific model because:
- They’re easily found on Amazon for around $200
- They’re pretty easy to work on
- They have 4 NICs, 1 management NIC, and lots of HD and RAM slots
- Most parts are hot swappable
- They happily run Hyper-V even though they’re getting pretty old now
That last one is important as I got some heartburn trying to run the newest version of ESXi in a Hyper-V VM on those HP severs. If anyone was wondering why I did these PowerCLI/ESXi home lab projects on ESXi 6.7 it’s because it complained about my hardware a lot less than version 8 did.
Another admin note is that generally speaking one does not want to run PowerCLI on the same Windows system as the Hyper-V PowerShell module. This is because many of the commands overlap. I got around this by managing ESXi directly from my refurbished Dell Latitude 5580 laptop that I got for around $600 back in late 2020 and have been using ever since.
The other admin note is that most of what’s in this cheatsheet requires your copy of ESXi to be licensed.
Get Rich’s stories in your inbox
Join Medium for free to get updates from this writer.
The last Admin Note is that in my home lab:
- The Hyper-V severs are .99 & .100
- The DCs are .101 — .104
- I give all my VMs IPs .110 and up
- Hence I gave my ESXi server .98
Bear this in mind when you’re reading my notes below.
Automating VM creation & config
My function is here. Simply import it and then run via:
New-VM_from_Template -ESXi 192.168.0.98 -ESXi_User root -ESXi_Password <password> -$VMName TestServer -HostOctet 112 -DomainName test.local -DomainUser Mishky -DomainPassword <password>To create, config, and domain join a VM named TestServer, for example, using Mishky’s account to join the VM to the test.local domain.
My PowerCLI Notes
This list is far from complete and I will likely add to it as I go.
Installing PowerCLI
Install-Module -Name VMware.PowerCLI -Scope CurrentUser -Repository PSGallery -Force
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
Set-PowerCLIConfiguration -Scope User -ParticipateInCEIP $false -Confirm:$false
Get-Module -Name VMware.PowerCLI -ListAvailableConnecting to ESXi & licensing
#Connect to ESXi, kinda required before running any of the following commands
Connect-VIServer -Server "192.168.0.98" -User "root" -Password '<password>'
#Assign a license key (ESXi 7)
Set-VMHost -VMHost 192.168.0.98 -LicenseKey "1C20K-4Z214-H84U1-T92EP-92838"
#Verify key
Get-VMHost -Name "192.168.0.98" | Get-VMHostLicenseInformation
#If ESXi times out Force-kill any stale/orphaned session objects in memory
Disconnect-VIServer -Server * -Force -Confirm:$false -ErrorAction SilentlyContinueOperations on ESXi & VMs
#Set DNS servers used by ESXi
Get-VMHost "192.168.0.98" | Get-VMHostNetwork | Set-VMHostNetwork -DNSAddress "192.168.0.101", "192.168.0.102", "192.168.0.103", "192.168.0.104", "8.8.8.8"
#Give ESXi a name and domain
Get-VMHost "192.168.0.98" | Get-VMHostNetwork | Set-VMHostNetwork -HostName "ESXi01" -DomainName "test.local" -Confirm:$false
#Join ESXi to a domain
#Don't put test\username, just put username with rights to join the domain
Get-VMHost | Get-VMHostAuthentication | Set-VMHostAuthentication -JoinDomain -Domain "test.local" -Credential (Get-Credential)
#Remove an old VM
Remove-VM -VM "Lab-DC" -DeletePermanently -Confirm:$false
#Show RAM, used HD, creation date of VMs
Get-VM | Select-Object Name, MemoryGB, @{N="UsedSpaceGB"; E={[math]::Round($_.UsedSpaceGB, 2)}}, CreateDate
#Take a snapshot of a VM
New-Snapshot -VM "TestServerII" -Name "Pre-Update" -Description "Snapshot taken before applying Windows updates"
#View existing snapshots
Get-Snapshot -VM "TestServerII"
#Go back to a snapshot
Set-VM -VM "TestServerII" -Snapshot (Get-Snapshot -VM "TestServerII" -Name "Pre-Update Backup") -Confirm:$falseDatastore stuff
# List all datastores on the host
Get-Datastore
# Navigate into the datastore like a local disk
Set-Location vmstore:\ha-datacenter\datastore1\
Get-ChildItem
#Upload a file to the datastore on ESXi
Copy-DatastoreItem -Item ".\id_ed25519.pub" -Destination "vmstore:\ha-datacenter\datastore1\authorized_keys.tmp"
#Copy items on a datastore
Copy-DatastoreItem -Item "C:\Users\fdhsr\Google Drive\Documents\CompTIA studying\Lab Domain Projects\00 Ideas\Automating ESXi VM deployment\autounattend.xml" -Destination "vmstore:\ha-datacenter\datastore1\OS Images\"
Copy-DatastoreItem -Item "C:\Users\fdhsr\Google Drive\Documents\CompTIA studying\Lab Domain Projects\00 Ideas\Automating ESXi VM deployment\unattend.xml" -Destination "vmstore:\ha-datacenter\datastore1\OS Images\"Querying ESXi’s settings
#Capture ESXi's IP scheme
#Capture IP scheme from ESXi
$GW = (Get-VMHostNetwork | Select-Object *).VMKernelGateway
$Subnet = (Get-VMHostNetworkAdapter -Name vmk0 | Select-Object *).SubnetMask
$DNS = (Get-VMHostNetwork | Select-Object *).DnsAddress
$DomainName = (Get-VMHost "192.168.0.98" | Get-VMHostAuthentication).DomainEnabling SSH on ESXi
#Enable SSH on ESXi, resets to default on reboot
Get-VMHost -Name $ESXi | Get-VMHostService | Where-Object { $_.Key -eq 'TSM-SSH' } | Start-VMHostService -Confirm:$false
#Set SSH to enabled permanently
Get-VMHost -Name "192.168.0.98" | Get-VMHostService | Where-Object { $_.Key -eq 'TSM-SSH' } | Set-VMHostService -Policy "on" -Confirm:$false
#Confirm SSH status
Get-VMHost -Name "192.168.0.98" | Get-VMHostService | Where-Object { $_.Key -eq 'TSM-SSH' } | Select-Object Key, Label, Running, PolicyRun a command on a VM
#Run a command against VM
# VM's initial local admin credentials:
[string]$userName = ".\Administrator"
[string]$userPassword = '<password>'
# Convert to SecureString and build PSCredential object
$secStringPassword = ConvertTo-SecureString $userPassword -AsPlainText -Force
$InitialCredObject = New-Object System.Management.Automation.PSCredential ($userName, $secStringPassword)
Invoke-VMScript -VM $VMName -GuestCredential $InitialCredObject -ScriptType Powershell -ScriptText {ipconfig /all}Run a code block on a VM
I’ll use my Config-NIC as an example. I orginally wrote a Config-NIC.ps1 for Hyper-V and I won’t lie; I’m rather proud of it. It
- Captures the Gateway, subnet mask, DNS servers, and first 3 octets of the IP address from the hypervisor itself.
- Lets you specify the 4th octet for the new VM and sets the rest according to the hyervisor’s settings.
Hyper-V is IMHO very intuitive and I was able to write Config-NIC for it on my own. Admittedly Gemini helped a bit with Config-NIC for ESXi, for example the part that converts the subnet mask to CIDR and the part that formats the DNS servers list are all Gemini.
Gemini also let me know that little trick about using the backtick ( ` ) to escape variables in the $ScriptPayload.
The rest was all just me translating my Hyper-V Config-NIC to ESXi.
#Run a code block against a VM
Function Config-NIC
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)]
[string]$VMName,
[Parameter(Mandatory=$true)]
[int]$HostOctet, # e.g., 112
[Parameter(Mandatory=$true)]
[pscredential]$GuestCred,
[Parameter(Mandatory=$false)]
[string]$ESXiHost = $ESXi
)
#Get the IP scheme from ESXi itself
$GW = (Get-VMHostNetwork -Server $ESXiHost).VMKernelGateway
$SubnetMask = (Get-VMHostNetworkAdapter -Server $ESXiHost -Name vmk0).SubnetMask
$DNSServers = (Get-VMHostNetwork -Server $ESXiHost).DnsAddress # Returns array of DNS IP strings
#Use the first 3 octets of ESXi's IP + 4th Octet for the new VM
$SubnetBase = ($ESXiHost.Split('.')[0..2]) -join '.' # "192.168.0"
$TargetIP = "$SubnetBase.$HostOctet" # "192.168.0.112"
#Convert Subnet Mask to CIDR Prefix (i.e., "255.255.255.0" -> 24)
$Bytes = $SubnetMask.Split('.') | ForEach-Object { [Convert]::ToString([byte]$_, 2) }
$PrefixLength = ($Bytes -join '').IndexOf('0')
if ($PrefixLength -eq -1) { $PrefixLength = 32 }
#Format DNS Server List into PowerShell Array Syntax string
#Converts @("192.168.0.101", "192.168.0.102") -> "'192.168.0.101','192.168.0.102'"
$FormattedDNS = ($DNSServers | ForEach-Object { "'$_'" }) -join ','
#Build Dynamic Payload via Double-Quoted String Expansion
$ScriptPayload = "
`$Adapter = Get-NetAdapter | Where-Object { `$_.Status -eq 'Up' } | Select-Object -First 1
# Configure Static IP and Default Gateway
New-NetIPAddress -InterfaceAlias `$Adapter.Name -IPAddress '$TargetIP' -PrefixLength $PrefixLength -DefaultGateway '$GW'
# Assign Dynamic DNS Array from ESXi Host
Set-DnsClientServerAddress -InterfaceAlias `$Adapter.Name -ServerAddresses @($FormattedDNS)
# Disable IPv6
`$NIC = (Get-NetAdapter).InterfaceAlias
Disable-NetAdapterBinding -InterfaceAlias `$NIC -ComponentID ms_tcpip6
Install-WindowsFeature -Name 'RSAT' -IncludeAllSubFeature
Rename-Computer -NewName '$VMName' -Force
Restart-Computer -Force
"
# 6. Execute inside VM over ESXi Hypervisor Layer
Invoke-VMScript -VM $VMName -GuestCredential $GuestCred -ScriptType PowerShell -ScriptText $ScriptPayload
}Summary
I don’t like VMware but I recognize that many, including my work still use it. Hence these last two home lab projects and this cheatsheet. Besides, I’d be lying if I said I didn’t have fun screwing around with PowerCLI for free. It’s just stupid that I had to chase down a license key on GitHub to do so.
If any of this helps anyone else then I’m flattered. I’m posting this just to put my PowerCLI notes all in one place, update it as I go, and because I know damn well that if I use PowerCLI 2–3 years from now I won’t remember how to set the DNS servers ESXi will use.
I post these cheatsheets so I don’t have to remember. I can just Ctrl + F this.
A future lab project is to try automating creation & configuration of a Linux VM including joining it to AD. After all Invoke-VMScript supports BASH and Bat as well as PowerShell.
Well that’s a future lab project for a future howto.
References
PowerCLI howto: https://www.techrepublic.com/article/how-to-manage-esxi-hosts-remotely-with-powercli/








