{"id":54323,"date":"2009-02-24T21:17:00","date_gmt":"2009-02-24T21:17:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/02\/24\/hey-scripting-guy-how-can-i-create-dns-mail-exchanger-mx-records-and-have-a-text-file-generated-to-show-what-was-created\/"},"modified":"2009-02-24T21:17:00","modified_gmt":"2009-02-24T21:17:00","slug":"hey-scripting-guy-how-can-i-create-dns-mail-exchanger-mx-records-and-have-a-text-file-generated-to-show-what-was-created","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-create-dns-mail-exchanger-mx-records-and-have-a-text-file-generated-to-show-what-was-created\/","title":{"rendered":"Hey, Scripting Guy! How Can I Create DNS Mail Exchanger (MX) Records and Have a Text File Generated to Show What Was Created?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/h2>\n<p>Hey, Scripting Guy! We are adding some new Exchange Servers to our messaging infrastructure, and I want to create some new MX (Mail Exchanger) records in DNS. I do not want to to create these records manually because carpal tunnel is not my friend and manual creation tends to introduce errors. I like having a text file that shows exactly what was created. Is this something that can be scripted?<\/p>\n<p>&#8211; CI<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><\/p>\n<p>Hi CI,<\/p>\n<p>Ding! Tea time. Be back in 15. Ah, sweet relief: Some <a href=\"http:\/\/en.wikipedia.org\/wiki\/Gunpowder_tea\" target=\"_blank\">gun powder green tea<\/a> I brought back from my favorite shop in Munich, an <a href=\"http:\/\/en.wikipedia.org\/wiki\/Anzac_biscuit\" target=\"_blank\">ANZAC biscuit<\/a> I scored during <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/australia2008\/dispatch1.mspx\" target=\"_blank\">my last trip to Australia<\/a>. I have to ration these things out because they are impossible to find in Charlotte, North Carolina, in the United States. Don&#8217;t get me wrong; Charlotte is nice, but we don\u2019t have a huge selection of Anzac biscuits. Around here, when you ask for a biscuit, they give you what looks more like a scone, and you are very likely to end up with <a href=\"http:\/\/en.wikipedia.org\/wiki\/Biscuits_and_gravy\" target=\"_blank\">gravy all over it<\/a>. Sorry, CI. Another tangent. What was it you asked? Oh, yeah! You want to create some MX records via script. Can do. We will call our script <b>New-M<\/b><b>X<\/b><b>Record.ps1<\/b>.<\/p>\n<table class=\"dataTable\" id=\"EPD\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\">This week we are talking about DNS. For more information about DNS, you can refer to the Windows Server 2008 Networking and Network Access Protection (NAP) book in the <a href=\"http:\/\/www.microsoft.com\/learning\/en\/us\/Books\/10345.aspx\" target=\"_blank\">Windows Server 2008 Resource Kit<\/a>. There is also a chapter on scripting network services in the <a href=\"http:\/\/www.microsoft.com\/MSPress\/books\/authors\/auth9541.aspx\" target=\"_blank\">Windows PowerShell Scripting Guide<\/a>. A number of good VBScript examples are in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/network\/dns\/default.mspx\" target=\"_blank\">Script Center Script Repository<\/a>. The WMI DNS provider is documented here <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms682134(VS.85).aspx\" target=\"_blank\">on MSDN<\/a>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>A VBScript version of the <b>New-MXRecord.ps1<\/b> script can be seen in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/network\/dns\/records\/nwrevb02.mspx\" target=\"_blank\">Script Center Script Repository<\/a>. Without further ado,&nbsp;Here is <b>New-M<\/b><b>X<\/b><b>Record.ps1<\/b><b>:<\/b><\/p>\n<pre class=\"codeSample\">Function Check-Path($file)\n{\n Begin { Write-Host -Foregroundcolor DarkCyan \"Checking $file\" }\n Process {\n       If (-not(Test-Path -Path $file))\n     {\n      Throw \"$file does not exist\"\n     }\n }\n} #End Check-Path\nFunction Get-DnsServer\n{\n Begin {Write-Host -ForeGroundColor Cyan \"Obtaining local DNS Server information...\"}\n Process {\n  (Get-WmiObject -Class win32_networkadapterconfiguration`\n    -filter \"ipenabled =   $true\").DnsServerSearchOrder[0]\n } #end Process\n} #end Get-DnsServer\nFunction New-MXRecord($DnsServer,$File)\n{\n Begin { Write-Host -ForeGroundColor Green \"Creating MX records\"}\n Process {\n Import-CSV $File |\n Foreach-Object {\n([wmiclass]\"\\\\$DnsServer\\Root\\MicrosoftDNS:MicrosoftDNS_MxType\")`\n.CreateInstanceFromPropertyData($_.DnsServer,$_.Container,$_.Owner,$_.RecordClass,`\n$_.TTL,$_.Preference,$_.MailExchanger) |\nFormat-List -property RR\n  }\n }\n} #end New-MxRecord\n# *** entry point to script ***\n$File = \"C:\\ScriptingGuys\\mxrecords.csv\"\ncheck-path $File\n$DnsServer = Get-DnsServer\nNew-MxRecord -DnsServer $DnsServer -File $File\n<\/pre>\n<p>&nbsp;If we were not able to use a script, we would be stuck mousing around the GUI DNS tool. This is fine for one record, but for more than that, it gets pretty boring very quickly. Here\u2019s the GUI:<\/p>\n<p><img decoding=\"async\" height=\"400\" alt=\"Image of the GUI\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/february\/hey0224\/hsg-02-24-9-01.jpg\" width=\"361\" border=\"0\"><\/p>\n<p>&nbsp;<\/p>\n<p>The first thing we do is check the path to the CSV file that holds our MX record information. This function is similar to the one we used to check the path for our Office Access database during Access Week. We update the function by adding a <b>Begin<\/b> block to print out a status message. We then use the <b>Test-Path<\/b> cmdlet to see if the file exists. If it does not exist, we use the <b>Throw<\/b> statement to raise an error. This is similar to the <b>Err.Raise<\/b> method from VBScript.<\/p>\n<pre class=\"codeSample\">Function Check-Path($file\n{\n Begin { Write-Host -Foregroundcolor DarkCyan \"Checking $file\" }\n Process {\n       If (-not(Test-Path -Path $file))\n     {\n      Throw \"$file does not exist\"\n     }\n }\n} #End Check-Path\n<\/pre>\n<p>After we check for the existence of the CSV file, we need to find the information about the DNS server. This is the same function we used yesterday, and we will not discuss it today. Check out <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/feb09\/hey0223.mspx\" target=\"_blank\">yesterday\u2019s \u201cHey, Scripting Guy!\u201d article<\/a> for a detailed discussion of this&nbsp;function.<\/p>\n<pre class=\"codeSample\">Function Get-DnsServer\n{\n Begin {Write-Host -ForeGroundColor Cyan \"Obtaining local DNS Server information...\"}\n Process {\n  (Get-WmiObject -Class win32_networkadapterconfiguration`\n    -filter \"ipenabled =   $true\").DnsServerSearchOrder[0]\n } #end Process\n} #end Get-DnsServer\n<\/pre>\n<p>Now we come to the <b>New-MXRecord<\/b> function. This function will be used to create the new MX Records in DNS. The function accepts two parameters: the first parameter is the DNS Server to connect to, and the second is the path to the CSV file that contains our MX record information. To create a function we use the <b>Function<\/b> keyword and give it a name. This is seen here:<\/p>\n<pre class=\"codeSample\">Function New-MXRecord($DnsServer,$File){<\/pre>\n<p>Then we use the <b>Begin<\/b> parameter to print a progress message that tells the user we are creating the MX records. This is seen here:<\/p>\n<pre class=\"codeSample\">Begin { Write-Host -ForeGroundColor Green \"Creating MX records\"}<\/pre>\n<p>Now we enter the <b>Process<\/b> section of the function. The first thing we do is use the <b>Import-C<\/b><b>SV<\/b> cmdlet to import the CSV file.<\/p>\n<pre class=\"codeSample\">Process {\nImport-CSV $File |\n<\/pre>\n<p>We take the CSV content and feed it to the <b>ForEach-Object<\/b> cmdlet, which allows us to work with one line of data at a time as it comes across the pipeline. This is a very efficient arrangement because the CSV file could be huge otherwise. Rather than using up a lot of memory to store the contents of the CSV file in memory and spend all that time waiting for the entire contents of the file to be read from the file system, we are able to go to work on the CSV file as soon as the first line has been read.<\/p>\n<pre class=\"codeSample\">ForEach-Object {<\/pre>\n<p>We use the <b>WMIClass<\/b> type accelerator to allow us to create a new MX record. It is efficient to work with this class directly. This is similar to using the <b>Get<\/b> method from the <b>Swbe<\/b><b>m<\/b><b>Services<\/b> object like we did in VBScript days. In fact, you can compare this to the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/network\/dns\/records\/nwrevb02.mspx\" target=\"_blank\">Create MX Record<\/a> script. The <b>[wmiclass]<\/b> type accelerator takes the path to the <b>Micr<\/b><b>o<\/b><b>softDNS_MxType<\/b> WMI class we want to use. It is on our remote DNS server, in the <b>root\\MicrosoftDNS<\/b> WMI namespace, and the name is <b>MicrosoftDNS_MxType<\/b>. This part is seen here:<\/p>\n<pre class=\"codeSample\">[wmiclass]\\\\$DnsServer\\Root\\MicrosoftDNS:MicrosoftDNS_MxType<\/pre>\n<p>The next thing we do is call the <b>CreateInstanceFromPropertyData<\/b> method. We give it the name of the DNS Server, the container in which to create the DNS record, the owner and class of the DNS record, the time to live value, a weighted preference, and the mail exchanger to use. These properties are all described <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms682702(VS.85).aspx\" target=\"_blank\">on MSDN<\/a>. All of the <b>Micr<\/b><b>o<\/b><b>softDNS_???Type<\/b> WMI classes have a <b>CreateInstanceFromPropertyData<\/b> method. The method signature is similar between all of the WMI classes in this namespace, the only differences being peculiar to the individual DNS record type. This section of the code is seen&nbsp;here:<\/p>\n<pre class=\"codeSample\">([wmiclass]\"\\\\$DnsServer\\Root\\MicrosoftDNS:MicrosoftDNS_MxType\")`\n.CreateInstanceFromPropertyData($_.DnsServer,$_.Container,$_.Owner,`\n$_.RecordClass,$_.TTL,$_.Preference,$_.MailExchanger) |\n<\/pre>\n<p>The <b>CreateInstanceFromPropertyData<\/b> method call returns an instance of <b>Micr<\/b><b>o<\/b><b>softDNS_RTType<\/b> class. We display the information from that class by using the <b>Format-List<\/b>&nbsp;:<\/p>\n<pre class=\"codeSample\">Format-List -property RR\n  }\n }\n} #end New-MxRecord\n<\/pre>\n<p>The formatted output from the <b>Format-List<\/b> cmdlet is seen here:<\/p>\n<p><img decoding=\"async\" height=\"248\" alt=\"Image of the formatted output from the cmdlet\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/february\/hey0224\/hsg-02-24-9-02.jpg\" width=\"500\" border=\"0\"><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>We now arrive at the entry point to the script. We assign the path to the CSV file, check the path to the file, obtain the DNS server information, and call the <b>New-MxRecord<\/b> functionfunction:<\/p>\n<pre class=\"codeSample\">$File = \"C:\\ScriptingGuys\\mxrecords.csv\"\ncheck-path $File\n$DnsServer = Get-DnsServer\nNew-MxRecord -DnsServer $DnsServer -File $File\n<\/pre>\n<p>Woohoo! It&#8217;s done. If you don&#8217;t believe me, take a look in the MMC, as shown here:<\/p>\n<p><img decoding=\"async\" height=\"317\" alt=\"Image of the MMC\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/february\/hey0224\/hsg-02-24-9-03.jpg\" width=\"500\" border=\"0\"><\/p>\n<p>Well, CI, that was cool. There is nothing more fun than writing a script that reads a CSV file and creates real live honest to goodness MX records in DNS. Certainly this is not something you will need to do every week, unless you are in consulting and you go around setting up DNS servers and doing a lot of Exchange work. But as I mentioned earlier in the article, the methodology is extremely similar amongst all the <b>MicrosoftDNS<\/b> record types. This means you can setup your DNS server from a script as easily as we created the three MX records\u2014and that is pretty sweet. Speaking of sweet, join us again tomorrow as DNS week continues.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! We are adding some new Exchange Servers to our messaging infrastructure, and I want to create some new MX (Mail Exchanger) records in DNS. I do not want to to create these records manually because carpal tunnel is not my friend and manual creation tends to introduce errors. I like having a [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[188,27,37,3,45],"class_list":["post-54323","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-dns-server","tag-exchange","tag-networking","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! We are adding some new Exchange Servers to our messaging infrastructure, and I want to create some new MX (Mail Exchanger) records in DNS. I do not want to to create these records manually because carpal tunnel is not my friend and manual creation tends to introduce errors. I like having a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54323","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54323"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54323\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}