PowerShell Script : How to Backup DNS Zones – Improved

 

Hello World,

Based on some comments and feedback received on the post about backing up DNS Zones, we have decided to publish a new version of the script.  The logic remains the same. The main difference with the previous one is that we are using better the powershell capabilities.

Special thanks to Jeffrey Hicks .

This version of the script integrates the comments, advices and recommendations he made on the previous version of the script.

The Improved Backup DNS Script

You can use this script as a starting point for your own purposes and integrate it in your own scripts or backup/restore strategy.

The Script is quite simple to understand.  In the first section, we define some variables, In the next section, we using wmiobject to get DNS information and we export this information into a csv file using export-csv powershell cmdlet. Finally, we using the dnscmd.exe command to export zones information into text file and store them in the location you have defined.

That’s it

#——————————————————————————————–#
# Script_Name : DNS_Backup.ps1
# Description : backup all DNS Zones defined on a Windows 2008 DNS Server
# Requirements : Windows 2008/R2 + DNS Management console Installed
# Version : 0.4 – Intergrated comments from Jeffrey Hicks
# Date : October 2011
# Created by Griffon
#——————————————————————————————-#

#– DEFINE VARIABLE——#

# Get Name of the server with env variable

$DNSSERVER=get-content env:computername

#—Define folder where to store backup  —–#
$BkfFolder=”c:\windows\system32\dns\backup”

#—Define file name where to store Dns Settings
$StrFile=Join-Path $BkfFolder “input.csv”

#—-Check if folder exists. if exists, delete contents–#
if (-not(test-path $BkfFolder)) {
new-item $BkfFolder -Type Directory | Out-Null
} else {

Remove-Item $BkfFolder”\*” -recurse
}

#—- GET DNS SETTINGS USING WMI OBJECT ——–#
#– Line wrapped should be only one line –#
$List = get-WmiObject -ComputerName $DNSSERVER
-Namespace root\MicrosoftDNS -Class MicrosoftDNS_Zone

#—-Export information into input.csv file —#
#– Line wrapped should be only one line –#
$list | Select Name,ZoneType,AllowUpdate,@{Name=”MasterServers”;Expression={$_.MasterServers}},
DsIntegrated | Export-csv $strFile -NoTypeInformation

#— Call Dnscmd.exe to export dns zones
$list | foreach {
$path=”backup\”+$_.name
$cmd=”dnscmd {0} /ZoneExport {1} {2}” -f $DNSSERVER,$_.Name,$path
Invoke-Expression $cmd
}

# End of Script
#——————————————————————————————-#

Final Words

Using the comments from some our readers, we were able to create a better powershell script. If you are a little bit patient, I might publish the restore DNS script quite soon (meaning this week)

 

Till then

See ya

