Written to complement the VbScript version of this post. This collection of functions handles subnet maths in PowerShell.

The functions described here have been updated since posting this article. The updated functions are available as part of the script module Indented.NetworkTools.

Convert an IP to binary

This function uses System.Convert to change each octet of an IP address into it’s binary form. PadLeft is used to add leading zero’s if required.

Convert an IP to a 32-bit decimal

Allows conversion of an IP Address to an unsigned 32-bit integer.

Convert a decimal number or binary IP to a dotted IP

Used to switch a decimal or binary IP back to the more common dotted decimal format. The function uses a simple set of regular expressions to determine which format is presented.

Convert a subnet mask to a mask length

Occasionally it is desirable to calculate the subnet mask bit length. This can be done using the following.

Convert a mask length to a subnet mask

To a dotted decimal IP via binary and an unsigned 32-bit integer.

Calculate the subnet network address

The functions above can be used with along with a bitwise AND operation against an IP address and subnet mask to calculate the network address.

Note that this function includes calls to both ConvertTo-DottedDecimalIP and ConvertTo-DecimalIP.

Calculate the subnet broadcast address

The function is right at the bottom, the explanation is, of course, entirely optional.

Getting to the Broadcast Address is a bit more complicated than the Network Address. A Bitwise Or is executed against an Inverted Subnet Mask. For example, the Inverted form of is

Inverting the decimal value of the subnet mask can be performed using BNot, the Complement Operator (see Get-Help About_Comparison_Operators).

Unfortunately BNot only returns a signed 64-bit integer (in the range -9223372036854775808 to 9223372036854775807).

The first 32 bits have are 1 (feel free to count). This happens because of the implicit conversion between UInt32 and Int64. Those 32 leading 1’s must go; Back to Binary And.

The operation takes advantage of the implicit conversion between types to get [UInt32]::MaxValue and to an Int64 type. As a result, this is what BAnd did:

Where 1 is the Int64 value from -BNot, 2 is the implicit conversion of [Int32]::MaxValue to Int64, and 3 is the result of the And operation. Finally, the resulting value can be implicitly (or explicitly) converted back to UInt32.

A very long explanation for a very short function.


Putting the functions above to work, providing a summary of an IP address range.


