Errors in script to Enable DNS Zone Transfers

This topic contains 7 replies, has 3 voices, and was last updated by  Ed O’Connor 1 year, 11 months ago.

  • Author
    Posts
  • #32579

    Ed O’Connor
    Participant

    Hi all,

    I am trying to writ a script that will look at a DNS server, identify all the Zones, see if Dynamic Update is set to "NonsecureandSecure", and if any zone are not set to that set it.

    This is what I have come up with:

    *****Begin Script******

    #Script to identify all zones on a DNS server and enable zone transfers
    
    Start-Transcript .\ZoneTransferInfo.txt
    
    Get-DNSServerZone |ft -Property ZoneName, ZoneType, DynamicUpdate
    
    Get-DNSServerZone | where DynamicUpdate -eq 'None' |ft -Property ZoneName, ZoneType, DynamicUpdate
    
    $NoDynamicUpdate = Get-DNSServerZone | where DynamicUpdate -eq 'None' | FT ZoneName
    
    foreach ($item in $NoDynamicUpdate) 
    	{Set-DNSServerPrimaryZone -Name "$item" -DynamicUpdate "NonsecureandSecure" -PassThru}
    
    Get-DNSServerZone |ft -Property ZoneName, ZoneType, DynamicUpdate
    
    Stop-Transcript
    
    

    *****End Script*****

    I am getting a few errors that I am having trouble working through. When I run the foreach line I get the following error:

    Set-DNSServerPrimaryZone : The zone Microsoft.PowerShell.Commands.Internal.Format.FormatEndData was not found on
    server LAB-DC02.
    At line:2 char:2
    + {Set-DNSServerPrimaryZone -Name "$item" -DynamicUpdate "NonsecureandSecure"
    -Pas ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~~~
    + CategoryInfo : ObjectNotFound: (Microsoft.Power...t.FormatEndDa
    ta:root/Microsoft/...rverPrimaryZone) [Set-DnsServerPrimaryZone], CimExcep
    tion
    + FullyQualifiedErrorId : WIN32 9601,Set-DnsServerPrimaryZone

    Any help/suggestion is greatly appreciated.

  • #32581

    Don Jones
    Keymaster

    You've got some Formatting data creeping in somewhere you don't want it. Understand that, once you run a format command like FT, you're making the data useless for anything but screen display. I suspect this is your problem root:

    $NoDynamicUpdate = Get-DNSServerZone | where DynamicUpdate -eq 'None' | FT ZoneName

    $noDynamicUpdate doesn't contain what you think it does. It contains a formatted table, with headers and columns and stuff. It's no longer data. You should stop it with the Format-Table stuff, really. This is probably also a problem:

    Get-DNSServerZone | where DynamicUpdate -eq 'None' |ft -Property ZoneName, ZoneType, DynamicUpdate

    See https://powershell.org/kb/format-to-the-right/ for a general explanation, but as a rule, make sure you understand why Format-Table and Select-Object are different.

  • #32582

    Ed O’Connor
    Participant

    Thank You Don, that does make sense but brings up a whole new set of problems for me.

    When I remove the | FT ZoneName the array now contains to much data. All I want in the array that I call with the next line is the ZoneName as that is the information required by the 'Get-DNSServerPrimaryZone' command so I can set the dynamic update setting.

    How can I go about only outputting the ZoneNames informaton into the Array? I have tried looking it up and am experimenting with different syntax/commands/things I find but can't seem to limit the array to just that information.

    Thanks again!

  • #32583

    Curtis Smith
    Participant

    Last paragraph of Don's response:

    See https://powershell.org/kb/format-to-the-right/ for a general explanation, but as a rule, make sure you understand why Format-Table and Select-Object are different.

    Specifically look into Select-Object

  • #32584

    Don Jones
    Keymaster

    Ed, Select-Object is the correct way to grab only the properties you want, while leaving a usable object that has usable data. In almost every case where you've used Format-Table, Select-Object is actually correct.

  • #32585

    Ed O’Connor
    Participant

    Yes, I was looking at that and made the following change:

    
    $NoDynamicUpdate = Get-DNSServerZone | select-object ZoneName, DynamicUpdate | where DynamicUpdate -eq 'None'
    
    

    This give me a output like:

    ZoneName DynamicUpdate
    —————- ————————
    0.in-addr.arpa None
    127.in-addr.arpa None

    All I need/want is the info under ZoneName:

    0.in-addr.arp
    127.in-addr.arpa
    and etc...

    As that is all that is needed for the:

    Set-DNSServerPrimaryZone -Name **ZoneName**

    field.

    I can't figure out how to just get that information in a array for the:

    foreach ($item in $NoDynamicUpdate) 
    	{Set-DNSServerPrimaryZone -Name "$item" -DynamicUpdate "NonsecureandSecure" -PassThru}
    

    command to use.

    I really appreciate all the guidance and information. I am learning alot

  • #32589

    Don Jones
    Keymaster

    So, be patient with me in case I'm not understanding where you're stuck :).

    I want to make sure you're not confusing the data that PowerShell has in memory, versus what PowerShell displays on the screen. For example, $NoDynamicUpdate doesn't actually contain the "ZoneName," "DynamicUpdate" headers, or the dashes. Those headers are added by an implicit call to Format-Table when you attempt to display the data. As the data sits in the variable, however, those headers don't exist. $NoDynamicUpdate[0] would give me the first object ("row"), and $NoDynamicUpdate[0].ZoneName is the ZoneName property ("column") from that first object.

    So in your ForEach loop, $item is one ROW from $NoDynamicUpdate. $item.ZoneName would be the ZoneName property from that object.

    -Name "$($item.ZoneName)"

    Might be what you're after. And just to make sure we're correct on terminology:

    $NoDynamicUpdate is a "collection," not an array. $item will consist of one "object" at a time, and ZoneName is a "property" of that object.

    Now, let's go a different direction. You could also have done this:

    $NoDynamicUpdate = Get-DNSServerZone | 
    where DynamicUpdate -eq 'None' |
    select -expand ZoneName
    
    foreach ($zonename in $nodynamicupdate) {
    Set-DNSServerPrimaryZone -Name "$zonename" -DynamicUpdate "NonsecureandSecure" -PassThru
    }
    

    Notice first that I used Where-Object prior to Select-Object. Always filter as far to the beginning of the command line as possible, for efficiency. Then, I used Select-Object to extract the only information I needed. The result is just a bunch of zone names – it isn't a complex object with multiple properties anymore. I "pulled" the zone names out of the ZoneName properties. The result is that $NoDynamicUpdate is an array of strings, rather than being a collection of objects.

    Even when you use Select to just pick one property, you still get output that is objects. Those objects just only have one property. Understanding the difference between objects, which are a data structure that contains values, and simple values like strings, is a key part of conquering PowerShell.

    Really, as a total plug, get "Learn Windows PowerShell in a Month of Lunches." It absolutely walks you through all of this. What you're running into is what **every** PowerShell newcomer runs into, and the book's designed to mitigate head-slamming-into-wall moments :).

  • #32590

    Ed O’Connor
    Participant

    Thank You very much, that got me going! I am going to grab that book you recommended and appreciate your patience with me.

You must be logged in to reply to this topic.