3

I'm working with the Get-DhcpServerv4Scope cmdlet and am looking to pull multiple scopes into a variable with the -scopeid switch.

Get-DhcpServerv4Scope -scopeid 10.1.0.0,10.1.1.0 

However if I do:

$IP = "10.2.0.0,10.1.0.0"
Get-DhcpServerv4Scope -scopeid $IP

I get the error:

Get-DhcpServerv4Scope : Cannot process argument transformation on parameter 'ScopeId'. Cannot convert value "10.2.0.0,10.1.0.0" to type "System.Net.IPAddress[]". Error: "Cannot convert value "10.2.0.0,10.1.0.0" to type "System.Net.IPAddress". Error: "An invalid IP address was specified.""

Anyone have an idea how to get do this conversion?

Edit: Here's the script I'm trying to fit this into. I'd like to have a way to point this script at a server and it rebuilds all scopes. right now I output the scopes in a tab delimited file, then copy & paste them into the Get-dhcpv4scope to store all of the scopes in one variable. I'm open to any suggestions:

#GetScopes
$ScopeExclusions = Get-DhcpServerv4ExclusionRange
[string]$ScopesCSV=Get-DhcpServerv4Scope | Select ScopeID | convertto-
csv -notypeinformation
$ScopesCSV.replace('" ', ',').replace('"', '').replace('ScopeId,', '') 
| out-file c:\users\aturner\desktop\csv.txt
**Copy contents from file to clipboard**
$Scopes=Get-DhcpServerv4Scope -scopeid *PasteScopeCSVListHere* | select 
ScopeId,Name,Description,SubnetMask,StartRange,EndRange,LeaseDuration

#Delete Scopes
$Scopes | % { Remove-DhcpServerv4Scope -ScopeId $_.scopeid -force}

#Rebuild Scopes
$Scopes | % {Add-DhcpServerv4Scope -Name $_.name -Description 
$_.description -SubnetMask $_.SubnetMask -StartRange $_.StartRange -
EndRange $_.EndRange -LeaseDuration 8.00:00:00 }
$ScopeExclusions | % {Add-DHCPServerv4ExclusionRange -ScopeID $_.ScopeID -
StartRange $_.StartRange -EndRange $_.EndRange}

New Code:

#GetScopes
$ScopeExclusions = Get-DhcpServerv4ExclusionRange
[string]$ScopesArray=Get-DhcpServerv4Scope | Select ScopeID | convertto-csv -notypeinformation
$ScopesCSV=$ScopesArray.replace('" ', ',').replace('"', '').replace('ScopeId,', '') 
$ScopeReservations = Get-DhcpServerv4Scope | Get-DhcpServerv4Reservation | select *
$Scopes=Get-DhcpServerv4Scope -scopeid $ScopesCSV.Split(',') | select ScopeId,Name,Description,SubnetMask,StartRange,EndRange,LeaseDuration

#Delete Scopes
$Scopes | % { Remove-DhcpServerv4Scope -ScopeId $_.scopeid -force}

#Rebuild Scopes
$Scopes | % {Add-DhcpServerv4Scope -Name $_.name -Description $_.description -SubnetMask $_.SubnetMask -StartRange $_.StartRange -EndRange $_.EndRange -LeaseDuration 8.00:00:00 }
$ScopeReservations | % {Add-DhcpServerv4Reservation -ScopeID $_.ScopeID -IPAddress $_.IPAddress -ClientId $_.ClientID -Description $_.Description -Name $_.Name -Type $_.Type}
New 
Mark Wragg
  • 236
  • 2
  • 12
Adam Turner
  • 31
  • 1
  • 3

3 Answers3

4
$IPobj = $IP | ConvertFrom-Csv -Delimiter "," -Header "ip1", "ip2"
Get-DhcpServerv4Scope -scopeid $IPobj.ip1, $IPobj.ip2

However your main problem is that $IP is a string, while when you manually pass 10.1.0.0,10.1.1.0 as parameters you are actually passing 2 strings.

You would be better off creating $IP as an array:

$IP = @("10.2.0.0", "10.1.0.0")
Get-DhcpServerv4Scope -scopeid $IP[0],$IP[1]

This way you can script / loop through the array if you have multiple scopes.

Adam asked how to do this dynamically and although I don't know where are we getting "10.2.0.0" and "10.1.0.0" from, you'll just need to keep populating the $IP array with all the scope IDs you need to check, then loop as follows:

foreach ($scopeid in $IP) { Get-DhcpServerv4Scope -scopeid $scopeid }

The above code goes through each entry in $IP, temporarily storing it in $scopeid and using it as parameter to call the Get-DhcpServerv4Scope cmdlet.

Mark Wragg
  • 236
  • 2
  • 12
