3

I am trying to Resolve some DNS records using PowerShell. All of the Resolve-DnsName methods work below with the exception of the one where I try to append "owa." to the beginning of the domain name. The latest error I get is "cannot validate argument on parameter name". I have tried various combinations with no luck (i.e. owa.$Domain.Name). What is the proper way to concatenate the values to achieve a successful DNS resolution?

$Domain = New-Object System.Object
$Domain | Add-Member -type NoteProperty -name MXRecord -value $MXQuery
$Domain | Add-Member -type NoteProperty -name Name -value "mydomain.com"
$MXQueryRecord = Resolve-DnsName $Domain.Name -type MX -Server 8.8.8.8
$OWAQuery = Resolve-DnsName $("owa.")-$($Domain.Name) -type CNAME -Server 8.8.8.8
$TXTQuery = Resolve-DnsName $Domain.Name -type TXT -Server 8.8.8.8
$NSQuery = Resolve-DnsName $Domain.Name -type NS -Server 8.8.8.8

$Queries =$($MXQuery,$OWAQuery,$TXTQuery,$NSQuery)
Bill Greer
  • 3,046
  • 9
  • 49
  • 80

2 Answers2

3

Use (...) to pass an expression's value / command's output as a command argument:

Resolve-DnsName ("owa." + $Domain.Name) -type CNAME -Server 8.8.8.8

Note: $(...), the subexpression operator, is only needed if what you're trying to pass comprises multiple statements. @(...), the array-subexpression operator, is only needed if you need to guarantee that the output is treated as an array even if only a single object is output.

(...), $(...), @(...) have the advantage of working with any data type, not just strings.

Alternatively, if what you're passing is a string value (as in this case), you can use string expansion (interpolation), as shown in Drako's answer.


As for what you tried:

$("owa.")-$($Domain.Name)

is parsed as two arguments by PowerShell:

  • Subexpression $("owa."), which evaluates to string literal owa.
  • Expandable string -$($Domain.Name), which evaluates to -<domain-name> (evaluation as an expandable string means that is evaluated the same way it would if you explicitly double-quoted that token ("-$($Domain.Name)")).

It's not always obvious when PowerShell breaks a compound token into multiple arguments; the behavior is summarized here.
To learn about how unquoted tokens are parsed as arguments in general, see this answer.

Note that if you had double-quoted your entire token ("$("owa.")-$($Domain.Name)"), your command would have worked too (but there'd be no need to embed a string literal via $(...)).
To learn more about expandable strings (string interpolation), see this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • you don't need concatenation that just unnecessary consumes extra (even very little in this case) CPU power. – Drako Dec 20 '18 at 14:44
  • 1
    @Drako fairly certain a subexpression is slower, but none of this matters when dealing with strings of small sets – Maximilian Burszley Dec 20 '18 at 14:48
  • @Drako: I doubt that that's a real-world concern, and, like TheIncorrigible1, my guess is that string interpolation is _slower_. That said, string interpolation is a viable alternative in this case, so I've added a link to your answer. I've chosen to showcase `(...)`, because it works with _any_ type of argument, not just _strings_. – mklement0 Dec 20 '18 at 14:49
  • I have not done such tests for this in PowerShell so will not argue :) . (have done similar tests in C++ and Python; there my approach makes less CPU instructions, so I assume same here but obviously my guess can be wrong as PS parses strings differently :) ) – Drako Dec 20 '18 at 14:56
  • @Drako: I took a quick look, but let me preface the next comment by saying that this won't matter in the real world, and **the method you pick should _not_ be chosen based on performance considerations - instead, decide based on data-type needs and readability**. – mklement0 Dec 20 '18 at 15:21
  • @Drako: On my single-core W10 VM with Windows PowerShell v5.1, expandable strings (`"owa.-$($Domain.Name)"`) are _marginally_ slower - again, it won't matter in the real world. Test command (averages 100,000 runs): `$domain = @{ Name = 'example.org' }; Time-Command { Write-Output ("owa." + $Domain.Name) }, { Write-Output "owa.-$($Domain.Name)" } -Count 1e5`. The `Time-Command` function can be found [here](https://gist.github.com/mklement0/9e1f13978620b09ab2d15da5535d1b27). – mklement0 Dec 20 '18 at 15:22
  • 1
    Thanks for info. I'll take it into account and its not that weird knowing that PS has very complex string parsing mechanism. – Drako Dec 21 '18 at 08:27
3

Try to write it like this

$OWAQuery = Resolve-DnsName "owa.-$($Domain.Name)" -type CNAME -Server 8.8.8.8

(if I correctly understood that it should look as: owa.-somedomainname; because dash seems extra so just remove it if unnecessary)

Drako
  • 773
  • 10
  • 22