<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Indented!</title>
	<atom:link href="http://www.indented.co.uk/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.indented.co.uk</link>
	<description></description>
	<lastBuildDate>Thu, 08 Mar 2012 19:33:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>PuTTY and PowerShell</title>
		<link>http://www.indented.co.uk/index.php/2012/02/17/putty-and-powershell/</link>
		<comments>http://www.indented.co.uk/index.php/2012/02/17/putty-and-powershell/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 17:29:00 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1633</guid>
		<description><![CDATA[A friend of mine found this enormously useful, one of the things PowerShell can do easily that is (apparently) helpful for people who want nothing to do with it otherwise (where it may be either PowerShell or Windows). PuTTY stores session settings in the Registry, this little snippet using the PowerShell Registry Provider to update [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>A friend of mine found this enormously useful, one of the things PowerShell can do easily that is (apparently) helpful for people who want nothing to do with it otherwise (where it may be either PowerShell or Windows).<br />
<span id="more-1633"></span><br />
PuTTY stores session settings in the Registry, this little snippet using the PowerShell Registry Provider to update PuTTY session values. Anything goes as long as you can figure out the registry value you want to change.</p>
<p>Everything is in short-hand to make it, well, short. So, for reference this is what the shorthand really means:</p>
<ul>
<li>ls is Get-ChildItem</li>
<li>sp is Set-ItemProperty</li>
<li>% is ForEach-Object (a loop operator)</li>
</ul>
<h3>List all sessions</h3>
<pre class="brush: powershell; title: ; notranslate">
ls HKCU:\Software\SimonTatham\PuTTY\Sessions
</pre>
<h3>List some sessions</h3>
<pre class="brush: powershell; title: ; notranslate">
ls HKCU:\Software\SimonTatham\PuTTY\Sessions\*.domain.example
ls HKCU:\Software\SimonTatham\PuTTY\Sessions\*-rtr-*
ls HKCU:\Software\SimonTatham\PuTTY\Sessions\*-sw-*
</pre>
<p>More complex filtering can be performed using Where-Object (?), but that breaks the simplicity I&#8217;m striving for here.</p>
<p>The items returned by ls (Get-ChildItem) can be piped directly into sp (Set-ItemProperty) to change things.</p>
<h3>Set the console size</h3>
<pre class="brush: powershell; title: ; notranslate">
ls HKCU:\Software\SimonTatham\PuTTY\Sessions | sp -name TermWidth -value 140
ls HKCU:\Software\SimonTatham\PuTTY\Sessions | sp -name TermHeight -value 50
</pre>
<h3>Set a proxy</h3>
<pre class="brush: powershell; title: ; notranslate">
ls HKCU:\Software\SimonTatham\PuTTY\Sessions | sp -name ProxyHost -value &quot;proxy.domain.example&quot;
ls HKCU:\Software\SimonTatham\PuTTY\Sessions | sp -name ProxyPort -value 3128
</pre>
<h3>Add a username</h3>
<p>This assumes none of the sessions have a username yet, if it were to run against a session with a username it would double up. That is, me@host becomes me@me@host.</p>
<pre class="brush: powershell; title: ; notranslate">
ls HKCU:\Software\SimonTatham\PuTTY\Sessions | %{
  sp $_.PSPath -name HostName -value &quot;me@$($_.GetValue('hostname'))&quot;
}
</pre>
<h3>Replace a username</h3>
<p>Swapping out root@ with me@, a regular expression matches ^root at the beginning of the HostName. If the session does not use root nothing will change.</p>
<pre class="brush: powershell; title: ; notranslate">
ls HKCU:\Software\SimonTatham\PuTTY\Sessions | %{
  sp $_.PSPath -name HostName -value ($_.GetValue('hostname') -replace '^root@', 'me@')
}
</pre>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2012/02/17/putty-and-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sorting by IP address</title>
		<link>http://www.indented.co.uk/index.php/2011/10/14/sorting-by-ip-address/</link>
		<comments>http://www.indented.co.uk/index.php/2011/10/14/sorting-by-ip-address/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 10:53:41 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Subnet Math]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1630</guid>
		<description><![CDATA[Sorting an array of IP addresses is one of those things that&#8217;s not quite as clean and simple as would be nice. Fortunately, the process can be simplified greatly by converting an IP address to decimal for the sort operation. To do this, I like to use ConvertTo-DecimalIP from my NetShell module (or my collection [...]
Related posts:<ol>
<li><a href='http://www.indented.co.uk/index.php/2011/10/13/more-ipv4-subnet-maths-with-powershell/' rel='bookmark' title='More IPv4 subnet maths with PowerShell'>More IPv4 subnet maths with PowerShell</a> <small>I&#8217;ve been extended and upgrading my library of network functions...</small></li>
</ol>

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Sorting an array of IP addresses is one of those things that&#8217;s not quite as clean and simple as would be nice.<br />
<span id="more-1630"></span><br />
Fortunately, the process can be simplified greatly by converting an IP address to decimal for the sort operation. To do this, I like to use ConvertTo-DecimalIP from my NetShell module (or my collection of subnet maths functions).</p>
<pre class="brush: powershell; title: ; notranslate">
&quot;10.1.10.10&quot;, &quot;192.168.1.42&quot;, &quot;172.16.1.1&quot;, &quot;127.0.0.1&quot; | Sort-Object { ConvertTo-DecimalIP $_ }
</pre>
<p>Short and simple.</p>
<p>Related posts:<ol>
<li><a href='http://www.indented.co.uk/index.php/2011/10/13/more-ipv4-subnet-maths-with-powershell/' rel='bookmark' title='More IPv4 subnet maths with PowerShell'>More IPv4 subnet maths with PowerShell</a> <small>I&#8217;ve been extended and upgrading my library of network functions...</small></li>
</ol></p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2011/10/14/sorting-by-ip-address/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More IPv4 subnet maths with PowerShell</title>
		<link>http://www.indented.co.uk/index.php/2011/10/13/more-ipv4-subnet-maths-with-powershell/</link>
		<comments>http://www.indented.co.uk/index.php/2011/10/13/more-ipv4-subnet-maths-with-powershell/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 11:55:19 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[subnet]]></category>
		<category><![CDATA[Subnet Math]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1621</guid>
		<description><![CDATA[I&#8217;ve been extended and upgrading my library of network functions for some time now, I thought I&#8217;d post the functions that work directly with my original collection. These functions are also included in my NetShell module, I need to post an update to that very soon as well. ConvertTo-HexIP Sometimes being able to convert to [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been extended and upgrading my library of network functions for some time now, I thought I&#8217;d post the functions that work directly with my <a href='http://www.indented.co.uk/index.php/2010/01/23/powershell-subnet-math/'>original collection</a>.<br />
<span id="more-1621"></span><br />
These functions are also included in my NetShell module, I need to post an update to that very soon as well.</p>
<h3>ConvertTo-HexIP</h3>
<p>Sometimes being able to convert to a hexadecimal format is useful, this little function does exactly that. The body is very simple; it uses the built in formatters.</p>
<pre class="brush: powershell; title: ; notranslate">
Function ConvertTo-HexIP {
  &lt;#
    .Synopsis
      Converts a dotted decimal IP address into a hexadecimal string.
    .Description
      ConvertTo-HexIP takes a dotted decimal IP and returns a single hexadecimal string value.
    .Parameter IPAddress
      An IP Address to convert.
  #&gt;

  [CmdLetBinding()]
  Param(
    [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
    [Net.IPAddress]$IPAddress
  )

  Process {
    &quot;$($IPAddress.GetAddressBytes() | ForEach-Object { '{0:x2}' -f $_ })&quot; -Replace '\s'
  }
}
</pre>
<h3>ConvertFrom-HexIP</h3>
<p>And back again, using System.Convert.ToUInt32 with a base-16 value to get to UInt32, then a call to ConvertTo-DottedDecimalIP (from the original set).</p>
<pre class="brush: powershell; title: ; notranslate">
Function ConvertFrom-HexIP {
  &lt;#
    .Synopsis
      Converts a hexadecimal IP address into a dotted decimal string.
    .Description
      ConvertFrom-HexIP takes a hexadecimal string and returns a dotted decimal IP address.
    .Parameter IPAddress
      An IP Address to convert.
  #&gt;

  [CmdLetBinding()]
  Param(
    [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
    [ValidatePattern('^[0-9a-f]{8}$')]
    [String]$IPAddress
  )

  Process {
    ConvertTo-DottedDecimalIP ([Convert]::ToUInt32($IPAddress, 16))
  }
}
</pre>
<h3>Get-NetworkSummary</h3>
<p>Get-NetworkSummary gets a bit of an improvement.</p>
<pre class="brush: powershell; title: ; notranslate">
Function Get-NetworkSummary {
  &lt;#
    .Synopsis
      Generates a summary of a network range
    .Description
      Get-NetworkSummary uses most of the IP conversion CmdLets to provide a summary of a network
      range from any IP address in the range and a subnet mask.
    .Parameter IPAddress
      Any IP address within the network range.
    .Parameter Network
      A network description in the format 1.2.3.4/24
    .Parameter SubnetMask
      The subnet mask for the network.
  #&gt;

  [CmdLetBinding(DefaultParameterSetName = &quot;IPAndMask&quot;)]
  Param(
    [Parameter(Mandatory = $True, Position = 0, ParameterSetName = &quot;IPAndMask&quot;, ValueFromPipeline = $True)]
    [Net.IPAddress]$IPAddress,

    [Parameter(Mandatory = $True, Position = 1, ParameterSetName = &quot;IPAndMask&quot;)]
    [Alias(&quot;Mask&quot;)]
    [Net.IPAddress]$SubnetMask,

    [Parameter(Mandatory = $True, ParameterSetName = &quot;CIDRNotation&quot;, ValueFromPipeline = $True)]
    [ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
    [String]$Network
  )

  Process {
    If ($PsCmdLet.ParameterSetName -eq 'CIDRNotation') {
      $Temp = $Network.Split(&quot;\/&quot;)
      $IPAddress = $Temp[0]
      $SubnetMask = ConvertTo-Mask $Temp[1]
    }

    $DecimalIP = ConvertTo-DecimalIP $IPAddress
    $DecimalMask = ConvertTo-DecimalIP $SubnetMask
    $DecimalNetwork =  $DecimalIP -BAnd $DecimalMask
    $DecimalBroadcast = $DecimalIP -BOr ((-BNot $DecimalMask) -BAnd [UInt32]::MaxValue)

    $NetworkSummary = New-Object PSObject -Property @{
      &quot;NetworkAddress&quot;   = (ConvertTo-DottedDecimalIP $DecimalNetwork);
      &quot;NetworkDecimal&quot;   = $DecimalNetwork
      &quot;BroadcastAddress&quot; = (ConvertTo-DottedDecimalIP $DecimalBroadcast);
      &quot;BroadcastDecimal&quot; = $DecimalBroadcast
      &quot;Mask&quot;             = $SubnetMask;
      &quot;MaskLength&quot;       = (ConvertTo-MaskLength $SubnetMask);
      &quot;MaskHexadecimal&quot;  = (ConvertTo-HexIP $SubnetMask);
      &quot;HostRange&quot;        = &quot;&quot;;
      &quot;NumberOfHosts&quot;    = ($DecimalBroadcast - $DecimalNetwork - 1);
      &quot;Class&quot;            = &quot;&quot;;
      &quot;IsPrivate&quot;        = $False}

    If ($NetworkSummary.MaskLength -lt 31) {
      $NetworkSummary.HostRange = [String]::Format(&quot;{0} - {1}&quot;,
        (ConvertTo-DottedDecimalIP ($DecimalNetwork + 1)),
        (ConvertTo-DottedDecimalIP ($DecimalBroadcast - 1)))
    }

    Switch -RegEx ($(ConvertTo-BinaryIP $IPAddress)) {
      &quot;^1111&quot;              { $NetworkSummary.Class = &quot;E&quot; }
      &quot;^1110&quot;              { $NetworkSummary.Class = &quot;D&quot; }
      &quot;^11000000.10101000&quot; { $NetworkSummary.Class = &quot;C&quot;; $NetworkSummary.IsPrivate = $True }
      &quot;^110&quot;               { $NetworkSummary.Class = &quot;C&quot; }
      &quot;^10101100.0001&quot;     { $NetworkSummary.Class = &quot;B&quot;; $NetworkSummary.IsPrivate = $True }
      &quot;^10&quot;                { $NetworkSummary.Class = &quot;B&quot; }
      &quot;^00001010&quot;          { $NetworkSummary.Class = &quot;A&quot;; $NetworkSummary.IsPrivate = $True }
      &quot;^0&quot;                 { $NetworkSummary.Class = &quot;A&quot; }
    }   

    Return $NetworkSummary
  }
}
</pre>
<h3>Get-NetworkRange</h3>
<p>And so does Get-NetworkRange.</p>
<pre class="brush: powershell; title: ; notranslate">
Function Get-NetworkRange {
  &lt;#
    .Synopsis
      Generates IP addresses within the specified network.
    .Description
      Get-NetworkRange finds the network and broadcast address as decimal values then starts a
      counter between the two, returning Net.IPAddress for each.
    .Parameter IPAddress
      Any IP address within the network range.
    .Parameter Network
      A network description in the format 1.2.3.4/24
    .Parameter SubnetMask
      The subnet mask for the network.
  #&gt;

  [CmdLetBinding(DefaultParameterSetName = &quot;IPAndMask&quot;)]
  Param(
    [Parameter(Mandatory = $True, Position = 0, ParameterSetName = &quot;IPAndMask&quot;, ValueFromPipeline = $True)]
    [Net.IPAddress]$IPAddress, 

    [Parameter(Mandatory = $True, Position = 1, ParameterSetName = &quot;IPAndMask&quot;)]
    [Alias(&quot;Mask&quot;)]
    [Net.IPAddress]$SubnetMask,

    [Parameter(Mandatory = $True, ParameterSetName = &quot;CIDRNotation&quot;, ValueFromPipeline = $True)]
    [ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
    [String]$Network
  )

  Process {
    If ($PsCmdLet.ParameterSetName -eq 'CIDRNotation') {
      $Temp = $Network.Split(&quot;\/&quot;)
      $IPAddress = $Temp[0]
      $SubnetMask = ConvertTo-Mask $Temp[1]
    }

    $DecimalIP = ConvertTo-DecimalIP $IPAddress
    $DecimalMask = ConvertTo-DecimalIP $SubnetMask

    $DecimalNetwork = $DecimalIP -BAnd $DecimalMask
    $DecimalBroadcast = $DecimalIP -BOr ((-BNot $DecimalMask) -BAnd [UInt32]::MaxValue)

    For ($i = $($DecimalNetwork + 1); $i -lt $DecimalBroadcast; $i++) {
      ConvertTo-DottedDecimalIP $i
    }
  }
}
</pre>
<h3>Get-Subnets</h3>
<p>I ran into a need to calculate a list of subnets of a specific length within a super-net, this function does just that.</p>
<pre class="brush: powershell; title: ; notranslate">
Function Get-Subnets {
  &lt;#
    .Synopsis
      Generates a list of subnets for a given network range
    .Description
      Generates a list of subnets for a given network range using either the address class or a
      user-specified value.
    .Parameter NetworkAddress
      Any address in the supernet range.
    .Parameter SubnetMask
      The desired mask, determines the size of the resulting subnet. Must be a valid subnet mask.
    .Parameter SupernetLength
      By default Get-Subnets uses the address class to determine the size of the supernet. Where the
      supernet describes the range of addresses being split.
  #&gt;

  [CmdLetBinding(DefaultParameterSetName = &quot;PS1&quot;)]
  Param(
    [Parameter(Mandatory = $True, Position = 0, ParameterSetName = &quot;IPAndMask&quot;, ValueFromPipeline = $True)]
    [Net.IPAddress]$IPAddress, 

    [Parameter(Mandatory = $True, Position = 1, ParameterSetName = &quot;IPAndMask&quot;)]
    [Alias(&quot;Mask&quot;)]
    [Net.IPAddress]$SubnetMask,

    [Parameter(Mandatory = $True, ParameterSetName = &quot;CIDRNotation&quot;, ValueFromPipeline = $True)]
    [ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
    [String]$Network,

    [ValidateRange(1, 32)]
    [UInt32]$SupernetLength
  )

  Process {
    If ($PsCmdLet.ParameterSetName -eq 'CIDRNotation') {
      $Temp = $Network.Split(&quot;\/&quot;)
      $IPAddress = $Temp[0]
      $SubnetMask = ConvertTo-Mask $Temp[1]
    } Else {
      $SubnetLength = ConvertTo-MaskLength $SubnetMask
    }

    If (!$SupernetLength) {
      $SupernetLength = Switch -RegEx ($(ConvertTo-BinaryIP $IPAddress)) {
        &quot;^110&quot;  { 24 }
        &quot;^10&quot;   { 16 }
        &quot;^0&quot;    { 8 }
        default { 24 }
      }
    }
    If ($SupernetLength -gt $SubnetLength) {
      Write-Error &quot;Subnet is larger than supernet. Aborting&quot;
    }
    $SupernetMask = ConvertTo-Mask $SupernetLength

    $NumberOfNets = [Math]::Pow(2, ($SubnetLength - $SupernetLength))
    $NumberOfAddresses = [Math]::Pow(2, (32 - $SubnetLength))

    $SupernetAddress = Get-NetworkAddress $IPAddress $SupernetMask
    $DecimalAddress = ConvertTo-DecimalIP $SupernetAddress

    For ($i = 0; $i -lt $NumberOfNets; $i++) {
      $NetworkAddress = ConvertTo-DottedDecimalIP $DecimalAddress 

      &quot;&quot; | Select-Object @{n='NetworkAddress';e={ $NetworkAddress }},
        @{n='BroadcastAddress';e={ Get-BroadcastAddress $NetworkAddress $SubnetMask }},
        @{n='SubnetMask';e={ $SubnetMask }},
        @{n='HostAddresses';e={
          $NumberOfHosts = $NumberOfAddresses - 2
          If ($NumberOfHosts -lt 0) { 0 } Else { $NumberOfHosts } }}

      $DecimalAddress += $NumberOfAddresses
    }
  }
}
</pre>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2011/10/13/more-ipv4-subnet-maths-with-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get-LocalGroupMember</title>
		<link>http://www.indented.co.uk/index.php/2011/01/31/get-localgroupmember/</link>
		<comments>http://www.indented.co.uk/index.php/2011/01/31/get-localgroupmember/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 19:26:16 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1575</guid>
		<description><![CDATA[A quick PowerShell 2 function for a Monday evening. A function to return properties from the WinNT provider, most commonly used to enumerate local group membership. This should also work for domain groups (using the domain as the SystemName), although if the domain is Active Directory the LDAP provider returns far more information. The function [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>A quick PowerShell 2 function for a Monday evening. A function to return properties from the WinNT provider, most commonly used to enumerate local group membership.<br />
<span id="more-1575"></span><br />
This should also work for domain groups (using the domain as the SystemName), although if the domain is Active Directory the LDAP provider returns far more information. </p>
<p>The function can be copied into the prompt as is, or made into a script by dropping the opening &#8220;Function &#8230;&#8221; and closing }.</p>
<p>Once it&#8217;s there, you can see usage with:</p>
<pre class="brush: powershell; title: ; notranslate">
Get-Help Get-LocalGroupMember
Get-Help Get-LocalGroupMember -Full
Get-Help Get-LocalGroupMember -Examples
</pre>
<p>And the function itself:</p>
<pre class="brush: powershell; title: ; notranslate">
Function Get-LocalGroupMember {
  &lt;#
    .Synopsis
      This function returns members of a local group, by default the
      Administrators group.
    .Description
      Get-LocalGroupMember returns the members of a local group,
      including all properties exposed by the WinNT provider. Complex
      properties are returned in their raw form, additional work is needed
      to make sense of many.
    .Parameter SystemName
      The name of the system to execute against. By default, the function
      uses the local system.
    .Parameter Name
      The group name to extract membership from. By default, the function
      uses Administrators.
    .Parameter Properties
      A list of properties to return. Refer to the default value for a list of
      permissible properties.
    .Example
      Get-LocalGroupMember | Select-Object SystemName, Name, Class, Description

      Return members of the administrator group on the local computer.
    .Example
      Get-Content ServerList.txt | ForEach-Object { Get-LocalGroupMember $_ }

      Return members of the administrator group all computers names in
      a text file.
    .Example
      Get-QADComputer -OperatingSystem &quot;Windows 7*&quot; | Get-LocalGroupMember

      Return members of the administrator group for all computers running
      Windows 7 in Active Directory
  #&gt;

  Param(
    [Parameter(ValueFromPipelineByPropertyName = $True)]
    [Alias(&quot;DnsHostName&quot;)]
    [String]$SystemName = $Env:ComputerName,

    [Alias(&quot;Group&quot;)]
    [String]$Name = &quot;Administrators&quot;,

    [String[]]$Properties = @(
      &quot;AccountDisabled&quot;, &quot;AccountExpirationDate&quot;, &quot;AdsPath&quot;,
      &quot;BadLoginAddress&quot;, &quot;BadLoginCount&quot;, &quot;Class&quot;, &quot;Department&quot;,
      &quot;Description&quot;, &quot;Division&quot;, &quot;EmailAddress&quot;, &quot;EmployeeID&quot;,
      &quot;FaxNumber&quot;, &quot;FirstName&quot;, &quot;FullName&quot;, &quot;GraceLoginsAllowed&quot;,
      &quot;GraceLoginsRemaining&quot;, &quot;GUID&quot;, &quot;HomeDirectory&quot;, &quot;HomePage&quot;,
      &quot;IsAccountLocked&quot;, &quot;Languages&quot;, &quot;LastFailedLogin&quot;, &quot;LastLogin&quot;,
      &quot;LastLogoff&quot;, &quot;LastName&quot;, &quot;LoginHours&quot;, &quot;LoginScript&quot;, &quot;LoginWorkstations&quot;,
      &quot;Manager&quot;, &quot;MaxLogins&quot;, &quot;MaxStorage&quot;, &quot;Name&quot;, &quot;NamePrefix&quot;,
      &quot;NameSuffix&quot;, &quot;OfficeLocations&quot;, &quot;OtherName&quot;, &quot;Parent&quot;,
      &quot;PasswordExpirationDate&quot;, &quot;PasswordLastChanged&quot;, &quot;PasswordMinimumLength&quot;,
      &quot;PasswordRequired&quot;, &quot;Picture&quot;, &quot;PostalAddresses&quot;, &quot;PostalCodes&quot;, &quot;Profile&quot;,
      &quot;RequireUniquePassword&quot;, &quot;Schema&quot;, &quot;SeeAlso&quot;, &quot;TelephoneHome&quot;,
      &quot;TelephoneMobile&quot;, &quot;TelephoneNumber&quot;, &quot;TelephonePager&quot;, &quot;Title&quot;)
  )

  Process {
    $Select = $Properties | ForEach-Object {
      Invoke-Expression &quot;@{n='$_';e={
        `$_.GetType().InvokeMember('$_', 'GetProperty', `$Null, `$_, `$Null) }}&quot;
    }  

    ([ADSI]&quot;WinNT://$SystemName/$Name&quot;).Members() |
      Select-Object ([Array](@{n='SystemName';e={ $SystemName }}) + $Select)
  }
}
</pre>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2011/01/31/get-localgroupmember/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Microsoft Lync: Group Policy Templates</title>
		<link>http://www.indented.co.uk/index.php/2011/01/06/microsoft-lync-group-policy-templates/</link>
		<comments>http://www.indented.co.uk/index.php/2011/01/06/microsoft-lync-group-policy-templates/#comments</comments>
		<pubDate>Thu, 06 Jan 2011 08:49:54 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Lync]]></category>
		<category><![CDATA[group policy]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1567</guid>
		<description><![CDATA[I&#8217;ve been migrating our Office Communications Server to Lync over the last few days. Last night I started looking at the client policies. The intention is that we use the in-band-provisioning, which is great, and you&#8217;ll find a nice article on Elan Shudnow&#8217;s blog. The client also ships with a group policy template (on retail [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been migrating our Office Communications Server to Lync over the last few days. Last night I started looking at the client policies. </p>
<p>The intention is that we use the in-band-provisioning, which is great, and you&#8217;ll find a nice article on <a href='http://www.shudnow.net/2010/10/28/lync-2010-client-policies/'>Elan Shudnow&#8217;s blog</a>.</p>
<p>The client also ships with a group policy template (on retail disk or downloaded from volume licensing) a small number of lines need to be changed as it contains errors.<br />
<span id="more-1567"></span><br />
These existing entries, found under the [Strings] section.</p>
<pre class="brush: plain; title: ; notranslate">
GalUseCompactDeltaFile0=&quot;Do not use compact delta file&quot;
GalUseCompactDeltaFile1=&quot;Use compact delta file (default)&quot;
GalUseCompactDeltaFile2=&quot;Use compact data file, but do not issue an LDAP query to retrieve the 'Title' and 'Office' attribute from AD.&quot;
</pre>
<p>Should be replaced with the these modified entries:</p>
<pre class="brush: plain; title: ; notranslate">
GalUseCompactDeltaFileVal0=&quot;Do not use compact delta file&quot;
GalUseCompactDeltaFileVal1=&quot;Use compact delta file (default)&quot;
GalUseCompactDeltaFileVal2=&quot;Use compact data file, but do not issue an LDAP query to retrieve the 'Title' and 'Office' attribute from AD.&quot;
</pre>
<p>These variables are referenced in the !!PolicyGalUseCompactDeltaFile policy (line 311 by default).</p>
<p>In addition to these changes, I felt compelled to rename the file to Lync.adm. Otherwise it removes my existing policy template for Communicator 2007 R2, losing access to a number of important policies (such as a definable peer-to-peer port range). Not a good thing to happen in the middle of a migration.</p>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2011/01/06/microsoft-lync-group-policy-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NetShell</title>
		<link>http://www.indented.co.uk/index.php/2010/11/25/netshell/</link>
		<comments>http://www.indented.co.uk/index.php/2010/11/25/netshell/#comments</comments>
		<pubDate>Thu, 25 Nov 2010 19:56:50 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[DHCP]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[smtp]]></category>
		<category><![CDATA[subnet]]></category>
		<category><![CDATA[Subnet Math]]></category>
		<category><![CDATA[SysLog]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1561</guid>
		<description><![CDATA[It&#8217;s been a while since I&#8217;ve posted, and since it&#8217;s almost Christmas I thought I&#8217;d better get on with it. Without further ado I want to post NetShell (I&#8217;m not very good at coming up with imaginative names). NetShell is a collection of 17 functions and a few supporting functions in a script module. Download [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I&#8217;ve posted, and since it&#8217;s almost Christmas I thought I&#8217;d better get on with it.</p>
<p>Without further ado I want to post NetShell (I&#8217;m not very good at coming up with imaginative names). NetShell is a collection of 17 functions and a few supporting functions in a script module. </p>
<p>Download <a href='http://www.indented.co.uk/wp-content/uploads/2011/05/NetShell.zip'>NetShell</a><br />
<span id="more-1561"></span><br />
Installation is a manual process, but not too hard. Open up Documents\WindowsPowerShell\Modules, extract the ZIP file. Make sure it includes the NetShell folder or it won&#8217;t work. The module is not currently signed, something else on the to-do list. Once it&#8217;s there, Import-Module NetShell and off you go.</p>
<p>It includes the following:</p>
<table>
<tr>
<td><b>ConvertTo-BinaryIP</b></td>
<td>Converts an IP address into a binary string</td>
</tr>
<tr>
<td><b>ConvertTo-Byte</b></td>
<td>A supporting function, a simple conversion of a string to a byte array (ASCII encoding)</td>
</tr>
<tr>
<td><b>ConvertTo-DecimalIP</b></td>
<td>Converts an IP address to 32-bit decimal number</td>
</tr>
<tr>
<td><b>ConvertTo-DottedDecimalIP</b></td>
<td>Converts a binary or 32-bit decimal back to an IP</td>
</tr>
<tr>
<td><b>ConvertTo-Mask</b></td>
<td>Converts from a mask length. For example, gets you from 22 to 255.255.252.0</td>
</tr>
<tr>
<td><b>ConvertTo-MaskLength</b></td>
<td>Converts from the IP form of a mask to the length</td>
</tr>
<tr>
<td><b>ConvertTo-String</b></td>
<td>Another supporting function, converts a byte array to a string (ASCII encoding)</td>
</tr>
<tr>
<td><b>Get-BroadcastAddress</b></td>
<td>Returns the broadcast address for the specified IP address and subnet mask</td>
</tr>
<tr>
<td><b>Get-NetworkAddress</b></td>
<td>Returns the network address for the specified IP address and subnet mask</td>
</tr>
<tr>
<td><b>Get-NetworkRange</b></td>
<td>Returns every IP within the specified range</td>
</tr>
<tr>
<td><b>Get-NetworkSummary</b></td>
<td>Everything about an IP address and mask I considered useful</td>
</tr>
<tr>
<td><b>New-DhcpDiscoverPacket</b></td>
<td>A supporting function for Send-DhcpDiscover. Creates the packet to send (a large byte array)</td>
</tr>
<tr>
<td><b>New-Socket</b></td>
<td>Creates an instance of System.Net.Sockets.Socket, an arbitrary network socket to do with as you please.</td>
</tr>
<tr>
<td><b>New-SysLogDateTime</b></td>
<td>A supporting function to create a DateTime string in the format SysLog likes.</td>
</tr>
<tr>
<td><b>Read-DhcpOption</b></td>
<td>A supporting function to read off an Option from a DHCP packet. Needs to be fed the Extended.BinaryReader class at the top of the module.</td>
</tr>
<tr>
<td><b>Read-DhcpPacket</b></td>
<td>Creates and uses an instance of Extended.BinaryReader to process a DHCP packet and translate the fields.</td>
</tr>
<tr>
<td><b>Receive-Bytes</b></td>
<td>Receives a stream of bytes from the network using a socket</td>
</tr>
<tr>
<td><b>Remove-Socket</b></td>
<td>Cleans up after New-Socket</td>
</tr>
<tr>
<td><b>Send-Bytes</b></td>
<td>Sends an arbitrary byte array over the network using a socket</td>
</tr>
<tr>
<td><b>Send-DhcpDiscover</b></td>
<td>Creates and sends a DHCPDISCOVER packet, then processes and returns the response</td>
</tr>
<tr>
<td><b>Start-Syslog</b></td>
<td>Starts a SysLog server. No termination for this one at the moment. Needs a bit more work.</td>
</tr>
<tr>
<td><b>Test-Smtp</b></td>
<td>Does the SMTP test you normally wind up doing with telnet, returning all the results along with the SMTP banner.</td>
</tr>
<tr>
<td><b>Test-SysLogDateTime</b></td>
<td>A supporting function to check the format of a DateTime that may or may not be present in a SysLog message.</td>
</tr>
<tr>
<td><b>Test-SysLogPRI</b></td>
<td>A supporting function to test of the PRI value in a SysLog message.</td>
</tr>
<tr>
<td><b>Test-TcpPort</b></td>
<td>Returns a boolean indicating whether or not the port connection succeeded.</td>
</tr>
</table>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2010/11/25/netshell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DnsShell: Zone and Server CmdLets</title>
		<link>http://www.indented.co.uk/index.php/2010/04/16/dnsshell-zone-and-server-cmdlets/</link>
		<comments>http://www.indented.co.uk/index.php/2010/04/16/dnsshell-zone-and-server-cmdlets/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 15:10:49 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[DnsShell]]></category>
		<category><![CDATA[Microsoft DNS]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1470</guid>
		<description><![CDATA[After fixing a couple of authentication bugs with Set-DnsRecord and New-DnsRecord I decided to make an attempt to finish off some of the zone and server CmdLets. The module now contains these additional CmdLets. Refresh-DnsZone &#8211; Implements the ForceRefresh method for Secondary Zones Reload-ADDnsZone &#8211; Implements the UpdateFromDS method for AD Integrated Zones Reload-DnsZone Reset-DnsZoneType [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>After fixing a couple of authentication bugs with Set-DnsRecord and New-DnsRecord I decided to make an attempt to finish off some of the zone and server CmdLets.</p>
<p>The module now contains these additional CmdLets.</p>
<ul>
<li><b>Refresh-DnsZone</b> &#8211; Implements the ForceRefresh method for Secondary Zones</li>
<li><b>Reload-ADDnsZone</b> &#8211; Implements the UpdateFromDS method for AD Integrated Zones</li>
<li><b>Reload-DnsZone</b></li>
<li><b>Reset-DnsZoneType</b> &#8211; Implements the ChangeZoneType method</li>
<li><b>Resume-DnsZone</b></li>
<li><b>Set-DnsZoneTransfer</b> &#8211; Implements the ResetSecondaries method</li>
<li><b>Start-DnsScavenging</b></li>
<li><b>Start-DnsService</b></li>
<li><b>Stop-DnsService</b></li>
<li><b>Suspend-DnsZone</b> &#8211; Implements the Pause method</li>
<li><b>Update-DnsZoneFile</b></li>
</ul>
<p>As usual, the module can be downloaded from <a href='http://code.msdn.microsoft.com/dnsshell'>code.msdn.microsoft.com/dnsshell</a>.</p>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2010/04/16/dnsshell-zone-and-server-cmdlets/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>DnsShell: Get-AD*</title>
		<link>http://www.indented.co.uk/index.php/2010/04/14/dnsshell-get-ad/</link>
		<comments>http://www.indented.co.uk/index.php/2010/04/14/dnsshell-get-ad/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 13:09:51 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[DnsShell]]></category>
		<category><![CDATA[Microsoft DNS]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1467</guid>
		<description><![CDATA[A new version of DnsShell has been released, this release improves Get-ADDnsRecord and adds Get-ADDnsPartition and Get-ADDnsZone. The updated release is available on MSDN as version 0.2.0. code.msdn.microsoft.com/dnsshell Basic help is available for each of the new CmdLets. No related posts. Related posts brought to you by Yet Another Related Posts Plugin.
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>A new version of DnsShell has been released, this release improves Get-ADDnsRecord and adds Get-ADDnsPartition and Get-ADDnsZone.</p>
<p>The updated release is available on MSDN as version 0.2.0.</p>
<p><a href='http://code.msdn.microsoft.com/dnsshell'>code.msdn.microsoft.com/dnsshell</a></p>
<p>Basic help is available for each of the new CmdLets.</p>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2010/04/14/dnsshell-get-ad/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DnsShell &#8211; alpha release</title>
		<link>http://www.indented.co.uk/index.php/2010/03/29/dnsshell-alpha/</link>
		<comments>http://www.indented.co.uk/index.php/2010/03/29/dnsshell-alpha/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 14:47:26 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[DnsShell]]></category>
		<category><![CDATA[Microsoft DNS]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1451</guid>
		<description><![CDATA[DnsShell is my PowerShell module intended to help administer MS DNS. This is an alpha relaese, it may contain bugs, it should be tested in a safe environment first. The module is currently available on MSDN. The following CmdLets are implemented at this stage: Get-Dns Clear-DnsCache Get-DnsRecord Get-DnsServer Get-DnsZone New-DnsRecord New-DnsZone Remove-DnsObject Set-DnsRecord Get-ADDnsRecord I [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>DnsShell is my PowerShell module intended to help administer MS DNS. This is an alpha relaese, it may contain bugs, it should be tested in a safe environment first.</p>
<p>The module is currently available on <a href='http://code.msdn.microsoft.com/dnsshell'>MSDN</a>.</p>
<p>The following CmdLets are implemented at this stage:</p>
<ul>
<li>Get-Dns</li>
<li>Clear-DnsCache</li>
<li>Get-DnsRecord</li>
<li>Get-DnsServer</li>
<li>Get-DnsZone</li>
<li>New-DnsRecord</li>
<li>New-DnsZone</li>
<li>Remove-DnsObject</li>
<li>Set-DnsRecord</li>
<li>Get-ADDnsRecord</li>
</ul>
<p>I am in the process of writing detailed CmdLet help, it will be made available as soon as possible.</p>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2010/03/29/dnsshell-alpha/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DHCP Discovery</title>
		<link>http://www.indented.co.uk/index.php/2010/02/17/dhcp-discovery/</link>
		<comments>http://www.indented.co.uk/index.php/2010/02/17/dhcp-discovery/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 12:46:24 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[DHCP]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.indented.co.uk/?p=1436</guid>
		<description><![CDATA[A PowerShell script to send a DHCP Discover request and listen for DHCP Offer responses, it can be used for finding DHCP servers (including rogue servers), or for testing DHCP servers and relays. The output from this script is an object containing a decode of the DHCP packet and a number of options. By default [...]
No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>A PowerShell script to send a DHCP Discover request and listen for DHCP Offer responses, it can be used for finding DHCP servers (including rogue servers), or for testing DHCP servers and relays. The output from this script is an object containing a decode of the DHCP packet and a number of options.<br />
<span id="more-1436"></span><br />
By default the script uses a spoofed MAC address of AA:BB:CC:DD:EE:FF to send the offer, a specific MAC address can be specified using the MacAddressString parameter. </p>
<p>The script can listen for DHCP offers for a specified number of seconds by using the DiscoverTimeout parameter, by default the script listens for 60 seconds. Note that a timeout is set for the ReceiveFrom method, this is set to 10 seconds in the script and applies to each receive attempt. If the connection times out the script will stop listening for offers regardless of the value for DiscoverTimeout.</p>
<p>This script has only been tested using PowerShell 2.0.</p>
<pre class="brush: powershell; title: ; notranslate">
&lt;#
  Net-DhcpDiscover.ps1

  Author: Chris Dent
  Date: 16/02/2010

  A script to send a DHCPDISCOVER request and report on DHCPOFFER
  responses returned by all DHCP Servers on the current subnet.

  DHCP Packet Format (RFC 2131 - http://www.ietf.org/rfc/rfc2131.txt):

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
  +---------------+---------------+---------------+---------------+
  |                            xid (4)                            |
  +-------------------------------+-------------------------------+
  |           secs (2)            |           flags (2)           |
  +-------------------------------+-------------------------------+
  |                          ciaddr  (4)                          |
  +---------------------------------------------------------------+
  |                          yiaddr  (4)                          |
  +---------------------------------------------------------------+
  |                          siaddr  (4)                          |
  +---------------------------------------------------------------+
  |                          giaddr  (4)                          |
  +---------------------------------------------------------------+
  |                                                               |
  |                          chaddr  (16)                         |
  |                                                               |
  |                                                               |
  +---------------------------------------------------------------+
  |                                                               |
  |                          sname   (64)                         |
  +---------------------------------------------------------------+
  |                                                               |
  |                          file    (128)                        |
  +---------------------------------------------------------------+
  |                                                               |
  |                          options (variable)                   |
  +---------------------------------------------------------------+

   FIELD      OCTETS       DESCRIPTION
   -----      ------       -----------

   op            1  Message op code / message type.
                    1 = BOOTREQUEST, 2 = BOOTREPLY
   htype         1  Hardware address type, see ARP section in &quot;Assigned
                    Numbers&quot; RFC; e.g., '1' = 10mb ethernet.
   hlen          1  Hardware address length (e.g.  '6' for 10mb
                    ethernet).
   hops          1  Client sets to zero, optionally used by relay agents
                    when booting via a relay agent.
   xid           4  Transaction ID, a random number chosen by the
                    client, used by the client and server to associate
                    messages and responses between a client and a
                    server.
   secs          2  Filled in by client, seconds elapsed since client
                    began address acquisition or renewal process.
   flags         2  Flags (see figure 2).
   ciaddr        4  Client IP address; only filled in if client is in
                    BOUND, RENEW or REBINDING state and can respond
                    to ARP requests.
   yiaddr        4  'your' (client) IP address.
   siaddr        4  IP address of next server to use in bootstrap;
                    returned in DHCPOFFER, DHCPACK by server.
   giaddr        4  Relay agent IP address, used in booting via a
                    relay agent.
   chaddr       16  Client hardware address.
   sname        64  Optional server host name, null terminated string.
   file        128  Boot file name, null terminated string; &quot;generic&quot;
                    name or null in DHCPDISCOVER, fully qualified
                    directory-path name in DHCPOFFER.
   options     var  Optional parameters field.  See the options
                    documents for a list of defined options.
#&gt;

#
# Parameters
#

Param(
  # MAC Address String in Hex-Decimal Format can be delimited with
  # dot, dash or colon (or none)
  [String]$MacAddressString = &quot;AA:BB:CC:DD:EE:FF&quot;,
  # Length of time (in seconds) to spend waiting for Offers if
  # the connection does not timeout first
  [Byte]$DiscoverTimeout = 60
)

# Build a DHCPDISCOVER packet to send
#
# Caller: Main

Function New-DhcpDiscoverPacket
{
  Param(
    [String]$MacAddressString = &quot;AA:BB:CC:DD:EE:FF&quot;
  )

  # Generate a Transaction ID for this request

  $XID = New-Object Byte[] 4
  $Random = New-Object Random
  $Random.NextBytes($XID)

  # Convert the MAC Address String into a Byte Array

  # Drop any characters which might be used to delimit the string
  $MacAddressString = $MacAddressString -Replace &quot;-|:|\.&quot;
  $MacAddress = [BitConverter]::GetBytes((
    [UInt64]::Parse($MacAddressString,
    [Globalization.NumberStyles]::HexNumber)))
  # Reverse the MAC Address array
  [Array]::Reverse($MacAddress)

  # Create the Byte Array
  $DhcpDiscover = New-Object Byte[] 243

  # Copy the Transaction ID Bytes into the array
  [Array]::Copy($XID, 0, $DhcpDiscover, 4, 4)

  # Copy the MacAddress Bytes into the array (drop the first 2 bytes,
  # too many bytes returned from UInt64)
  [Array]::Copy($MACAddress, 2, $DhcpDiscover, 28, 6)

  # Set the OP Code to BOOTREQUEST
  $DhcpDiscover[0] = 1
  # Set the Hardware Address Type to Ethernet
  $DhcpDiscover[1] = 1
  # Set the Hardware Address Length (number of bytes)
  $DhcpDiscover[2] = 6
  # Set the Broadcast Flag
  $DhcpDiscover[10] = 128
  # Set the Magic Cookie values
  $DhcpDiscover[236] = 99
  $DhcpDiscover[237] = 130
  $DhcpDiscover[238] = 83
  $DhcpDiscover[239] = 99
  # Set the DHCPDiscover Message Type Option
  $DhcpDiscover[240] = 53
  $DhcpDiscover[241] = 1
  $DhcpDiscover[242] = 1

  Return $DhcpDiscover
}

# Parse a DHCP Packet, returning an object containing each field
#
# Caller: Main

Function Read-DhcpPacket( [Byte[]]$Packet )
{
  $Reader = New-Object IO.BinaryReader(New-Object IO.MemoryStream(@(,$Packet)))

  $DhcpResponse = New-Object Object

  # Get and translate the Op code
  $DhcpResponse | Add-Member NoteProperty Op $Reader.ReadByte()
  if ($DhcpResponse.Op -eq 1)
  {
    $DhcpResponse.Op = &quot;BootRequest&quot;
  }
  else
  {
    $DhcpResponse.Op = &quot;BootResponse&quot;
  }

  $DhcpResponse | Add-Member NoteProperty HType -Value $Reader.ReadByte()
  if ($DhcpResponse.HType -eq 1) { $DhcpResponse.HType = &quot;Ethernet&quot; }

  $DhcpResponse | Add-Member NoteProperty HLen $Reader.ReadByte()
  $DhcpResponse | Add-Member NoteProperty Hops $Reader.ReadByte()
  $DhcpResponse | Add-Member NoteProperty XID $Reader.ReadUInt32()
  $DhcpResponse | Add-Member NoteProperty Secs $Reader.ReadUInt16()
  $DhcpResponse | Add-Member NoteProperty Flags $Reader.ReadUInt16()
  # Broadcast is the only flag that can be present, the other bits are reserved
  if ($DhcpResponse.Flags -BAnd 128) { $DhcpResponse.Flags = @(&quot;Broadcast&quot;) }

  $DhcpResponse | Add-Member NoteProperty CIAddr `
    $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
    &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;)
  $DhcpResponse | Add-Member NoteProperty YIAddr `
    $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
    &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;)
  $DhcpResponse | Add-Member NoteProperty SIAddr `
    $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
    &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;)
  $DhcpResponse | Add-Member NoteProperty GIAddr `
    $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
    &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;)

  $MacAddrBytes = New-Object Byte[] 16
  [Void]$Reader.Read($MacAddrBytes, 0, 16)
  $MacAddress = [String]::Join(
    &quot;:&quot;, $($MacAddrBytes[0..5] | %{ [String]::Format('{0:X2}', $_) }))
  $DhcpResponse | Add-Member NoteProperty CHAddr $MacAddress

  $DhcpResponse | Add-Member NoteProperty SName `
    $([String]::Join(&quot;&quot;, $Reader.ReadChars(64)).Trim())
  $DhcpResponse | Add-Member NoteProperty File `
    $([String]::Join(&quot;&quot;, $Reader.ReadChars(128)).Trim())

  $DhcpResponse | Add-Member NoteProperty MagicCookie `
    $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
    &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;)

  # Start reading Options

  $DhcpResponse | Add-Member NoteProperty Options @()
  While ($Reader.BaseStream.Position -lt $Reader.BaseStream.Length)
  {
    $Option = New-Object Object
    $Option | Add-Member NoteProperty OptionCode $Reader.ReadByte()
    $Option | Add-Member NoteProperty OptionName &quot;&quot;
    $Option | Add-Member NoteProperty Length 0
    $Option | Add-Member NoteProperty OptionValue &quot;&quot;

    If ($Option.OptionCode -ne 0 -And $Option.OptionCode -ne 255)
    {
      $Option.Length = $Reader.ReadByte()
    }

    Switch ($Option.OptionCode)
    {
      0 { $Option.OptionName = &quot;PadOption&quot; }
      1 {
        $Option.OptionName = &quot;SubnetMask&quot;
        $Option.OptionValue = `
          $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
          &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;) }
      3 {
        $Option.OptionName = &quot;Router&quot;
        $Option.OptionValue = `
          $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
          &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;) }
      6 {
        $Option.OptionName = &quot;DomainNameServer&quot;
        $Option.OptionValue = @()
        For ($i = 0; $i -lt ($Option.Length / 4); $i++)
        {
          $Option.OptionValue += `
            $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
            &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;)
        } }
      15 {
        $Option.OptionName = &quot;DomainName&quot;
        $Option.OptionValue = [String]::Join(
          &quot;&quot;, $Reader.ReadChars($Option.Length)) }
      51 {
        $Option.OptionName = &quot;IPAddressLeaseTime&quot;
        # Read as Big Endian
        $Value = ($Reader.ReadByte() * [Math]::Pow(256, 3)) + `
          ($Reader.ReadByte() * [Math]::Pow(256, 2)) + `
          ($Reader.ReadByte() * 256) + `
          $Reader.ReadByte()
        $Option.OptionValue = $(New-TimeSpan -Seconds $Value) }
      53 {
        $Option.OptionName = &quot;DhcpMessageType&quot;
        Switch ($Reader.ReadByte())
        {
          1 { $Option.OptionValue = &quot;DHCPDISCOVER&quot; }
          2 { $Option.OptionValue = &quot;DHCPOFFER&quot; }
          3 { $Option.OptionValue = &quot;DHCPREQUEST&quot; }
          4 { $Option.OptionValue = &quot;DHCPDECLINE&quot; }
          5 { $Option.OptionValue = &quot;DHCPACK&quot; }
          6 { $Option.OptionValue = &quot;DHCPNAK&quot; }
          7 { $Option.OptionValue = &quot;DHCPRELEASE&quot; }
        } }
      54 {
        $Option.OptionName = &quot;DhcpServerIdentifier&quot;
        $Option.OptionValue = `
          $(&quot;$($Reader.ReadByte()).$($Reader.ReadByte()).&quot; + `
          &quot;$($Reader.ReadByte()).$($Reader.ReadByte())&quot;) }
      58 {
        $Option.OptionName = &quot;RenewalTime&quot;
        # Read as Big Endian
        $Value = ($Reader.ReadByte() * [Math]::Pow(256, 3)) + `
          ($Reader.ReadByte() * [Math]::Pow(256, 2)) + `
          ($Reader.ReadByte() * 256) + `
          $Reader.ReadByte()
        $Option.OptionValue = $(New-TimeSpan -Seconds $Value) }
      59 {
        $Option.OptionName = &quot;RebindingTime&quot;
        # Read as Big Endian
        $Value = ($Reader.ReadByte() * [Math]::Pow(256, 3)) + `
          ($Reader.ReadByte() * [Math]::Pow(256, 2)) + `
          ($Reader.ReadByte() * 256) + `
          $Reader.ReadByte()
        $Option.OptionValue = $(New-TimeSpan -Seconds $Value) }
      255 { $Option.OptionName = &quot;EndOption&quot; }
      default {
        # For all options which are not decoded here
        $Option.OptionName = &quot;NoOptionDecode&quot;
        $Buffer = New-Object Byte[] $Option.Length
        [Void]$Reader.Read($Buffer, 0, $Option.Length)
        $Option.OptionValue = $Buffer
      }
    }

    # Override the ToString method
    $Option | Add-Member ScriptMethod ToString `
        { Return &quot;$($this.OptionName) ($($this.OptionValue))&quot; } -Force

    $DhcpResponse.Options += $Option
  }

  Return $DhcpResponse
}

# Create a UDP Socket with Broadcast and Address Re-use enabled.
#
# Caller: Main

Function New-UdpSocket
{
  Param(
    [Int32]$SendTimeOut = 5,
    [Int32]$ReceiveTimeOut = 5
  )

  $UdpSocket = New-Object Net.Sockets.Socket(
    [Net.Sockets.AddressFamily]::InterNetwork,
    [Net.Sockets.SocketType]::Dgram,
    [Net.Sockets.ProtocolType]::Udp)
  $UdpSocket.EnableBroadcast = $True
  $UdpSocket.ExclusiveAddressUse = $False
  $UdpSocket.SendTimeOut = $SendTimeOut * 1000
  $UdpSocket.ReceiveTimeOut = $ReceiveTimeOut * 1000

  Return $UdpSocket
}

# Close down a Socket
#
# Caller: Main

Function Remove-Socket
{
  Param(
    [Net.Sockets.Socket]$Socket
  )

  $Socket.Shutdown(&quot;Both&quot;)
  $Socket.Close()
}

#
# Main
#

# Create a Byte Array for the DHCPDISCOVER packet
$Message = New-DhcpDiscoverPacket -Send 10 -Receive 10

# Create a socket
$UdpSocket = New-UdpSocket

# UDP Port 68 (Server-to-Client port)
$EndPoint = [Net.EndPoint](
  New-Object Net.IPEndPoint($([Net.IPAddress]::Any, 68)))
# Listen on $EndPoint
$UdpSocket.Bind($EndPoint)

# UDP Port 67 (Client-to-Server port)
$EndPoint = [Net.EndPoint](
 New-Object Net.IPEndPoint($([Net.IPAddress]::Broadcast, 67)))
# Send the DHCPDISCOVER packet
$BytesSent = $UdpSocket.SendTo($Message, $EndPoint)

# Begin receiving and processing responses
$NoConnectionTimeOut = $True

$Start = Get-Date

While ($NoConnectionTimeOut)
{
  $BytesReceived = 0
  Try
  {
    # Placeholder EndPoint for the Sender
    $SenderEndPoint = [Net.EndPoint](
      New-Object Net.IPEndPoint($([Net.IPAddress]::Any, 0)))
    # Receive Buffer
    $ReceiveBuffer = New-Object Byte[] 1024
    $BytesReceived = $UdpSocket.ReceiveFrom($ReceiveBuffer, [Ref]$SenderEndPoint)
  }
  #
  # Catch a SocketException, thrown when the Receive TimeOut value is reached
  #
  Catch [Net.Sockets.SocketException]
  {
    $NoConnectionTimeOut = $False
  }

  If ($BytesReceived -gt 0)
  {
    Read-DhcpPacket $ReceiveBuffer[0..$BytesReceived]
  }

  If ((Get-Date) -gt $Start.AddSeconds($DiscoverTimeout))
  {
    # Exit condition, not error condition
    $NoConnectionTimeOut = $False
  }
}

Remove-Socket $UdpSocket
</pre>
<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2010/02/17/dhcp-discovery/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

