<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://powershell.com/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Dreaming in PowerShell : cast</title><link>http://powershell.com/cs/blogs/tobias/archive/tags/cast/default.aspx</link><description>Tags: cast</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Creating IP Ranges (and other type magic)</title><link>http://powershell.com/cs/blogs/tobias/archive/2011/02/20/creating-ip-ranges-and-other-type-magic.aspx</link><pubDate>Sun, 20 Feb 2011 21:20:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:9438</guid><dc:creator>Tobias</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://powershell.com/cs/blogs/tobias/rsscomments.aspx?PostID=9438</wfw:commentRss><comments>http://powershell.com/cs/blogs/tobias/archive/2011/02/20/creating-ip-ranges-and-other-type-magic.aspx#comments</comments><description>&lt;p&gt;Recently I needed to create a range of IP addresses. No big deal, you think? Well, if it is just a small segment, then it *is* easy stuff:&lt;/p&gt;
&lt;div class="pscode"&gt;1..255 | &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Foreach-Object&lt;/span&gt;&lt;/span&gt; { &lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;quot;192.168.2.$_&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;/div&gt;
&lt;p&gt;But what if you need larger segments? &lt;/p&gt;
&lt;h3&gt;Type Conversion Magic&lt;/h3&gt;
&lt;p&gt;Ok, you &lt;em&gt;could&lt;/em&gt; use nested loops. However, there&amp;#39;s also a &lt;strong&gt;type&lt;/strong&gt; that represents IP addresses. It is called &lt;strong&gt;System.Net.IPAddress&lt;/strong&gt;, and it can &lt;strong&gt;turn a string into an IP address&lt;/strong&gt;. It even calculates the decimal value (check out property &lt;em&gt;Address&lt;/em&gt;), and you can also convert a decimal value back into an IP address:&lt;/p&gt;
&lt;div class="pscode"&gt;PS &amp;gt; [&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]&lt;span style="color:#800000;"&gt;&lt;span class="string"&gt;&amp;#39;192.168.2.1&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Address : 16951488&lt;br /&gt;AddressFamily : InterNetwork&lt;br /&gt;ScopeId :&lt;br /&gt;IsIPv6Multicast : False&lt;br /&gt;IsIPv6LinkLocal : False&lt;br /&gt;IsIPv6SiteLocal : False&lt;br /&gt;IPAddressToString : 192.168.2.1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PS &amp;gt; [&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]16951488&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Address : 16951488&lt;br /&gt;AddressFamily : InterNetwork&lt;br /&gt;ScopeId :&lt;br /&gt;IsIPv6Multicast : False&lt;br /&gt;IsIPv6LinkLocal : False&lt;br /&gt;IsIPv6SiteLocal : False&lt;br /&gt;IPAddressToString : 192.168.2.1&lt;/div&gt;
&lt;p&gt;Now, since IP addresses really are just 32bit numeric values, this conversion is doing an amazing thing when you start thinking about it: it &lt;strong&gt;breaks up the decimal into its byte parts&lt;/strong&gt;.&amp;nbsp;Breaking up a number in its &lt;strong&gt;High/Low-part&lt;/strong&gt;&amp;nbsp;something needed very often, and most of the time people are coding confusing amounts of math into their scripts to do just that.&lt;/p&gt;
&lt;h3&gt;Breaking Up Decimals in Low-/High-Bytes&lt;/h3&gt;
&lt;p&gt;So the first thing I want to do is use the &lt;strong&gt;System.Net.IPAddress&lt;/strong&gt; type to &lt;strong&gt;break up any decimal into its low/high bytes&lt;/strong&gt;. I created a pretty small function called &lt;strong&gt;ConvertTo-HighLow&lt;/strong&gt; which you can &lt;a target="_blank" href="http://powershell.com/cs/media/p/9434.aspx"&gt;download here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="pscode"&gt;&lt;span class="keyword"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;&lt;/span&gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;ConvertTo-HighLow&lt;/span&gt;&lt;/span&gt;(&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$number&lt;/span&gt;&lt;/span&gt;) {&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$v&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; [&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Version&lt;/span&gt;&lt;/span&gt;][&lt;span class="datatype"&gt;&lt;span style="color:#0000ff;"&gt;String&lt;/span&gt;&lt;/span&gt;]([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$number&lt;/span&gt;&lt;/span&gt;) &lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$o&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; 1 | &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Select-Object&lt;/span&gt;&lt;/span&gt; Low, High, Low32, High32&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$o&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Low&lt;/span&gt;&lt;/span&gt;, &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$o&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;High&lt;/span&gt;&lt;/span&gt;, &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$o&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Low32&lt;/span&gt;&lt;/span&gt;, &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$o&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;High32&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$v&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Major&lt;/span&gt;&lt;/span&gt;, &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$v&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Minor&lt;/span&gt;&lt;/span&gt;, &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$v&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Build&lt;/span&gt;&lt;/span&gt;, &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$v&lt;/span&gt;&lt;/span&gt;.&lt;span style="color:#8b4513;"&gt;&lt;span class="method"&gt;Revision&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#800080;"&gt;&lt;span class="var"&gt;$o&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;
&lt;p&gt;It accepts any &lt;strong&gt;unsigned&amp;nbsp;64bit&lt;/strong&gt; number and returns &lt;strong&gt;its four bytes&lt;/strong&gt; like this:&lt;/p&gt;
&lt;div class="pscode"&gt;PS &amp;gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;ConvertTo-HighLow&lt;/span&gt;&lt;/span&gt; 255&lt;br /&gt;&lt;br /&gt;Low High Low32 High32&lt;br /&gt;&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;---&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;----&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;-----&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&lt;span class="op"&gt;------&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;255 0 0 0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PS &amp;gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;ConvertTo-HighLow&lt;/span&gt;&lt;/span&gt; 256&lt;br /&gt;&lt;br /&gt;Low High Low32 High32&lt;br /&gt;&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;---&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;----&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;-----&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&lt;span class="op"&gt;------&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;0 1 0 0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PS &amp;gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;ConvertTo-HighLow&lt;/span&gt;&lt;/span&gt; 52176537&lt;br /&gt;&lt;br /&gt;Low High Low32 High32&lt;br /&gt;&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;---&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;----&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;-----&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&lt;span class="op"&gt;------&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;153 38 28 3&lt;/div&gt;
&lt;p&gt;Here is what I did: I &lt;strong&gt;converted the number&lt;/strong&gt; to an &lt;strong&gt;IP address&lt;/strong&gt;. This did all the complex math by converting the number into four octets. Next, I &lt;strong&gt;converted the string IP&lt;/strong&gt; address into a &lt;strong&gt;System.Version&lt;/strong&gt; type. A version has four numbers, just like an IP address, so now I was able to create a new object (using the &lt;strong&gt;Select-Object trick&lt;/strong&gt;) with the properties I needed and add the byte values to the appropriate properties of my return object - done.&lt;/p&gt;
&lt;p&gt;If you just need the low or high byte of a decimal, you could also boil it down to this:&lt;/p&gt;
&lt;div class="pscode"&gt;PS &amp;gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$low&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; ([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]15672).&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;GetAddressBytes&lt;/span&gt;&lt;/span&gt;()[0]&lt;br /&gt;PS &amp;gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$high&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; ([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]15672).&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;GetAddressBytes&lt;/span&gt;&lt;/span&gt;()[1]&lt;br /&gt;PS &amp;gt; &lt;span style="color:#800080;"&gt;&lt;span class="var"&gt;$low&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;56&lt;br /&gt;PS &amp;gt; &lt;span style="color:#800080;"&gt;&lt;span class="var"&gt;$High&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;61&lt;br /&gt;PS &amp;gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$high&lt;/span&gt;&lt;/span&gt;&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;*&lt;/span&gt;&lt;/span&gt;256 &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;+&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#800080;"&gt;&lt;span class="var"&gt;$low&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;15672&lt;/div&gt;
&lt;h3&gt;Creating IP Address Ranges&lt;/h3&gt;
&lt;p&gt;Now that this worked perfectly, let&amp;#39;s &lt;strong&gt;create IP address ranges&lt;/strong&gt;. Here is the scoop: if every ip address is just a (large) decimal number, then why not convert start and end ip address into such a number and loop through that range? Each number could then be converted back into a valid IP address!&lt;/p&gt;
&lt;p&gt;Sounds cool, BUT. &lt;strong&gt;IP addresses organize bytes in an unusual way&lt;/strong&gt;. Turns out that the lowest byte represents the first octet. So if you counted up, you would not get consecutive ip address ranges.&lt;/p&gt;
&lt;p&gt;The solution is simple, though. Just &lt;strong&gt;reverse the octets&lt;/strong&gt; before you convert them, create the numeric range, and &lt;strong&gt;reverse them back&lt;/strong&gt;. Here is the function &lt;strong&gt;New-IPRange&lt;/strong&gt; (&lt;a target="_blank" href="http://powershell.com/cs/media/p/9437.aspx"&gt;which you can also download here&lt;/a&gt;):&lt;/p&gt;
&lt;div class="pscode"&gt;&lt;span class="keyword"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;&lt;/span&gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;New-IPRange&lt;/span&gt;&lt;/span&gt; (&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$start&lt;/span&gt;&lt;/span&gt;, &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$end&lt;/span&gt;&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color:#008000;"&gt;&lt;span class="comment"&gt;# created by Dr. Tobias Weltner, MVP PowerShell&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip1&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; ([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$start&lt;/span&gt;&lt;/span&gt;).&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;GetAddressBytes&lt;/span&gt;&lt;/span&gt;()&lt;br /&gt;[&lt;span class="datatype"&gt;&lt;span style="color:#0000ff;"&gt;Array&lt;/span&gt;&lt;/span&gt;]::&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Reverse&lt;/span&gt;&lt;/span&gt;(&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip1&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip1&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; ([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;](&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip1&lt;/span&gt;&lt;/span&gt; &lt;span class="modifier"&gt;&lt;span style="color:#5f9ea0;"&gt;-join&lt;/span&gt;&lt;/span&gt; &lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;/span&gt;)).&lt;span style="color:#8b4513;"&gt;&lt;span class="method"&gt;Address&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip2&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; ([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$end&lt;/span&gt;&lt;/span&gt;).&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;GetAddressBytes&lt;/span&gt;&lt;/span&gt;()&lt;br /&gt;[&lt;span class="datatype"&gt;&lt;span style="color:#0000ff;"&gt;Array&lt;/span&gt;&lt;/span&gt;]::&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Reverse&lt;/span&gt;&lt;/span&gt;(&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip2&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip2&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; ([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;](&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip2&lt;/span&gt;&lt;/span&gt; &lt;span class="modifier"&gt;&lt;span style="color:#5f9ea0;"&gt;-join&lt;/span&gt;&lt;/span&gt; &lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;/span&gt;)).&lt;span style="color:#8b4513;"&gt;&lt;span class="method"&gt;Address&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;for (&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$x&lt;/span&gt;&lt;/span&gt;&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip1&lt;/span&gt;&lt;/span&gt;; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$x&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;-le&lt;/span&gt;&lt;/span&gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip2&lt;/span&gt;&lt;/span&gt;; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$x&lt;/span&gt;&lt;/span&gt;&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;++&lt;/span&gt;&lt;/span&gt;) {&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; ([&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;System.Net.IPAddress&lt;/span&gt;&lt;/span&gt;]&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$x&lt;/span&gt;&lt;/span&gt;).&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;GetAddressBytes&lt;/span&gt;&lt;/span&gt;()&lt;br /&gt;[&lt;span class="datatype"&gt;&lt;span style="color:#0000ff;"&gt;Array&lt;/span&gt;&lt;/span&gt;]::&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Reverse&lt;/span&gt;&lt;/span&gt;(&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$ip&lt;/span&gt;&lt;/span&gt; &lt;span class="modifier"&gt;&lt;span style="color:#5f9ea0;"&gt;-join&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#800000;"&gt;&lt;span class="string"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;}&lt;br /&gt;}&lt;/div&gt;
&lt;p&gt;Now it is really easy to create IP address ranges. Try this:&lt;/p&gt;
&lt;div class="pscode"&gt;PS &amp;gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;New-IPRange&lt;/span&gt;&lt;/span&gt; 192.168.1.12 192.168.3.44&lt;br /&gt;192.168.1.12&lt;br /&gt;192.168.1.13&lt;br /&gt;192.168.1.14&lt;br /&gt;...&lt;br /&gt;192.168.3.43&lt;br /&gt;192.168.3.44&lt;/div&gt;
&lt;p&gt;When you look at the code, it really is pretty straight-forward: both start and end address are converted into an ip address, then the four octets are read into an array (&lt;strong&gt;GetAddressBytes()&lt;/strong&gt;). The static &lt;strong&gt;Reverse()&lt;/strong&gt; method can reverse the array content.&lt;/p&gt;
&lt;p&gt;Now we have two numbers, the start and the end point. A for loop can loop through that range (you cannot use the &amp;quot;..&amp;quot; trick because the numbers are 64bit values and &amp;quot;..&amp;quot; only deals with &lt;strong&gt;Int32&lt;/strong&gt;). Finally, the numbers are again converted into an ip address and the bytes reversed. &amp;nbsp;Now, &lt;strong&gt;-join&lt;/strong&gt; can put the bytes together and create an ip address.&lt;/p&gt;
&lt;h3&gt;Wait, there is more!&lt;/h3&gt;
&lt;p&gt;Using types can be fun, and you can achive a lot of cool results. Now that you can easily create IP address segments, what is the purpose? Of course there is always a purpose. Originally, I wanted not just a tool to create addresses but also check which computers are online in that segment and what their names are.&lt;/p&gt;
&lt;p&gt;If you did that with &lt;strong&gt;Test-Connection&lt;/strong&gt; or ping, it could take forever because it would work sequentially. Next time around, I show you how to ping 500 computers at the same time, making analyzing an entire network segment only a matter of seconds.&lt;/p&gt;
&lt;p&gt;Hope you had fun, see you next week around...&lt;/p&gt;
&lt;p&gt;Tobias&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Microsoft MVP PowerShell Germany&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;P.S.&lt;br /&gt;If you live in Germany or other parts of Europe and your company would like to set up a truly great PowerShell training, just contact me! I regularly train mid- to large-size companies. Trainings are always a blast with tons of real-world-examples and solutions. Here&amp;#39;s how to get in touch with me: &lt;a href="mailto:tobias.weltner@scriptinternals.de"&gt;&lt;span style="color:#3366cc;"&gt;tobias.weltner@scriptinternals.de&lt;/span&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://powershell.com/cs/aggbug.aspx?PostID=9438" width="1" height="1"&gt;</description><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/cast/default.aspx">cast</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/ping/default.aspx">ping</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/Convert/default.aspx">Convert</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/System.Net.IPAddress/default.aspx">System.Net.IPAddress</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/System.Version/default.aspx">System.Version</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/Test-Connection/default.aspx">Test-Connection</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/HighLow/default.aspx">HighLow</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/Significant+Byte/default.aspx">Significant Byte</category></item><item><title>Casting Data and Creating Validators</title><link>http://powershell.com/cs/blogs/tobias/archive/2008/11/22/casting-data-and-creating-validators.aspx</link><pubDate>Sat, 22 Nov 2008 21:30:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:349</guid><dc:creator>Tobias Weltner</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://powershell.com/cs/blogs/tobias/rsscomments.aspx?PostID=349</wfw:commentRss><comments>http://powershell.com/cs/blogs/tobias/archive/2008/11/22/casting-data-and-creating-validators.aspx#comments</comments><description>&lt;p&gt;Casting data from one type into another type has a lot of uses. One is data validation. Let&amp;#39;s take a look at how that works.&lt;/p&gt;
&lt;h3&gt;Casting Data: What&amp;#39;s that anyway?&lt;/h3&gt;
&lt;p&gt;Whenever you store information, PowerShell automatically picks the right &amp;quot;container type&amp;quot; for you. &lt;/p&gt;
&lt;p&gt;So when you assign text to a variable, the variable will internally use the System.String type. When you assign a whole number, it picks System.Int32. Every .NET object supports the &lt;strong&gt;GetType() &lt;/strong&gt;method which tells you the type PowerShell picked for you:&lt;/p&gt;
&lt;div style="font-family:&amp;#39;Lucida Console&amp;#39;;font-size:17;background:#012456;"&gt;&lt;span style="color:#eeedf0;background-color:#012456;"&gt;PS&amp;gt;&amp;nbsp;$a&amp;nbsp;=&amp;nbsp;&amp;quot;Hello&amp;quot;&lt;br /&gt;PS&amp;gt;&amp;nbsp;$a.GetType().FullName&lt;br /&gt;System.String&lt;br /&gt;PS&amp;gt;&amp;nbsp;$a&amp;nbsp;=&amp;nbsp;100&lt;br /&gt;PS&amp;gt;&amp;nbsp;$a.GetType().FullName&lt;br /&gt;System.Int32&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;You can override the automatic type selection and convert data into any type you want which is sometimes called &amp;quot;casting&amp;quot;. &lt;/p&gt;
&lt;p&gt;Why would you do that? There are hundreds of types, and some of them are highly specialized to deal with certain data such as types for XML, DateTimes or IPAddresses. PowerShell always selects a basic or &amp;quot;primitive&amp;quot; type like Integer or String. &lt;/p&gt;
&lt;p&gt;To get access to more specialized data, override the internal type selection and choose the best type manually.&lt;/p&gt;
&lt;h3&gt;How Do I Cast Data?&lt;/h3&gt;
&lt;p&gt;There are two ways to convert data from one type to another. The first one takes the new target type and puts it in square brackets. &lt;/p&gt;
&lt;p&gt;The following line takes a string and converts it into a specialized DateTime. DateTime gives you all kinds of specialized methods to deal with dates so you now can easily add time intervals:&lt;/p&gt;
&lt;div class="listing"&gt;
&lt;pre&gt;&lt;span class="var"&gt;$raw&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="string"&gt;&amp;#39;1.1.2000&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="var"&gt;$raw&lt;/span&gt;.&lt;span class="method"&gt;GetType&lt;/span&gt;().&lt;span class="method"&gt;FullName&lt;/span&gt;&lt;br /&gt;&lt;span class="var"&gt;$raw&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="var"&gt;$date&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; [&lt;span class="optional"&gt;DateTime&lt;/span&gt;] &lt;span class="var"&gt;$raw&lt;/span&gt;&lt;br /&gt;&lt;span class="var"&gt;$date&lt;/span&gt;.&lt;span class="method"&gt;GetType&lt;/span&gt;().&lt;span class="method"&gt;FullName&lt;/span&gt;&lt;br /&gt;&lt;span class="var"&gt;$date&lt;/span&gt;&lt;br /&gt;&lt;span class="var"&gt;$date&lt;/span&gt;.&lt;span class="method"&gt;AddDays&lt;/span&gt;(10)&lt;br /&gt;&lt;span class="var"&gt;$date&lt;/span&gt;.&lt;span class="method"&gt;AddDays&lt;/span&gt;(&lt;span class="op"&gt;-&lt;/span&gt;10)&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This simple casting approach will fail if the raw data cannot be converted to the specified target type so you generally need an error handler to catch exceptions if you cannot make sure the raw data meets the requirements. &lt;/p&gt;
&lt;p&gt;So for example, if you accept user input, you generally never know what the user enters. If the user enters invalid data that cannot be converted to the target type, you want to make sure the exception is caught. &lt;/p&gt;
&lt;p&gt;Here is a simple script. It asks for your birthday and calculates your age in days. If you enter something that cannot be converted to a DateTime, the script handles the error using Trap and outputs an error message:&lt;/p&gt;
&lt;div class="listing"&gt;
&lt;pre&gt;&lt;span class="keyword"&gt;trap&lt;/span&gt; { &lt;span class="string"&gt;&amp;#39;Your input was invalid!&amp;#39;&lt;/span&gt;; &lt;span class="keyword"&gt;continue&lt;/span&gt; }&lt;br /&gt;&lt;br /&gt;&lt;span class="op"&gt;&amp;amp;&lt;/span&gt; {&lt;br /&gt; &lt;span class="var"&gt;$date&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="verbnoun"&gt;Read-Host&lt;/span&gt; &lt;span class="string"&gt;&amp;quot;Enter your birthday&amp;quot;&lt;/span&gt;&lt;br /&gt; &lt;span class="var"&gt;$difference&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="verbnoun"&gt;New-TimeSpan&lt;/span&gt; &lt;span class="var"&gt;$date&lt;/span&gt;).&lt;span class="method"&gt;totalDays&lt;/span&gt;&lt;br /&gt; &lt;span class="string"&gt;&amp;#39;You are {0:0} days old&amp;#39;&lt;/span&gt; &lt;span class="op"&gt;-f&lt;/span&gt; &lt;span class="var"&gt;$difference&lt;/span&gt;&lt;br /&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There is a second approach to cast data which is widely unknown: the &lt;strong&gt;-as&lt;/strong&gt; operator. &lt;/p&gt;
&lt;p&gt;This operator tries to cast the data to the new type, and if that won&amp;#39;t work, it does not raise an exception. Instead, it simply returns &lt;strong&gt;$null.&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;With this approach, you can simplify your script because you no longer need an error handler:&lt;/p&gt;
&lt;div class="listing"&gt;
&lt;pre&gt;&lt;span class="var"&gt;$date&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="verbnoun"&gt;Read-Host&lt;/span&gt; &lt;span class="string"&gt;&amp;quot;Enter your birthday&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="var"&gt;$date&lt;/span&gt; &lt;span class="op"&gt;-as&lt;/span&gt; [&lt;span class="optional"&gt;DateTime&lt;/span&gt;]) {&lt;br /&gt;  &lt;span class="var"&gt;$difference&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="verbnoun"&gt;New-TimeSpan&lt;/span&gt; &lt;span class="var"&gt;$date&lt;/span&gt;).&lt;span class="method"&gt;totalDays&lt;/span&gt;&lt;br /&gt;  &lt;span class="string"&gt;&amp;#39;You are {0:0} days old&amp;#39;&lt;/span&gt; &lt;span class="op"&gt;-f&lt;/span&gt; &lt;span class="var"&gt;$difference&lt;/span&gt;&lt;br /&gt;} &lt;span class="keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;  &lt;span class="string"&gt;&amp;#39;Your input was invalid.&amp;#39;&lt;/span&gt;&lt;br /&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Creating Custom Validators&lt;/h3&gt;
&lt;p&gt;When you look at the previous example, you can see that type casting is a great way of automatically validating data. All you need to do is try to cast to the desired target type. If it works, the validation was successful. If it fails, the data was in the wrong format. As long as you find a type that represents a certain date format, you can delegate validation entirely to the type conversion process. &lt;/p&gt;
&lt;p&gt;For example, to write a little function that checks for valid date input, try this:&lt;/p&gt;
&lt;div class="listing"&gt;
&lt;pre&gt;&lt;span class="keyword"&gt;function&lt;/span&gt; isDate(&lt;span class="var"&gt;$object&lt;/span&gt;) {&lt;br /&gt;  [&lt;span class="optional"&gt;Boolean&lt;/span&gt;](&lt;span class="var"&gt;$object&lt;/span&gt; &lt;span class="op"&gt;-as&lt;/span&gt; [&lt;span class="optional"&gt;DateTime&lt;/span&gt;])&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;isDate(&lt;span class="string"&gt;&amp;#39;1.1.2000&amp;#39;&lt;/span&gt;)&lt;br /&gt;isDate(&lt;span class="string"&gt;&amp;#39;hehehe&amp;#39;&lt;/span&gt;)&lt;br /&gt;isDate(&lt;span class="string"&gt;&amp;#39;September 12, 2008&amp;#39;&lt;/span&gt;)&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Likewise, if you&amp;#39;d like to check for a valid IP address, don&amp;#39;t waste your time writing own validation code or figuring out tricky regular expressions. Instead, use the &lt;strong&gt;System.Net.IPAddress&lt;/strong&gt; like so:&lt;/p&gt;
&lt;div class="listing"&gt;
&lt;pre&gt;&lt;span class="keyword"&gt;function&lt;/span&gt; isIPAddress(&lt;span class="var"&gt;$object&lt;/span&gt;) {&lt;br /&gt;  [&lt;span class="optional"&gt;Boolean&lt;/span&gt;](&lt;span class="var"&gt;$object&lt;/span&gt; &lt;span class="op"&gt;-as&lt;/span&gt; [&lt;span class="namespace"&gt;System.Net.IPAddress&lt;/span&gt;])&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;isIPAddress(&lt;span class="string"&gt;&amp;#39;10.10.10.10&amp;#39;&lt;/span&gt;)&lt;br /&gt;isIPAddress(&lt;span class="string"&gt;&amp;#39;500.10.10.10&amp;#39;&lt;/span&gt;)&lt;br /&gt;isIPAddress(&lt;span class="string"&gt;&amp;#39;2001:0:d5c7:a2ca:184a:7bd:a865:5fb4&amp;#39;&lt;/span&gt;)&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, your validator also accepts V6 IP addresses which is pretty cool. Your own regular expression validator would have had a hard time figuring that out. &lt;/p&gt;
&lt;p&gt;With your new validator function, you can easily check user input and make sure only the desired data is entered:&lt;/p&gt;
&lt;div class="listing"&gt;
&lt;pre&gt;&lt;span class="keyword"&gt;function&lt;/span&gt; isIPAddress(&lt;span class="var"&gt;$object&lt;/span&gt;) {&lt;br /&gt;  [&lt;span class="optional"&gt;Boolean&lt;/span&gt;](&lt;span class="var"&gt;$object&lt;/span&gt; &lt;span class="op"&gt;-as&lt;/span&gt; [&lt;span class="namespace"&gt;System.Net.IPAddress&lt;/span&gt;])&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="var"&gt;$prompt&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="string"&gt;&amp;#39;Enter IP Address&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;do&lt;/span&gt; {&lt;br /&gt;  &lt;span class="var"&gt;$ip&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="verbnoun"&gt;Read-Host&lt;/span&gt; &lt;span class="var"&gt;$prompt&lt;/span&gt;&lt;br /&gt;  &lt;span class="var"&gt;$prompt&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="string"&gt;&amp;#39;Invalid input. Try again and enter IP Address&amp;#39;&lt;/span&gt;&lt;br /&gt;} &lt;span class="keyword"&gt;while&lt;/span&gt; (&lt;span class="op"&gt;-not&lt;/span&gt; (isIPAddress(&lt;span class="var"&gt;$ip&lt;/span&gt;)))&lt;br /&gt;&lt;br /&gt;&lt;span class="string"&gt;&amp;quot;You entered this IP address: $ip&amp;quot;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;span style="color:#800000;"&gt;As Alexander and Shay pointed out to me, validators are only as good as the underlying .NET type converter. As it turns out, .NET is quite liberal and even happily accepts a single number which it turns into a (correct) IP-Address:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#800000;"&gt;[system.Net.IPAddress]&amp;#39;1&amp;#39;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#800000;"&gt;So in real life, you may want to look how liberal .NET conversion is, and if it is too liberal, add a simple manual check like this:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#800000;"&gt;$ip -like &amp;#39;*.*.*.*&amp;#39;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#800000;"&gt;Or, you look at the conversion result and check to make sure it is identical to the user input. If it is not, you know that the conversion mechanism was too liberal:&lt;/span&gt;&lt;/p&gt;
&lt;div class="listing"&gt;
&lt;pre&gt;&lt;span class="keyword"&gt;function&lt;/span&gt; isIPAddress(&lt;span class="var"&gt;$object&lt;/span&gt;) { &lt;br /&gt;	(&lt;span class="var"&gt;$object&lt;/span&gt; &lt;span class="op"&gt;-as&lt;/span&gt; [&lt;span class="namespace"&gt;System.Net.IPAddress&lt;/span&gt;]).&lt;span class="method"&gt;IPAddressToString&lt;/span&gt; &lt;span class="op"&gt;-eq&lt;/span&gt; &lt;span class="var"&gt;$object&lt;/span&gt;&lt;br /&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Call for Action&lt;/h3&gt;
&lt;p&gt;If you happen to know other interesting .NET types for certain data formats, please add a comment. You have seen how you can use the -as operator in conjunction with any .NET type to validate raw data and make sure it is convertible into that type. Check out &lt;a target="_blank" href="http://www.powershellplus.com"&gt;PowerShellPlus&lt;/a&gt; to discover types and get rich code completion!&lt;/p&gt;
&lt;p&gt;See ya soon,&lt;/p&gt;
&lt;p&gt;-Tobias&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://powershell.com/cs/aggbug.aspx?PostID=349" width="1" height="1"&gt;</description><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/GetType_28002900_/default.aspx">GetType()</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/-as/default.aspx">-as</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/Validation/default.aspx">Validation</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/IPAddress/default.aspx">IPAddress</category><category domain="http://powershell.com/cs/blogs/tobias/archive/tags/cast/default.aspx">cast</category></item></channel></rss>