Update VMware Windows VM’s DNS using PowerCLI

How to update VMware Windows VM’s DNS using PowerCLI

This post will show you how to update a VMware Windows virtual machine’s DNS IP addresses using PowerCLI.

You’ll also see how I went from a starting point to a fully working script – all thanks to the awesome #vCommunity!

Here at work we’ve been doing a number of networking, AD, and DNS changes. In doing so, our DNS IP address have changed. Changing the DNS settings for our workstations was easy, simply edit the DHCP scope.

The servers on the other hand all had static IP’s and static DNS IP’s entered, each of which needed to be updated.

Just like anyone else who uses PowerCLI – the first thing I did was search Google for any code that is already available.

One of the first results I found was this blog post from @jasemccarty

After a few minor edits I had this code ready to run.

Update VMware Windows VM’s DNS using PowerCLI Take 1


# Jase McCarty 6/6/2010

Connect-VIServer vcenter.jasemccarty.com
 
$HostCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter ESX host credential", "", "")
$GuestCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter Guest credentials", "", "")
 
$vmlist = Get-Content C:\Scripts\serverlist.txt
 
foreach ($item in $vmlist) {
 
  # I like to map out my variables
  #$vmname = $item.vmname
  $pdnswins = "192.168.1.1"
  $sdnswins = "192.168.1.2"
 
  #Get the current interface info
  $GuestInterface = Get-VMGuestNetworkInterface -VM $vmlist -HostCredential $HostCred -GuestCredential $GuestCred
 
  #If the IP in the VM matches, then I don't need to update
  Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -DNS $pdnswins,$sdnswins
}

The script however failed. Instead I was presented with red text about missing commands.

At first I searched Google again for “Get-VMGuestNetworkInterface” and found a vSphere PowerCLI Reference page and everything looked good to me.

I reached out to Jase via Twitter to see if he had any suggestions.

Almost immediately Jase kindly informs me that those cmdlet’s have been deprecated, along with a link to this announcement and this Microsoft blog post.

Great, I have everything I need to update the script!

But Jase isn’t done yet. Moments later I get another message from Jase, this time to a Github page with another script he just put together:

Update VMware Windows VM’s DNS using PowerCLI Take 2!


Function Set-VMGuestWindowsIp {
	<#
	.SYNOPSIS
	This function is a modification the Set-VMGuestNetworkInterface
	.DESCRIPTION
	This function is a modification the Set-VMGuestNetworkInterface
    .PARAMETER VM
	The VM 
	.PARAMETER Adapter
	The Name of the Windows Network Adapter
	.PARAMETER IP
	The IP of the Windows Network Adapter
	.PARAMETER Netmask
	The Netmask of the Windows Network Adapter
	.PARAMETER Gateway
	The Gateway of the Windows Network Adapter
	.PARAMETER GuestUser
	The Windows Guest User Account
	.PARAMETER GuestPass
	The Windows Guest User Account Password
	.PARAMETER SetDns
	True or False, set the DNS Address to the Hardcoded DNS
    
	.EXAMPLE
	PS C:\> UpdateIp.ps1 -VM VMNAME -Adapter "Local Network Connection" -GuestUser "admin" -GuestPass "pass" -SetDns $true
	.EXAMPLE 
	PS C:\> UpdateIp.ps1 -VM VMNAME -Adapter "Local Network Connection" -GuestUser "admin" -GuestPass "pass" -SetDns $true -IP "192.168.0.5" -Netmask "255.255.255.0" -Gateway "192.168.0.1"
	.NOTES
	Author                                    : Jase McCarty
	Version                                   : 0.1
	#>

    param(
        [Parameter(Mandatory=$true)][String]$VM,
        [Parameter(Mandatory=$true)][String]$Adapter,
        [Parameter(Mandatory=$false)][String]$IP,
        [Parameter(Mandatory=$false)][String]$Netmask,
        [Parameter(Mandatory=$false)][String]$Gateway,
        [Parameter(Mandatory=$true)][String]$GuestUser,
        [Parameter(Mandatory=$true)][String]$GuestPass,
        [Parameter(Mandatory=$true)][Boolean]$SetDns
    )
    
    # Windows netsh path
    $netshPath = "C:\Windows\System32\netsh.exe"
    # Set DNS Entries
    $pdns = "1.1.1.1"
    $sdns = "8.8.8.8"

    $netsh = "$netshPath interface ip set address $Adapter static $IP $NetMask $Gateway1"
    $netsh1 = "$netshPath interface ip set dnsserver $Adapter static $pdns"
    $netsh2 = "$netshPath interface ip set dnsserver $Adapter static $sdns Index=2"

    If ($IP) {
        # Set the IP Address
        Invoke-VMScript -VM (Get-VM -Name $VM) -GuestUser $GuestUser -GuestPassword $GuestPass -ScriptType bat -ScriptText $netsh 
    }   

    If ($SetDns -eq $true) {
        # Set the Primary DNS
        Invoke-VMScript -VM (Get-VM -Name $VM) -GuestUser $GuestUser -GuestPassword $GuestPass -ScriptType bat -ScriptText $netsh1 

        # Set the Secondary DNS
        Invoke-VMScript -VM (Get-VM -Name $VM) -GuestUser $GuestUser -GuestPassword $GuestPass -ScriptType bat -ScriptText $netsh2 
    }

}
 