Pedro Perez
  • 6,202
  • 1
  • 11
  • 11
  • Any way to handle this dynamically? I'd like to use this against different DHCP servers wither varying scopes. – Adam Turner Apr 19 '17 at 00:15
  • Yes, definitely. You can populate the array with more scopes as needed, then we could loop in a foreach and call Get-DhcpServerv4Scope for each of them ;) - how do you learn the scope id's? manually? or do you get them from a file / another cmdlet / etc? Either way, I'll update the answer with the loop too. – Pedro Perez Apr 19 '17 at 00:17
  • I updated the post to show the full code I'm using right now. I'm looking to replace the whole "create CSV of subnets, C&P into -subnetid switch" part with an automated approach. – Adam Turner Apr 19 '17 at 00:22
  • Use a foreach ($scope in (Get-DhcpServerv4Scope | Select ScopeID)) to use $scope as parameter on "Get-DhcpServerv4Scope -scopeid *PasteScopeCSVListHere*" and save the output to $Scopes, but make sure $Scopes is an array, so inside the same foreach use $Scopes+=$scope to populate the array :) – Pedro Perez Apr 19 '17 at 00:30
3

There's a native [ipaddress] cast that should make this pretty easy.

$csvIPs = "10.2.0.0,10.1.0.0"
$IP = $csvIPs.Split(',') | %{ [ipaddress]$_ }
Get-DhcpServerv4Scope -scopeid $IP

I don't have a test system with DHCP running at the moment, but I'd guess you might not even need the [ipaddress] cast and could just get by with the .Split(',') because Powershell should be smart enough to take the individual IP strings and convert them for you just like it did in your first code snippet.

$IP = "10.2.0.0,10.1.0.0"
Get-DhcpServerv4Scope -scopeid $IP.Split(',')
Ryan Bolger
  • 16,755
  • 4
  • 42
  • 64
2

Let's answer the immediate question at hand: why does your first example work but your second example doesn't. Let's start with why the first one DOES work. It involves PowerShell's different Parsing Modes.

Your First Example (works):

Get-DhcpServerv4Scope -scopeid 10.1.0.0,10.1.1.0

In your first example, PowerShell is in Command Parsing Mode because your line begins with a command. In Command Mode, PowerShell will automatically quote arguments to a command for you, since quoting everything all the time when working in your shell would be really annoying! This means it is quoting your unquoted IP address values for you, turning them into strings and the ',' (Comma operator) is combining the two strings into an array. Since the Parameter is IPAddress[] (array of IPAddress object), it tries to cast your strings to IPAddress, and it succeeds, since they are individual entries in an array and IPAddress knows how to parse 1 string in that format and creates an IPAddress object with it. At least, I'm 90% sure a combination of those 3 things (comma/array operator, command parsing mode, and casting) is why that works.

NOTE: More specifically command mode may be called argument mode (as in arguments to a command), the other mode being called expression mode. In my older PowerShell book I just saw it called command mode, but the current doc talks about argument mode.

From the doc:

In argument mode, each value is treated as an expandable string unless it begins with one of the following special characters: dollar sign ($), at sign (@), single quotation mark ('), double quotation mark ("), or an opening parenthesis (().

Your Second Example:

$IP = "10.2.0.0,10.1.0.0"
Get-DhcpServerv4Scope -scopeid $IP

In the first line, you're just creating a string, "10.2.0.0,10.1.0.0". PowerShell is going to let you make that string however you want and leaves it alone. Even if you omitted the double quotes, you'd notice that PowerShell won't do the same thing as Example 1...and this is because it's in Expression Mode and won't auto-quote your strings for you in this mode. When I try that I don't get anything assigned. You probably saw that as well.

In the second line of your example, there's nothing special PowerShell is going to do - it's just a string that happens to have a comma in it - it's not going to inspect and modify your string, it's going to just pass it along, where it will fail to parse into an IPAddress because it's not the valid form and whatever parse method IPAddress has can only handle a single IP Address and not a comma separated string of them.

This part can be corrected by adjusting the line as Pedro suggested into an array. e.g.:

$IP = @("10.2.0.0","10.1.0.0")

It can then be passed directly:

Get-DhcpServerv4Scope -ScopeId $IP

However, you didn't specify whether you're intending to only process some scopes. I don't see a comment about you editing your CSV to exclude certain scopes (or in your code), so you could instead skip ALL of this in that case and just call Get-DhcpServerv4Scope without any -ScopeId argument and it will return all scopes. You could then skip all this to CSV and back work.

It's unclear to me the reason for the scope rebuilding, since it seems like you're potentially discarding existing 8 day leases (if they have the same as what it was before, maybe they were set to be quite short first) and could get address conflicts if the server re-assigns it before clients with those leases expire. Maybe I'm missing something. Just take care with whatever it is your end goal is here, and good luck!

Joshua McKinnon
  • 1,431
  • 1
  • 14
  • 26