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

  • Restore a VM using the {vm}-flat.vmdk file

    missing vmdk file error

    A couple days ago I was asked the question “An admin deleted the vmdk file associated with a VM, there are no snapshots or backups of the VM . Can we restore this VM somehow?“. I believe in backups, I like to have my VM’s backed up so that I can depend on them for events just like this very issue. At first I was stumped, until the {vm-name}.flat.vmdk was mentioned. That’s when I remembered a method to recover a VM using the vm-flat.vmdk file that I had actually done 2-3 years ago.

    Read More “Restore a VM using the {vm}-flat.vmdk file”

  • Thank you VMware Community!

    VMware vExpert 2014

    So far, 2014 has been a very rewarding year for a number of reasons, two of which has happened in just a week or two span. First, Eric Siebert (@ericsiebert) announced on March 27th, this years results of the 2014 Top VMware & Virtualization Blog voting. My first year entered into voting and made it to 71st place! A huge thanks goes out to not only Eric but just as much so to everyone who voted for me!

    To top it off, yesterday VMware announced 2014’s first quarter VMware vExpert list. While vExpert isn’t a technical certification or even a general measure of VMware expertise. The VMware judges selected people who were engaged with their community and who had developed a substantial personal platform of influence in those communities. There were a lot of very smart, very accomplished people, even VCDXs, that weren’t named as vExpert this year. VMware awarded this title to 754 people this year and on that list of many impressive names you’ll find yours truly, Michael Tabor!

    I’m both honored and humbled by both lists. It’s a great feeling to be recognized by not only my peers through the voting in the Top vBlog but also by VMware themselves through the vExpert title.

    So again THANK YOU very much to the entire VMware community, a spectacular community indeed, and congratulations to everyone else that made the Top vBlog and vExpert lists!

  • Download VMware vCenter & ESXi 6.0 Update 2

    VMware has released vCenter Server 6.0 Update 2 and ESXi 6.0 Update 2 (build: 3620759) which include a number of new features and fixes. VMware has also released the much anticipate VSAN 6.2 which includes it’s own bunch of new features such as deduplication, compression, QoS, and RAID5/RAID6 Erasure coding.

    Read More “Download VMware vCenter & ESXi 6.0 Update 2”

  • HTML5 Embedded Host Client, this looks promising

    It’s no secret many people have really disliked the vSphere web client, it’s very sluggish, clunky, and based on flash (flash comes with it’s own security issues). It was rumored and highly hoped that vSphere 6 might be re-written in HTML5, but sadly this didn’t and hasn’t happened yet. While vSphere 6 did improve a bit on the web client the issues many people have had with it in the past still remain today.

    Enter the VMware HTML5 Embedded Host Client fling. I’ve been using and following this fling for a while now and have really enjoyed it and with each release it keeps getting better and better.

    The Embedded Host Client fling is based on HTML5 which allows it works great across all kinds of platforms, it’s fast, responsive, and doesn’t require any plug-ins – YES the VM console works great. If this happens to be a look of what’s to come in a new VMware vSphere web client, then a client is looking very promising!

    If you haven’t tried it yet, you should. It’s extremely easy to install and doesn’t even require a reboot just follow these simple instructions.

    Read More “HTML5 Embedded Host Client, this looks promising”

  • How to change vCenter Operations Manager session timeout

    I’ve been using vCenter Operations Manager for a while now at work for all the great information that can be found about our environment so I tend to log into vCOp at the start of the morning and then come back to as I may or may not need it thoughout the day. One thing that has kind of annoyed me is having to constantly log into the standard UI multiple times a day due to the default 30 minute timeout value.

    Luckily, with a bit of SSH and a few commands we can increase this timeout to anything we like or even disable it all together!

    Read More “How to change vCenter Operations Manager session timeout”

Leave a Reply to Mike Tabor Cancel 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
    }

    }