# Windows Path
#$vmlist = Get-Content C:\Scripts\logs\serverlist.txt

# Path on my Mac
$vmList = Get-Content /Users/jase/PowerCLI/serverlist.txt

foreach ($VM in $vmlist) {
 
    Set-VMGuestWindowsIp -VM $VM -Adapter "Local Area Connection" -GuestUser "admin" -GuestPass "pass" -SetDns $true
}

I was shocked. I wasn’t expecting anything close to this much feedback. Just a pointer in the right direction and instead get a nearly fully blown working script.

I tried it and received a number of syntax errors. Now to be fair Jase did warn me that he didn’t have any Windows machines to test it on.

Time for more debugging.

How to update VMware Windows VM’s DNS using PowerCLI – Works!

There was three things that I modified in the above code:

  1. I found I didn’t need to provide the full path to netsh.exe so I removed that variable and replaced it simply with netsh.
  2. The $Adapter variable in both of the netsh1 & netsh2 (lines 51-52) needed to be in double quotes.
  3. I needed to use “netsh interface ip add dns “”$Adapter”” $sdns index=2″ in $netsh2 (line 52) in order for the second DNS IP to be properly configured.

Below is the final version of the script.


Function Set-VMGuestWindowsIp {
	<#
	.SYNOPSIS
	This function is a modification the Set-VMGuestNetworkInterface
	.DESCRIPTION
	This function is a modification the Set-VMGuestNetworkInterface
    .PARAMETER VM
	The VM 
	.PARAMETER Adapter
	The Name of the Windows Network Adapter
	.PARAMETER IP
	The IP of the Windows Network Adapter
	.PARAMETER Netmask
	The Netmask of the Windows Network Adapter
	.PARAMETER Gateway
	The Gateway of the Windows Network Adapter
	.PARAMETER GuestUser
	The Windows Guest User Account
	.PARAMETER GuestPass
	The Windows Guest User Account Password
	.PARAMETER SetDns
	True or False, set the DNS Address to the Hardcoded DNS
    
	.EXAMPLE
	PS C:\> UpdateIp.ps1 -VM VMNAME -Adapter "Local Network Connection" -GuestUser "admin" -GuestPass "pass" -SetDns $true
	.EXAMPLE 
	PS C:\> UpdateIp.ps1 -VM VMNAME -Adapter "Local Network Connection" -GuestUser "admin" -GuestPass "pass" -SetDns $true -IP "192.168.0.5" -Netmask "255.255.255.0" -Gateway "192.168.0.1"
	.NOTES
	Author                                    : Jase McCarty
	Version                                   : 0.1
	#>

    param(
        [Parameter(Mandatory=$true)][String]$VM,
        [Parameter(Mandatory=$true)][String]$Adapter,
        [Parameter(Mandatory=$false)][String]$IP,
        [Parameter(Mandatory=$false)][String]$Netmask,
        [Parameter(Mandatory=$false)][String]$Gateway,
        [Parameter(Mandatory=$true)][String]$GuestUser,
        [Parameter(Mandatory=$true)][String]$GuestPass,
        [Parameter(Mandatory=$true)][Boolean]$SetDns
    )
    
    # Windows netsh path
    $netshPath = "C:\Windows\System32\netsh.exe"
    # Set DNS Entries
    $pdns = "1.1.1.1"
    $sdns = "8.8.8.8"

    $netsh = "$netshPath interface ip set address $Adapter static $IP $NetMask $Gateway1"
    $netsh1 = "netsh interface ip set dns ""$Adapter"" static $pdns"
    $netsh2 = "netsh interface ip add dns ""$Adapter"" $sdns index=2"

    If ($IP) {

        # Set the IP Address
        Invoke-VMScript -VM (Get-VM -Name $VM) -GuestUser $GuestUser -GuestPassword $GuestPass -ScriptType Bat -ScriptText $netsh 
    }   

    If ($SetDns -eq $true) {

        # Set the Primary DNS
        Invoke-VMScript -VM (Get-VM -Name $VM) -GuestUser $GuestUser -GuestPassword $GuestPass -ScriptType Bat -ScriptText $netsh1 

        # Set the Secondary DNS
        Invoke-VMScript -VM (Get-VM -Name $VM) -GuestUser $GuestUser -GuestPassword $GuestPass -ScriptType Bat -ScriptText $netsh2 
    }

}