34 thoughts on “PowerShell Script : How to Backup DNS Zones – Improved

  1. Hi

    Ends with error:
    Missing expression after unary operator ‘-‘.
    At C:\dns_backup.ps1:33 char:2
    + – <<<< Namespace root\MicrosoftDNS -Class MicrosoftDNS_Zone
    + CategoryInfo : ParserError: (-:String) [], ParseException
    + FullyQualifiedErrorId : MissingExpressionAfterOperator

    thanks

  2. Hello there,

    Error problably comes from the fact that I had to break lines within the script…
    I might make a link to a downloadable version
    Anyway, It seems you’ve got it fixed..

    See ya around for more scripts :-))

  3. Hi ,

    Please help me in understanding below lines in script
    $list | foreach {
    $path=”backup\”+$_.name
    $cmd=”dnscmd {0} /ZoneExport {1} {2}” -f $DNSSERVER,$_.Name,$path
    Invoke-Expression $cmd
    }

  4. Hello Sunny,

    we simply loop through the items contains in the variable $list. While looping we simply execute the dnscmd.exe command.

    What’s in bracket are variables that are replaced with values found after -f operator.

    I hope this help

    Till next time

  5. Hi,

    Thanks for publishing this script. I am a bit new to Powershell, but am learning. I have a Microsoft Windows 2008 R2 server that runs DNS, and Powershell 3.0. I want to be able to back up my DNS Zones using your script. I seem to be getting tripped up with this command:

    $List = get-WmiObject -ComputerName $DNSSERVER -Namespace root\MicrosoftDNS -Class MicrosoftDNS_Zone

    get-WmiObject : Generic failure
    At D:\Scripts\DNS_Backup.ps1:32 char:10
    + $List = get-WmiObject -ComputerName $DNSSERVER -Namespace root\MicrosoftDNS
    -Cl …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~~~
    + CategoryInfo : InvalidOperation: (:) [Get-WmiObject], Managemen
    tException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.C
    ommands.GetWmiObjectCommand

    I think it is getting tripped up by the -class parameter. Is there a specific DNS Powershell module I need to first import onto that DNS server before running this script?

  6. Hello Kevin,

    We have seen this error when UAC is enabled and you run the powershell console as a standard user. Please try to run the script within a powershell console started with elevated privileges and check if this is working.

    To run powershell with elevated privilege, right-click the powershell console and select run as administrator

    Let us know if this is working

    Hope this help
    Till next time
    See ya

  7. Hi,

    Thank you for replying back. That did it! I am now running it as a Scheduled Task! Thanks again!

  8. hi

    when i run your script only the csv gets created in the correct backup location. the zone files get created in system32\DNS folder… i did not specify this path for backup. should be c:\backup\DNS

    thanks

  9. Great script,

    One questions though and it is very similar to Sunny’s

    The outcome from:

    $list | foreach {
    $path=”backup\”+$_.name
    $cmd=”dnscmd {0} /ZoneExport {1} {2}” -f $DNSSERVER,$_.Name,$path
    Invoke-Expression $cmd
    }

    Doesn’t get saved anywhere does it? If it doesn’t what is the point of it?

  10. Hello Neuro,

    The syntax might seem special or complex but as you said in your last message, I’m assuming that you got it
    the line $cmd=”dnscmd {0} /ZoneExport {1} {2}” -f $DNSSERVER,$_.Name,$path basically can be split in two part
    the part one use {x} to define parameters to be passed
    the second part after the -f specify which variable needs to be passed
    so you could rewrite the command like dnscmd /zoneExport

    I hope this clear up your mind

    Till next time
    See ya

  11. Ahh yes I understand now thank you.

    One other question, since I don’t have a DNS server to test at the moment, what is the difference between the .csv (from get-WmiObject) and the .txt file (from dnscmd ). Are both needed and how would each be used?

  12. Hey Griffon,

    Sorry for bothering you, I understand the script now, but the problem is, now when I run just the

    “get-WmiObject -ComputerName $DNSSERVER -Namespace root\MicrosoftDNS -Class MicrosoftDNS_Zone”

    I get this error:

    “Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)”

    Any idea what might be causing this?

  13. Hello Neuro,

    are you trying to run the scrit from a remote computer ? You might need to check that the firewall or wmi services…..
    are you running the script in a powershell prompt, ensure that you run as an administrator…

    Till next time
    See ya

  14. Hello,

    When trying to run this script I get the bellow error:

    Get-Dns : Cannot bind parameter ‘RecordType’. Cannot convert value “Script.ps1” to type “DnsShell.RecordType”. Error: “Unable to match the identifier name Script.ps1 to a valid
    enumerator name. Specify one of the following enumerator names and try again: A, NS, MD, MF, CNAME, SOA, MB, MG, MR, NULL, WKS, PTR, HINFO, MINFO, MX, TXT, RP, AFSDB, X25, ISDN,
    RT, NSAP, NSAPPTR, SIG, KEY, PX, GPOS, AAAA, LOC, NXT, EID, NIMLOC, SRV, ATMA, NAPTR, KX, CERT, A6, DNAME, SINK, OPT, APL, DS, SSHFP, IPSECKEY, RRSIG, NSEC, DNSKEY, DHCID, NSEC3,
    NSEC3PARAM, HIP, NINFO, RKEY, SPF, UINFO, UID, GID, UNSPEC, TKEY, TSIG, IXFR, AXFR, MAILB, MAILA, ANY, TA, DLV, WINS, WINSR”
    At line:1 char:12
    + DNS backup Script.ps1
    + ~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-Dns], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,DnsShell.PowerShell.CmdLet.GetDns

    Also I was wondering you had any tips on how to do this as For Each loop (importing a list of my DC’s from a csv then outputting to the same CSV)

  15. Hello Chris,

    We have run the script on a 2012 R2 and no issues. If I read the error, I see there is a mention of a get-dns which looks like a powershell cmdlet… Later on I see something like DnsShell.Powershell.CmdLet.GetDns

    It looks like you are using a custom dns module (DnsShell module). The script we have provided does not use any custom module but simply call DNSCMD.EXE
    About your other question about any tips, If you have an Active Directory infrastructure, you should be using AD integrated zones. This ways you would only need to backup one DC only.

    If you still want to export dns from multiple servers, the easiest way would be to use Powershell remote Powershell using invoke-command

    Hope this help
    till next time
    see ya

  16. in case you’re curious this is what we ended up doing:

    ——
    $IPGDCs = ls -Path ‘AD:\OU=Domain Controllers,DC=domain,DC=domain,DC=com’ | select -ExpandProperty Name
    $mycol = @()
    Foreach ($IPGDC in $IPGDCs){
    $Props = [ordered]@{
    ‘Name’ = $IPGDC;
    ‘IPs’ = $null;
    ‘UseRootHints’ = $null;}

    $OBJ1 = New-Object -TypeName PSObject -Property $Props

    $DCDetails = Get-DNSServerForwarder -ComputerName $($OBJ1.Name)| select UseRootHint,@{name=’IPAddress’;expression={$_.IPAddress -join ‘,’}}
    $OBJ1.IPs = ($DCDetails.IPAddress)
    $OBJ1.UseRootHints = $DCDetails.UseRootHint
    $mycol += $OBJ1
    }#End of foreach

    $Mycol| select * | export-csv -Path c:\path.csv -NoTypeInformation

    ——

  17. Thanks for providing this script. I am attempting to put a process in place to backup our Windows 2012R2 Standalone non-integrated zones. I am running the script in Windows PowerShell ISE with run as Administrator while logged in with an account in the Local Administrators group. The script stalls at “Class:”. This being run from the server that I am trying to backup.

    Thank you for any assistances,
    -Michael

  18. Hello Michael,
    We have tried a gain on a 2012 R2 and it seems to work.
    Can you provide the full error message you are getting ?
    are you sure that there is not break in your line of code in the powershel ISE Admin (did you simply copy/paste the text from the blog into your ISE console)

    When we have that we might have a better view of what’s happening

    till next time
    see ya

  19. I would like to add some improvements to the Backup Script.
    This modifications allows to use a shared folder to drop the backup objetcs.
    The comments are in spanish but are almost the same as the original script.

    thank you so much for sharing this work.

    Hope this contribute help many others.

    Regards.

    #——————————————————————————————-#
    #– Definicion de variables——#

    #Obtener nombre del server con variable de entorno

    $DNSSERVER=get-content env:computername

    #—Definir carpeta donde guardar el backup—–#
    $BkfFolder=”\\contoso.com\bkp_dns”
    $BkpDefaltFolder=”c:\windows\system32\dns\backup”

    #—Definir archivo donde guardar las configuraciones de DNS
    $ArchivoConfig=Join-Path $BkfFolder “input.csv”

    #—-Verifica si existe la carpeta. Si existe borra el contenido–#
    if (-not(test-path $BkfFolder)) {
    new-item $BkfFolder -Type Directory | Out-Null
    } else {

    Remove-Item $BkfFolder”\*” -recurse
    }

    #—- Obtiene configuraciones de DNS atraves de WMI ——–#

    $lista = get-WmiObject -ComputerName $DNSSERVER -Namespace root\MicrosoftDNS -Class MicrosoftDNS_Zone

    #—-Exporta la informacion y la escribe en el archivo escrito en la variable $ArchivoConfig —#

    $lista | Select Name,ZoneType,AllowUpdate,@{Name=”MasterServers”;Expression={$_.MasterServers}},DsIntegrated | Export-csv $ArchivoConfig -NoTypeInformation

    #— Llamada a DNSCMD para exportar todas las zonas
    $lista | foreach {
    $path=”backup\”+$_.name
    $cmd=”dnscmd {0} /ZoneExport {1} {2}” -f $DNSSERVER,$_.Name,$path
    Invoke-Expression $cmd
    }

    #- Mueve todos los items de la carpeta por defecto al servidor de archivos

    copy-item $BkpDefaltFolder -destination $BkfFolder -recurse -verbose

    #-Remueve los archivos de la carpeta .\dns\backup del S.O.
    Remove-Item $BkpDefaltFolder”\*” -recurse

    #Fin del script
    #——————————————————————————————-#

  20. Hey David,

    Thank you for the improvements in the script
    and also thank for you sharing the information

    I hope indeed that this info will be useful to anyone out there….

    Thank you for the visit…
    Till next time
    See ya

  21. Hello Ian,

    If this is the only script you intend to publish into Microsoft Web site, we are OK with this. Thank you for notifying us and having left the original credits and link to our web site. Remember that our resources are free to use but copyrights might apply.

    Till next time
    See ya

  22. Using PS for this looks like an overkill. A simple batch script can do the job easily:
    FOR /F %%G IN (‘DNSCMD /ENUMZONES’) DO DNSCMD /ZONEEXPORT %%G export\%%G.dns
    It will backup all dns zones (AD integrated or standalone) into c:\windows\system32\dns\export

    If you want to filter zone type, you can add more parameter/argument into the ‘DNSCMD /ENUMZONES’

  23. Hello Anh,

    Thank you for your feedback and comments. You have indeed different way to perform this action. You can use the dnscmd or you can use powershell. It’s up to the user to choose which way he wants to use to perform the backup of the DNS

    Till next time
    See ya

  24. @Smithe621,

    do not hesitate the share the info provided here and participate in providing feedback, tips and tricks, and constructive comments
    Hope you and your buddies will enjoy the visit 🙂
    till next time
    See ya

  25. I am newbie here and in search of how to backup my dns, I got this useful script. However, I have some newbie questions.

    1. It is not clear for me what and what I should change to suit my environment. Please help newbie like me indicate what and what I need to change to suit environment.
    1. Once I run this ps script, will it be running automatically? Or I have to be running it every time I want to backup.
    2. What is the proper syntax for a remote server? (\\remotesever.com\folder) and env:network. Right?
    3. Does this script work for Win 2016 Server.
    Once again my apologies for any kind of inexperience here. I want to learn.
    Thanks
    -Schubborniel

  26. @Schulbert,

    1. you do not need to change anything. The script will detect automatically your settings and perform the actions
    2. The script will run only once when started. If needed to perform regular backups, use task scheduler to schedule a job that would call the script
    3. The script as is should be running locally on your dns server. If you want to execute the script from a remote machine, you will have to adapt the script
    4. The script should be working on Windows 2016 Server

    Hope this help
    Till next time
    See ya

Leave a Reply