Calculate each host address within the network range.



  1. This is beautiful. I have been doing some of this from scratch and you just saved me a lot of time.

    One thing I have noted however is that Int32 can’t handle some of the decimal values generated. Everything works very nicely if you use Int64 instead.


    • Thanks 🙂

      PowerShell 1? It may have some issues with the unsigned integers used by the script, everything was written under PowerShell 2. Otherwise if you happen to have examples of where it’s failing I’ll fix it 🙂


  2. Pingback: Episode 112 – Scripting Games 2010 Roundup with Ed Wilson and Joel Bennett « PowerScripting Podcast

  3. Great thanks for posting – you just saved me a whole load of pain!!

    I owe you a beer!




  4. These functions have proven supremely useful – I’ve automated a tedious firewall object provisioning process based on your work.. Thanks for sharing!

    Rather thank dot-sourcing, I’ve made a Module from the file by adding ” Export-ModuleMember -Function * ” and saving the script as a .psm1 file in the system Modules directory.


  5. I’m noticing a problem when I run the script with Powershell 1 in Windows 2003…

    Cannot convert value “4294966784” to type “System.Int32”. Error: “Value was either too large or too small for

    + (ConvertTo-DecimalIP $IP) -BAnd <<<<

    this occurs inside the Get-NetworkAddress function. each "ConvertTo-DecimalIP" function within Get-NetworkAddress get called successfully, but it fails right before it gets to the value to send to ConvertTo-DottedDecimalIP.

    I believe it has to do with the use of "-BAnd"


    • I can’t make it work as well for PowerShell 1, it needs to support Unsigned Integers and PowerShell 1 does not. That is, it must support System.UInt32, not just System.Int32.


  6. Pingback: Script for DHCP Scope - Admins Goodies

  7. Pingback: Indented! : More IPv4 subnet maths with PowerShell

  8. this is excellent. thank you


  9. Great functions here, would make a great module


  10. Great functions; extremely helpful for bulk IP management (split-scope exclusion range calculations). BTW — If you’re receiving the System.Int32 error described above [by Wes] then try type casting to [int64]. I had to do this in v2 just to perform arithmetic with some decimal-converted IPs.


  11. Pingback: Enumerate devices on a given subnet – powershell script « Blog of Kliment Andreev

  12. I’ve been tasked with assessing our Active Directory Sites and Subnets structure, and you have saved me an awful lot of trouble.

    One little thing, though – when I copied and pasted your code into both my PS editor (PowerGUI) and plain old Notepad, the line returns came out as spaces. This ended up combining a lot of lines that couldn’t be combined. I was able to split it up by searching for 4 spaces and replacing them with a CR+LF, but that then split up some of the hash tables. Anyway, I was eventually able to get it all working, but you might want to post this to CodePlex or some other repository that will retain your original formatting so that people who don’t know PowerShell well enough to clean up the joined (or split) lines can use this wonderful stuff.

    Thanks again for sharing your great work!


  13. Pingback: Network Discovery – Part 1 « The Surly Admin

  14. Excellent Post. Saved a lot time


  15. Excellent functions!
    Thanks for posting.


  16. Pingback: PS Fab:> PowerShell Blog - Subnet mask functions

  17. Danny McDermott

    Great functions and really useful. I found a bug when I tried them on my system with the ConvertTo-DottedDecimalIP Function. It kept throwing a ‘Cannot convert this format’ error.
    To rectify, i changed the switch statement that evaluated “d” to “d”

    Process {
    Switch -RegEx ($IPAddress) {
    “([01]{8}.){3}[01]{8}” {
    Return [String]::Join(‘.’, $( $IPAddress.Split(‘.’) | ForEach-Object { [Convert]::ToUInt32($_, 2) } ))
    “d” {
    $IPAddress = [UInt32]$IPAddress
    $DottedIP = $( For ($i = 3; $i -gt -1; $i–) {
    $Remainder = $IPAddress % [Math]::Pow(256, $i)
    ($IPAddress – $Remainder) / [Math]::Pow(256, $i)
    $IPAddress = $Remainder
    } )

    Thanks, Danny


  18. Hi, according to my understanding, the function ConvertTo-MaskLength does not calculate right. For example, when given the following Input: “” which is 16 bits the function Outputs “19”. I didn’t yet had the time to look what is wrong.

    Maybe you could have a look into it?

    thanks and with kind regards,



  19. Hi,

    I have found the error. Please exchange the lines within process section as follows:

    $Bits = “$( $SubnetMask.GetAddressBytes() | ForEach-Object { [Convert]::ToString($_, 2) } )” -Replace ‘ ‘
    $BitCount = [regex]::Matches($Bits,’1’).Count;
    Return $BitCount


    • I lost my web server a little while ago and had to re-import all the content. It looks like that process has broken a number of the examples, wiping out certain special characters (such as ). It will be fixed.


  20. Hi, Can you release this code under the Apache license? I would like to reuse it for a QA project. Please let me know.


    • Indented.Common and Indented.NetworkTools have been explicitly updated with a Copyright statement based on the ISC licence. This appears to be less restrictive than the Apache licence. Indented.NetworkTools contains all functions on this page (in updated form).

      Functions on this page are now also covered by the ISC licence, as stipulated here: http://www.indented.co.uk/licence/


  21. Dario Ribeiro

    The ConvertTo-DottedDecimalIP function was playing up for me with error “Cannot convert this format error”, the easy fix that worked for me was adding “\d” instead of “d” in the Switch -RegEx statement. Hope it helps.

    function ConvertTo-DottedDecimalIP {

    [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]

    process {
    Switch -RegEx ($IPAddress) {
    “([01]{8}.){3}[01]{8}” {
    return [String]::Join(‘.’, $( $IPAddress.Split(‘.’) | ForEach-Object { [Convert]::ToUInt32($_, 2) } ))
    “\d” {
    $IPAddress = [UInt32]$IPAddress
    $DottedIP = $( For ($i = 3; $i -gt -1; $i–) {
    $Remainder = $IPAddress % [Math]::Pow(256, $i)
    ($IPAddress – $Remainder) / [Math]::Pow(256, $i)
    $IPAddress = $Remainder
    } )

    return [String]::Join(‘.’, $DottedIP)
    default {
    Write-Error “Cannot convert this format”


Leave a Reply

Your email address will not be published. Required fields are marked *