# Windows path to server list
$vmlist = Get-Content C:\Scripts\logs\serverlist.txt

# Mac path to server list
# $vmList = Get-Content /Users/jase/PowerCLI/serverlist.txt

foreach ($VM in $vmlist) {

    Set-VMGuestWindowsIp -VM $VM -Adapter "Ethernet0" -GuestUser "domain\admin" -GuestPass "Password123" -SetDns $true
}

I take no credit for this code. This was made possible by Jase and his generosity by going above and beyond.

The #vCommunity has always been an incredibly helpful community and it’s guys like @jasemccarty that make it what it is!

Similar Posts

  • Easy ESXi 6.0 upgrade via command line

    VMware has released ESXi 6.0 back in March and I recently posted a guide on how to upgrade your vCenter Server Appliance from 5.x to 6.0 – Now we’re going to look at two ways to upgrade a VMware ESXi 5.x host to ESXi 6.0 via command line.

    The first method will show you how to have each ESXi host download the update directly from VMware and then upgrade itself while the second method shows how to download the update, place it on a datastore accessible to the host, then upgrade the host.

    Read More “Easy ESXi 6.0 upgrade via command line”

  • VMware ESXi 5 home lab upgrade

    In the past I’ve been using a single server to run my VMware ESXi home lab. it was slow, old, big and loud. I’ve been meaning to upgrade my home lab for a while and just never got around to it, until now! When looking for new hardware I wanted the servers to be as compact as possible, quiet, and low energy usage as possible while still having some horsepower.

    I debated on going the whitebox solution as I build all my own desktops anyway, I also looked at several other solutions such as the HP ML310e server, Shuttle XH61V barebones machine, but ultimately decided to go with two Intel NUC i5’s.

    Intel NUC i5 and 16GB ram

    Intel NUC i5 DC53427HYE Features:

    • Uses very little energy
    • Completely quiet
    • Supports up to 16GB RAM
    • A dual core CPU that scores nearly 3,600 in PassMark benchmarking
    • Includes vPro which allows me to easily run both NUC’s headless
    • Extremely small, nearly 4 1/2″ inch square footprint

    Read More “VMware ESXi 5 home lab upgrade”

  • Improve Linux VM IO performance by disabling IO Scheduler

    For a little while now we’ve been seeing RedHat Linux virtual machines performing poorly. Tasks would take considerably longer on the Linux VM’s then other Windows VM’s. After digging around I eventually found that RedHat has it’s own IO scheduler that runs in the background. On a physical box this wouldn’t be a big deal, but as a virtual machine everything is already being processed by VMware hypervisor. The fix, disable the IO Scheduler!

    Read More “Improve Linux VM IO performance by disabling IO Scheduler”

  • VMware Recertification Policy

    VMware certified

    Starting today, March 10 2014, new VCP certifications must be re-certified within two years of it’s earned date. Anyone who currently has their VCP certification prior to March 10 2013 has until March 10, 2015 to re-certify.

    The new policy gives you three options to re-certify:

    1. Take the current exam for your existing VCP certification solution track. For example, if you are a VCP3, you could take the current VCP5-Data Center Virtualization (VCP5-DCV) exam.
    2. Earn a new VCP certification in a different solution track. For example, if you are a VCP-Cloud, you could recertify by earning VCP5-Desktop (VCP5-DT) certification.
    3. Advance to the next level by earning a VMware Certified Advanced Professional (VCAP) certification. For example, if you are a VCP5-DCV you could earn VCAP5-DCA certification.

    I can understand why they are doing this but I don’t agree with the changes. As per the announcement if you let your certification expire, “Your certification will be revoked,and you will no longer be entitled to use the certification logo or represent yourself as VMware certified“. Really? You mean everything that was done prior and after taking the exam means nothing?

    Read More “VMware Recertification Policy”

  • VMware Certified Professional 6 (VCP6-DCV) now available

    VMware VCP DCV

    VMware has just recently announced that the VMware Certified Professional 6 (VCP6-DCV) is now available. The new VCP6 exam is similar to the others in the past whereas the VCP6 aims to validate your ability to deploy, configure, administer and scale a vSphere virtualized data center, including administering and troubleshooting virtualization technologies such as:

    • vSphere HA and DRS Clusters
    • Storage virtualization using VMFS
    • Storage DRS and Storage I/O Control
    • Network virtualization using vSphere standard and distributed switches and Network I/O Control
    • vSphere management using vCenter Server and vRealize Operations Manager Standard
    • Virtual Machines

    Read More “VMware Certified Professional 6 (VCP6-DCV) now available”

