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

  • How to install VMware Workstation 10 on Linux Mint 17.1

    vmware workstation 10 linux mint

    Two goals that I would like to achieve this year is to learn how to program (likely Python) as well as learn more about Linux. So last week I completely wiped my HP laptop that used to run Windows 7 Pro and installed Linux Mint 17.1. However, I had a nested ESXi lab within VMware Workstation when I was running Windows and wanted to do the same on my new Linux install.

    I found this wasn’t just as simple as downloading an .exe and running the file, like it is in Windows. There are a few dependiences that are needed first, below is the steps I took to install VMware Workstation 10 on Linux Mint 17.1.

    Read More “How to install VMware Workstation 10 on Linux Mint 17.1”

  • VMware View client now availabe for Android!

    VMware has announced that they have released a View Client for Android tablets available on the Android Market now. Here are just a few of the features found on the new client.

    • A new look and feel – The View Client for Android features the NEW blue look and feel of the VMware View clients!
    • Multiple broker support – If you have more than one VMware View broker in your organization, you can can easily access your desktop from all of them via the Android client
    • Desktop Shortcuts – Quickly connect with as many as four recent desktop via shortcuts
    • Virtual trackpad – Control your desktop on a granular level just like you would control the mouse on a laptop
    • Custom keyboard toolbar – Super easy access to all of the special keys not found on the Android default keynboard
    • Honeycomb 3.x support – Made from the ground up for the new generation of Android tablets
    • Custom gestures – Invoke keyboard, scrolling, etc are as easy as ever and simple to use
    • VMware View Security Server support (best experience) – No need to have VPN when you use VMware View Security Server
    • Background tasking – Switch between apps on your tablet and come right back
  • Clone VMware ESXi USB boot drive to another USB flash drive

    A few days ago one of my hosts in my home lab was displaying an alarm message:

    Lost connectivity to the device

    Lost connectivity to the device mpx.vmhbaXX:XX:XX:XX backing the boot filesystem /vmfs/devices/disks/mpx.vmhbaXX:XX:XX:XX. As a result, host configuration changes will not be saved to persistent storage.

    The last part of the message (“persistent storage”) made me think it might have something to do with the USB drive due to the fact that a similar message appeared when setting up the home lab on the Intel NUC’s. After some research it appears my assumption was correct and that the USB flash drive I was using to boot from was indeed starting to fail.

    Read More “Clone VMware ESXi USB boot drive to another USB flash drive”

  • Shrink a thin provisioned VMDK disk

    When maintaining a Horizon View environment I like to keep my parent images as small as possible and over time a thin provision disk can start to grow on you if you don’t watch it – be it from downloading installers, updates, or even running disk defrag. While there isn’t a simple, one click button in the View Administrator Console there is a fairly easy manual method using vmfkstools.

    Before we can use “vmkfstools” to shrink the VMDK file we must zero out any unused space on the thin provisioned disk. A simple way of doing this is by using a free utility called SDelete from Sysinternals.

    Read More “Shrink a thin provisioned VMDK disk”

  • Set default printer for View floating desktop and Persona Management

    Sometime ago I asked a question over at the VMware forum about how to set default network printers on a VMware View 5.0 floating pool that used Persona Management as Persona Management wasn’t keeping this user setting on it’s own. The printers would be added to the VM just not remember the default printer setting. I’ll admit I forgot to update the thread, but a work around was devised which I’ll share below.

    Read More “Set default printer for View floating desktop and Persona Management”

  • VCP5 Exam: Passed

    Pass

    This morning I took the VCP510 exam and passed it on my first go at it!

    Overall I felt the exam was a nice challenge, while I can’t go into details of the exam, per the NDA. I will say I was surprised at the number of multiple answer questions and the VPC510 was certainly more “real-world” based and not so much memorizing config maximums.

    That said, I’ll do as others have done and list what I used in my preparation for the VCP510 exam…

    Read More “VCP5 Exam: Passed”

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
    }

    }