Leave a Reply

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

4 Comments

  1. Thanks for all the work you put into this. I have been using straight PowerShell to update dns on my servers relying on Get-WMIObject Win32_NetworkAdapterConfiguration. I like this more elegant solution for my vm servers. I will still need to rely on Get-WMIObject to change my physical Windows servers.

  2. Just another thought if you wanted for this to be more automated, since you need to know the name of the network adapter in windows to be able to target it, you can have the script look for it before you make the changes using something like this.

    $Network = Invoke-VMScript -VM $VMName -ScriptType Powershell -ScriptText`
    “(gwmi Win32_NetworkAdapter -filter ‘netconnectionid is not null’).netconnectionid”`
    -GuestUser “UserName” -GuestPassword “Password”
    $NetworkName = $Network.ScriptOutput
    $NetworkName = $NetworkName.Trim()

    Where $NetworkName would be the Windows name of the adapter just in case that all of your adapter names are different depending of the version of the OS.

    1. Stuart you rock buddy. Great addition and I can see this being very handy for those environments where the network adapter names are all over the place.

      Thanks for sharing!

  3. Invoke-VMScript is pretty slow for me, I’d add a -RunAsync switch, and requery the VM fewer times:

    Function Set-VMGuestWindowsIp {
    UpdateIp.ps1 -VM VMNAME -Adapter “Local Network Connection” -GuestUser “admin” -GuestPass “pass” -SetDns $true
    .EXAMPLE
    PS C:\> UpdateIp.ps1 -VM VMNAME -Adapter “Local Network Connection” -GuestUser “admin” -GuestPass “pass” -SetDns $true -IP “192.168.0.5” -Netmask “255.255.255.0” -Gateway “192.168.0.1”
    .NOTES
    Author : Jase McCarty
    Version : 0.1
    #>

    param(
    [Parameter(Mandatory=$true)][String]$VM,
    [Parameter(Mandatory=$true)][String]$Adapter,
    [Parameter(Mandatory=$false)][String]$IP,
    [Parameter(Mandatory=$false)][String]$Netmask,
    [Parameter(Mandatory=$false)][String]$Gateway,
    [Parameter(Mandatory=$true)][String]$GuestUser,
    [Parameter(Mandatory=$true)][String]$GuestPass,
    [Parameter(Mandatory=$true)][Boolean]$SetDns,
    [switch]$RunAsync
    )

    # Windows netsh path
    $netshPath = “C:\Windows\System32\netsh.exe”
    # Set DNS Entries
    $pdns = “1.1.1.1”
    $sdns = “8.8.8.8”

    $netsh = “$netshPath interface ip set address $Adapter static $IP $NetMask $Gateway1”
    $netsh1 = “netsh interface ip set dns “”$Adapter”” static $pdns”
    $netsh2 = “netsh interface ip add dns “”$Adapter”” $sdns index=2″

    $invokeParam = @{
    VM = Get-VM -Name $VM
    GuestUser = $GuestUser
    GuestPass = $GuestPass
    ScriptType = ‘Bat’
    RunAsync = $RunAsync.IsPresent
    }

    If ($IP) {

    # Set the IP Address
    Invoke-VMScript @invokeParam -ScriptText $netsh
    }

    If ($SetDns -eq $true) {

    # Set the Primary DNS
    Invoke-VMScript @invokeParam -ScriptText $netsh1

    # Set the Secondary DNS
    Invoke-VMScript @invokeParam -ScriptText $netsh2
    }

    }