<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Nivot Ink</title>
    <link>http://www.nivot.org/</link>
    <description>PowerShell, SharePoint, WCF, WWF, .NET, ASP.NET, Enterprise Computing and babble from Microsoft MVP Oisin Grehan.</description>
    <language>en-us</language>
    <copyright>Oisin Grehan</copyright>
    <lastBuildDate>Thu, 11 Mar 2010 01:01:07 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>oising@gmail.com</managingEditor>
    <webMaster>oising@gmail.com</webMaster>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=d670cb31-373a-41bc-8633-c5d102fd308d</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,d670cb31-373a-41bc-8633-c5d102fd308d.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,d670cb31-373a-41bc-8633-c5d102fd308d.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=d670cb31-373a-41bc-8633-c5d102fd308d</wfw:commentRss>
      <title>PowerShell 2.0 – Partial Application of Functions and Cmdlets</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,d670cb31-373a-41bc-8633-c5d102fd308d.aspx</guid>
      <link>http://www.nivot.org/2010/03/11/PowerShell20PartialApplicationOfFunctionsAndCmdlets.aspx</link>
      <pubDate>Thu, 11 Mar 2010 01:01:07 GMT</pubDate>
      <description>&lt;p&gt;
This is unashamedly a post for developers, in particular those with an interest in
functional languages. With the advent of PowerShell 2.0, some of you may have noticed
that ScriptBlocks - which I suppose could also be called anonymous functions or lambdas
- gained a new method: &lt;a href="http://blogs.msdn.com/powershell/archive/2009/03/27/get-closure-with-getnewclosure.aspx" target="_blank"&gt;GetNewClosure&lt;/a&gt;.
Closures are one of the essential tools for functional programming., something I’ve
been trying to learn more about over the last few years. I don’t really have an opportunity
to use it in work other than the hybrid trickery available in C# 3.0, but I have been
tinkering a lot with PowerShell 2.0 to see if some of the tricks of the functional
trade could be implemented. It’s just a shell language, but there are some nice features
in there that enable a wide variety of funky stuff.
&lt;/p&gt;
&lt;h3&gt;Partial Application
&lt;/h3&gt;
&lt;p&gt;
In a nutshell, partial application of a function is when you pass in only some of
the parameters and get a function back that can accept the remaining parameters:
&lt;/p&gt;
&lt;pre class="brush:powershell"&gt;# define a simple function
function test {
    param($a, $b, $c);
    "a: $a; b: $b; c:$c"
}

# partially apply with -c parameter
$f = merge-parameter (gcm test) -c 5

# partially apply with -c and -a then execute with -b (papp is an alias)
&amp;amp; (papp (papp (gcm test) -c 3) -a 2) -b 7

# partially apply the get-command cmdlet with -commandtype
# and assign the result to a new function
si function:get-function (papp (gcm get-command) -commandtype function)
&lt;/pre&gt;
&lt;p&gt;
This is by no means a complete implementation of a partial application framework for
powershell. The merge-parameter function (aliased to papp) currently only works with
the default parameterset and does not mirror any of the parameteric attributes in
the applied function or cmdlet. I'm not saying it couldn't do that, but this is purely
a proof of concept. The module is listed below and is also available from PoshCode
at &lt;a href="http://poshcode.org/1687" target="_blank"&gt;http://poshcode.org/1687&lt;/a&gt; 
&lt;/p&gt;
&lt;pre class="brush:powershell"&gt;# save as functional.psm1 and drop into your module path
Set-StrictMode -Version 2

$commonParameters = @("Verbose",
                      "Debug",
                      "ErrorAction",
                      "WarningAction",
                      "ErrorVariable",
                      "WarningVariable",
                      "OutVariable",
                      "OutBuffer")

&amp;lt;#
.SYNOPSIS
    Support function for partially-applied cmdlets and functions.
#&amp;gt;
function Get-ParameterDictionary {
    [outputtype([Management.Automation.RuntimeDefinedParameterDictionary])]
    [cmdletbinding()]
    param(
        [validatenotnull()]
        [management.automation.commandinfo]$CommandInfo,
        [validatenotnull()]
        [management.automation.pscmdlet]$PSCmdletContext = $PSCmdlet
    )
    
    # dictionary to hold dynamic parameters
    $rdpd = new-object Management.Automation.RuntimeDefinedParameterDictionary

    try {
        # grab parameters from function
        if ($CommandInfo.parametersets.count &amp;gt; 1) {
            $parameters = $CommandInfo.ParameterSets[[string]$CommandInfo.DefaultParameterSet].parameters
        } else {
            $parameters = $CommandInfo.parameters.getenumerator() | % {$CommandInfo.parameters[$_.key]}
        }        
                
        $parameters | % {
            
            write-verbose "testing $($_.name)"
                                    
            # skip common parameters        
            if ($commonParameters -like $_.Name) {                                  
                
                write-verbose "skipping common parameter $($_.name)"
                
            } else {
                
                $rdp = new-object management.automation.runtimedefinedparameter
                $rdp.Name = $_.Name
                $rdp.ParameterType = $_.ParameterType
                
                # tag new parameters to match this function's parameterset
                $pa = new-object system.management.automation.parameterattribute
                $pa.ParameterSetName = $PSCmdletContext.ParameterSetName
                $rdp.Attributes.Add($pa)
                
                $rdpd.add($_.Name, $rdp)
            }
            
        }
    } catch {
    
        Write-Warning "Error getting parameter dictionary: $_"
    }
    
    # return
    $rdpd
}

&amp;lt;#
.SYNOPSIS
    Function that accepts a FunctionInfo or CmdletInfo reference and one or more parameters
    and returns a FunctionInfo bound to those parameter(s) and their value(s.)
.DESCRIPTION
    Function that accepts a FunctionInfo or CmdletInfo reference and one or more parameters
    and returns a FunctionInfo bound to those parameter(s) and their value(s.)
    
    Any parameters "merged" into the function are removed from the available parameters for
    future invocations. Multiple chained merge-parameter calls are permitted.
.EXAMPLE

    First, we define a simple function:
    
    function test {
        param($a, $b, $c, $d);
        "a: $a; b: $b; c:$c; d:$d"
    }
    
    Now we merge -b parameter into functioninfo with the static value of 5, returning a new
    functioninfo:
    
    ps&amp;gt; $x = merge-parameter (gcm test) -b 5
    
    We execute the new functioninfo with the &amp;amp; (call) operator, passing in the remaining 
    arguments:
    
    ps&amp;gt; &amp;amp; $x -a 2 -c 4 -d 9
    a: 2; b: 5; c: 4; d: 9
    
    Now we merge two new parameters in, -c with the value 3 and -d with 5:
    
    ps&amp;gt; $y = merge-parameter $x -c 3 -d 5
    
    Again we call $y with the remaining named parameter -a:
    
    ps&amp;gt; &amp;amp; $y -a 2
    a: 2; b: 5; c: 3; d: 5
.EXAMPLE

    Cmdlets can also be subject to partial application. In this case we create a new
    function with the returned functioninfo:
    
    ps&amp;gt; si function:get-function (merge-parameter (gcm get-command) -commandtype function)
    ps&amp;gt; get-function
    
&lt;lists  ?function? commandtype of commands all&gt;
.PARAMETER _CommandInfo The FunctionInfo or CmdletInfo into which to merge (apply)
parameter(s.) The parameter is named with a leading underscore character to prevent
parameter collisions when exposing the targetted command's parameters and dynamic
parameters. .INPUTS FunctionInfo or CmdletInfo .OUTPUTS FunctionInfo #&amp;gt; function
Merge-Parameter { [OutputType([Management.Automation.FunctionInfo])] [CmdletBinding()]
param( [parameter(position=0, mandatory=$true)] [validatenotnull()] [validatescript({
($_ -is [management.automation.functioninfo]) -or ` ($_ -is [management.automation.cmdletinfo])
})] [management.automation.commandinfo]$_Command ) dynamicparam { # strict mode compatible
check for parameter if ((test-path variable:_command)) { # attach input functioninfo's
parameters to self Get-ParameterDictionary $_Command $PSCmdlet } } begin { write-verbose
"merge-parameter: begin" # copy our bound parameters, except common ones $mergedParameters
= new-object 'collections.generic.dictionary[string,object]' $PSBoundParameters #
remove our parameters, leaving only target function/CommandInfo's args to curry in
$mergedParameters.remove("_Command") &amp;gt; $null # remove common parameters $commonParameters
| % { if ($mergedParameters.ContainsKey($_)) { $mergedParameters.Remove($_) &amp;gt; $null
} } } process { write-verbose "merge-parameter: process" # temporary function name
$temp = [guid]::NewGuid() $target = $_Command # splat our fixed named parameter(s)
and then splat remaining args $partial = { [cmdletbinding()] param() # begin dynamicparam
dynamicparam { $targetRdpd = Get-ParameterDictionary $target $PSCmdlet # remove fixed
parameters $mergedParameters.keys | % { $targetRdpd.remove($_) &amp;gt; $null } $targetRdpd
} begin { write-verbose "i have $($mergedParameters.count) fixed parameter(s)." write-verbose
"i have $($targetrdpd.count) remaining parameter(s)" } # end dynamicparam process
{ $boundParameters = $PSCmdlet.MyInvocation.BoundParameters # remove common parameters
(verbose, whatif etc) $commonParameters | % { if ($boundParameters.ContainsKey($_))
{ $boundParameters.Remove($_) &amp;gt; $null } } # invoke command with fixed parameters
and passed parameters (all named) . $target @mergedParameters @boundParameters if
($args) { write-warning "received $($args.count) arg(s) not part of function." } }
} # emit function/CommandInfo new-item -Path function:$temp -Value $partial.GetNewClosure()
} end { # cleanup rm function:$temp } } new-alias papp Merge-Parameter -force Export-ModuleMember
-Alias papp -Function Merge-Parameter, Get-ParameterDictionary 
&lt;/pre&gt;
&lt;p&gt;
Have fun[ctional]!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=d670cb31-373a-41bc-8633-c5d102fd308d" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,d670cb31-373a-41bc-8633-c5d102fd308d.aspx</comments>
      <category>Closures</category>
      <category>Cmdlets</category>
      <category>Functional Programming</category>
      <category>Functions</category>
      <category>Modules</category>
      <category>Monad</category>
      <category>PowerShell</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=c7d2809a-49cc-492c-88dc-1af937dd360a</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,c7d2809a-49cc-492c-88dc-1af937dd360a.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,c7d2809a-49cc-492c-88dc-1af937dd360a.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=c7d2809a-49cc-492c-88dc-1af937dd360a</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Paths in PowerShell are tough to understand [at first.] PowerShell Paths - or PSPaths,
not to be confused with Win32 paths - in their absolute forms, come in two distinct
flavours:
</p>
        <ul>
          <li>
Provider-qualified: FileSystem::<strong>c:\temp\foo.txt</strong></li>
          <li>
Drive-qualified: c:\temp\foo.txt</li>
        </ul>
        <p>
It's very easy to get confused over provider-internal (The <a href="http://msdn.microsoft.com/en-us/library/system.management.automation.pathinfo.providerpath(VS.85).aspx" target="_blank">ProviderPath</a> property
of a resolved <a href="http://msdn.microsoft.com/en-us/library/system.management.automation.pathinfo(VS.85).aspx" target="_blank">PathInfo</a> –
and the bold portion of the provider-qualified path above) and drive-qualified paths
since they look the same if you look at the default FileSystem provider drives. That
is to say, the PSDrive has the same name (C) as the native backing store, the windows
filesystem (C). So, to make it easier for yourself to understand the differences,
create yourself a new PSDrive:
</p>
        <p>
ps c:\&gt; new-psdrive temp filesystem c:\temp\<br />
ps c:\&gt; cd temp:<br />
ps temp:\&gt;
</p>
        <p>
Now, let's look at this again:
</p>
        <ul>
          <li>
Provider-qualified: FileSystem::<strong>c:\temp\foo.txt</strong></li>
          <li>
Drive-qualified: temp:\foo.txt</li>
        </ul>
        <p>
A bit easier this time to see what’s different this time. The bold text to the right
of the provider name is the ProviderPath.
</p>
        <p>
So, your goals for writing a generalized provider-friendly Cmdlet (or advanced function)
that accepts paths are:
</p>
        <ul>
          <li>
Define a LiteralPath path parameter aliased to PSPath</li>
          <li>
Define a Path parameter (which will resolve wildcards / glob)</li>
          <li>
Assume you are receiving PSPaths, <strong>NOT</strong> native provider-paths</li>
        </ul>
        <p>
Point number three is especially important. Also, obviously LiteralPath and Path should
belong in mutually exclusive parameter sets. 
</p>
        <p>
          <strong>Relative Paths</strong>
        </p>
        <p>
A good question is: how do we deal with relative paths being passed to a Cmdlet. As
you should assume all paths being given to you are PSPaths,  let’s look at what
the Cmdlet below does:
</p>
        <p>
ps temp:\&gt; write-zip -literalpath foo.txt
</p>
        <p>
The command should assume foo.txt is in the current drive, so this should be resolved
immediately in the ProcessRecord or EndProcessing block like (using the scripting
API here to demo):
</p>
        <p>
$provider = $null;<br />
$drive = $null<br />
$providerPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("foo.txt",
[ref]$provider, [ref]$drive)<br /><br />
Now you everything you need to recreate the two absolute forms of PSPaths, and you
also have the native absolute ProviderPath. To create a provider-qualified PSPath
for foo.txt, use $provider.Name + “::” + $providerPath. If $drive is not null (your
current location might be provider-qualified in which case $drive will be null) then
you should use $drive.name + ":\" + $drive.CurrentLocation + "\" + "foo.txt" to get
a drive-qualified PSPath.
</p>
        <p>
Have fun!
</p>
        <img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=c7d2809a-49cc-492c-88dc-1af937dd360a" />
      </body>
      <title>PowerShell – The Patchwork of Paths, PSPaths and ProviderPaths</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,c7d2809a-49cc-492c-88dc-1af937dd360a.aspx</guid>
      <link>http://www.nivot.org/2010/03/05/PowerShellThePatchworkOfPathsPSPathsAndProviderPaths.aspx</link>
      <pubDate>Fri, 05 Mar 2010 06:02:31 GMT</pubDate>
      <description>&lt;p&gt;
Paths in PowerShell are tough to understand [at first.] PowerShell Paths - or PSPaths,
not to be confused with Win32 paths - in their absolute forms, come in two distinct
flavours:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Provider-qualified: FileSystem::&lt;strong&gt;c:\temp\foo.txt&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
Drive-qualified: c:\temp\foo.txt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
It's very easy to get confused over provider-internal (The &lt;a href="http://msdn.microsoft.com/en-us/library/system.management.automation.pathinfo.providerpath(VS.85).aspx" target="_blank"&gt;ProviderPath&lt;/a&gt; property
of a resolved &lt;a href="http://msdn.microsoft.com/en-us/library/system.management.automation.pathinfo(VS.85).aspx" target="_blank"&gt;PathInfo&lt;/a&gt; –
and the bold portion of the provider-qualified path above) and drive-qualified paths
since they look the same if you look at the default FileSystem provider drives. That
is to say, the PSDrive has the same name (C) as the native backing store, the windows
filesystem (C). So, to make it easier for yourself to understand the differences,
create yourself a new PSDrive:
&lt;/p&gt;
&lt;p&gt;
ps c:\&amp;gt; new-psdrive temp filesystem c:\temp\&lt;br&gt;
ps c:\&amp;gt; cd temp:&lt;br&gt;
ps temp:\&amp;gt;
&lt;/p&gt;
&lt;p&gt;
Now, let's look at this again:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Provider-qualified: FileSystem::&lt;strong&gt;c:\temp\foo.txt&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
Drive-qualified: temp:\foo.txt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
A bit easier this time to see what’s different this time. The bold text to the right
of the provider name is the ProviderPath.
&lt;/p&gt;
&lt;p&gt;
So, your goals for writing a generalized provider-friendly Cmdlet (or advanced function)
that accepts paths are:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Define a LiteralPath path parameter aliased to PSPath&lt;/li&gt;
&lt;li&gt;
Define a Path parameter (which will resolve wildcards / glob)&lt;/li&gt;
&lt;li&gt;
Assume you are receiving PSPaths, &lt;strong&gt;NOT&lt;/strong&gt; native provider-paths&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Point number three is especially important. Also, obviously LiteralPath and Path should
belong in mutually exclusive parameter sets. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Relative Paths&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
A good question is: how do we deal with relative paths being passed to a Cmdlet. As
you should assume all paths being given to you are PSPaths,&amp;nbsp; let’s look at what
the Cmdlet below does:
&lt;/p&gt;
&lt;p&gt;
ps temp:\&amp;gt; write-zip -literalpath foo.txt
&lt;/p&gt;
&lt;p&gt;
The command should assume foo.txt is in the current drive, so this should be resolved
immediately in the ProcessRecord or EndProcessing block like (using the scripting
API here to demo):
&lt;/p&gt;
&lt;p&gt;
$provider = $null;&lt;br&gt;
$drive = $null&lt;br&gt;
$providerPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("foo.txt",
[ref]$provider, [ref]$drive)&lt;br&gt;
&lt;br&gt;
Now you everything you need to recreate the two absolute forms of PSPaths, and you
also have the native absolute ProviderPath. To create a provider-qualified PSPath
for foo.txt, use $provider.Name + “::” + $providerPath. If $drive is not null (your
current location might be provider-qualified in which case $drive will be null) then
you should use $drive.name + ":\" + $drive.CurrentLocation + "\" + "foo.txt" to get
a drive-qualified PSPath.
&lt;/p&gt;
&lt;p&gt;
Have fun!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=c7d2809a-49cc-492c-88dc-1af937dd360a" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,c7d2809a-49cc-492c-88dc-1af937dd360a.aspx</comments>
      <category>Cmdlets</category>
      <category>Functions</category>
      <category>Monad</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
      <category>PSPath</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=2cb1ab35-ec6b-40bb-b917-db1630560e72</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,2cb1ab35-ec6b-40bb-b917-db1630560e72.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,2cb1ab35-ec6b-40bb-b917-db1630560e72.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=2cb1ab35-ec6b-40bb-b917-db1630560e72</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
PowerShell guru and Admin-extraordinare <a href="http://www.jdhitsolutions.com/" target="_blank">Jeff
Hicks</a> asked a great question that many a Windows administrator has probably asked
themselves when working with Hashtables in PowerShell: Why do the key/values come
out in a different order than put in? This is a great question and the answer lies
in computer science theory, particularly computational complexity theory. Rather than
bore you with a <a href="http://en.wikipedia.org/wiki/Big_O_notation" target="_blank"><strong>ton
of nonsense about O(1), O(n)</strong></a> and other <a href="http://en.wikipedia.org/wiki/Hash_table" target="_blank">propeller-head
dribble</a>, I figure I could explain it in terms everyone should be able to understand.
</p>
        <h4>Hashtables, Buckets and HashCodes = Rolodex, Index Cards and Surnames<a href="http://www.nivot.org/content/binary/WindowsLiveWriter/PowerShellWhyarekeysinHashtablessortedra_E213/card-index_2.jpg"><img style="border-right-width: 0px; margin: 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="card-index" border="0" alt="card-index" align="right" src="http://www.nivot.org/content/binary/WindowsLiveWriter/PowerShellWhyarekeysinHashtablessortedra_E213/card-index_thumb.jpg" width="130" height="88" /></a></h4>
        <p>
Yes, if the light hasn’t gone on yet, it will soon. Every .NET object includes a method
called GetHashCode. This method returns a number that represents the identity of the
object in a kind of fuzzy way. I say “fuzzy” because the hash code for a given instance
of an object can be different on different platforms (xp, vista, 2003 etc) or on different
bitness (64 vs 32 bit.) This method is used by hashtable to get the “surname” of an
object. Instead of Index Cards, a Hashtable uses “buckets” to separate groups of objects.
Any given Hashcode will naturally fall into a particular bucket as the function (result)
of a high-speed optimized algorithm, much like any given surname naturally falls under
a particular letter of the alphabet. Finally, it should be clear to you that using
index cards [Hashtable buckets] is way faster than flicking through an unsorted folder
[randomized list.]
</p>
        <p>
Just like a Rolodex, the order you add names to it doesn’t dictate the order they
are in as you flip through the cards sequentially, which is analogous to sending a
Hashtable to out-default.
</p>
        <img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=2cb1ab35-ec6b-40bb-b917-db1630560e72" />
      </body>
      <title>PowerShell - Why are keys in Hashtables sorted randomly?</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,2cb1ab35-ec6b-40bb-b917-db1630560e72.aspx</guid>
      <link>http://www.nivot.org/2010/02/24/PowerShellWhyAreKeysInHashtablesSortedRandomly.aspx</link>
      <pubDate>Wed, 24 Feb 2010 22:38:55 GMT</pubDate>
      <description>&lt;p&gt;
PowerShell guru and Admin-extraordinare &lt;a href="http://www.jdhitsolutions.com/" target="_blank"&gt;Jeff
Hicks&lt;/a&gt; asked a great question that many a Windows administrator has probably asked
themselves when working with Hashtables in PowerShell: Why do the key/values come
out in a different order than put in? This is a great question and the answer lies
in computer science theory, particularly computational complexity theory. Rather than
bore you with a &lt;a href="http://en.wikipedia.org/wiki/Big_O_notation" target="_blank"&gt;&lt;strong&gt;ton
of nonsense about O(1), O(n)&lt;/strong&gt;&lt;/a&gt; and other &lt;a href="http://en.wikipedia.org/wiki/Hash_table" target="_blank"&gt;propeller-head
dribble&lt;/a&gt;, I figure I could explain it in terms everyone should be able to understand.
&lt;/p&gt;
&lt;h4&gt;Hashtables, Buckets and HashCodes = Rolodex, Index Cards and Surnames&lt;a href="http://www.nivot.org/content/binary/WindowsLiveWriter/PowerShellWhyarekeysinHashtablessortedra_E213/card-index_2.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="card-index" border="0" alt="card-index" align="right" src="http://www.nivot.org/content/binary/WindowsLiveWriter/PowerShellWhyarekeysinHashtablessortedra_E213/card-index_thumb.jpg" width="130" height="88"&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;
Yes, if the light hasn’t gone on yet, it will soon. Every .NET object includes a method
called GetHashCode. This method returns a number that represents the identity of the
object in a kind of fuzzy way. I say “fuzzy” because the hash code for a given instance
of an object can be different on different platforms (xp, vista, 2003 etc) or on different
bitness (64 vs 32 bit.) This method is used by hashtable to get the “surname” of an
object. Instead of Index Cards, a Hashtable uses “buckets” to separate groups of objects.
Any given Hashcode will naturally fall into a particular bucket as the function (result)
of a high-speed optimized algorithm, much like any given surname naturally falls under
a particular letter of the alphabet. Finally, it should be clear to you that using
index cards [Hashtable buckets] is way faster than flicking through an unsorted folder
[randomized list.]
&lt;/p&gt;
&lt;p&gt;
Just like a Rolodex, the order you add names to it doesn’t dictate the order they
are in as you flip through the cards sequentially, which is analogous to sending a
Hashtable to out-default.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=2cb1ab35-ec6b-40bb-b917-db1630560e72" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,2cb1ab35-ec6b-40bb-b917-db1630560e72.aspx</comments>
      <category>.NET</category>
      <category>CTP3</category>
      <category>Monad</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=a10ddb33-447c-4f5d-a9f5-aef32b8fc008</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,a10ddb33-447c-4f5d-a9f5-aef32b8fc008.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,a10ddb33-447c-4f5d-a9f5-aef32b8fc008.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=a10ddb33-447c-4f5d-a9f5-aef32b8fc008</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Did you know that when you run Get-Help against a cmdlet to find out about its parameters,
you might not be getting the whole truth? Certain cmdlets, especially those that operate
on providers (FileSystem, Certificate, Registry etc) can adopt new parameters on the
fly, depending on the path they are acting on. For example, when use you Get-Content
on the file system (drive c: etc), it gets three new parameters in addition to the
static ones listed by Get-Help (but more about this later): Delimiter, Encoding and
Wait. 
</p>
        <h4>Determining Dynamic Parameters using Get-Help
</h4>
        <p>
Get-Help has a new parameter, –Path, which lets you give the help system some context
for determining dynamic parameters:
</p>
        <blockquote>
          <i>
            <p>
-Path &lt;string&gt;<br />
    Gets help that explains how the cmdlet works in the specified provider
path. Enter a Windows PowerShell provider path. 
</p>
            <p>
    This parameter gets a customized version of a cmdlet help topic
that explains how the cmdlet works in the specified Windows PowerShell provider path.
This parameter is effective only for help about a provider cmdlet and only when the
provider includes a custom version of the provider cmdlet help topic. 
</p>
            <p>
    To see the custom cmdlet help for a provider path, go to the provider
path location and enter a Get-Help command or, from any path location, use the Path
parameter of Get-Help to specify the provider path. For more information, see about_Providers.
</p>
          </i>
        </blockquote>
        <h4>Determining Dynamic Parameters using Get-Command
</h4>
        <p>
Get-Command has a new parameter, –ArgumentList, which acts similarly to unveil what
dynamic parameters might be attached to a cmdlet for a given parameterset and path/literalpath
if available on the chosen cmdlet. I’ve written a simple function that takes a cmdlet
name as an argument and will display all of the dynamic parameters available for a
cmdlet for each distinct provider:
</p>
        <pre class="brush:powershell"># this function will pass a drive name in position 0 as an unnamed argument
# most path-oriented cmdlets accept this binding
function Get-DynamicParameter {
    param(        
        [string]$command
    ) 
  
    $parameters = @{}
    get-psdrive | sort -unique provider | % {
        $parameters[$_.provider.name] = gcm $command -args "$($_.name):" | % {
            $c = $_; @($_.parameters.keys) | sort | ? {
                $c.parameters[$_].isdynamic
            }
        }
    }
    $parameters    
}</pre>
        <p>
Example use:
</p>
        <pre style="font-family: courier; font-size: 11pt">PS&gt; Get-DynamicParameter get-content

Name                           Value
----                           -----
Alias
FileSystem                     {Delimiter, Encoding, Wait}
AssemblyCache
Registry
Environment
WSMan
Certificate
FeedStore
Function
Variable
PscxSettings</pre>
        <p>
          <strong>NOTE: </strong>when you don’t pass any context parameters to get-command via
–argumentlist, it will take your current location as the context for dynamic parameters
(if any are found.) So running get-command from c:\ instead hklm:\ will give you the
additional parameters Delimiter, Encoding and Wait.
</p>
        <p>
Have fun!
</p>
        <img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=a10ddb33-447c-4f5d-a9f5-aef32b8fc008" />
      </body>
      <title>PowerShell 2.0 - About Dynamic Parameters</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,a10ddb33-447c-4f5d-a9f5-aef32b8fc008.aspx</guid>
      <link>http://www.nivot.org/2010/01/18/PowerShell20AboutDynamicParameters.aspx</link>
      <pubDate>Mon, 18 Jan 2010 02:33:04 GMT</pubDate>
      <description>&lt;p&gt;
Did you know that when you run Get-Help against a cmdlet to find out about its parameters,
you might not be getting the whole truth? Certain cmdlets, especially those that operate
on providers (FileSystem, Certificate, Registry etc) can adopt new parameters on the
fly, depending on the path they are acting on. For example, when use you Get-Content
on the file system (drive c: etc), it gets three new parameters in addition to the
static ones listed by Get-Help (but more about this later): Delimiter, Encoding and
Wait. 
&lt;/p&gt;
&lt;h4&gt;Determining Dynamic Parameters using Get-Help
&lt;/h4&gt;
&lt;p&gt;
Get-Help has a new parameter, –Path, which lets you give the help system some context
for determining dynamic parameters:
&lt;/p&gt;
&lt;blockquote&gt;&lt;i&gt; 
&lt;p&gt;
-Path &amp;lt;string&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Gets help that explains how the cmdlet works in the specified provider
path. Enter a Windows PowerShell provider path. 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; This parameter gets a customized version of a cmdlet help topic
that explains how the cmdlet works in the specified Windows PowerShell provider path.
This parameter is effective only for help about a provider cmdlet and only when the
provider includes a custom version of the provider cmdlet help topic. 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; To see the custom cmdlet help for a provider path, go to the provider
path location and enter a Get-Help command or, from any path location, use the Path
parameter of Get-Help to specify the provider path. For more information, see about_Providers.
&lt;/p&gt;
&lt;/i&gt;&lt;/blockquote&gt; 
&lt;h4&gt;Determining Dynamic Parameters using Get-Command
&lt;/h4&gt;
&lt;p&gt;
Get-Command has a new parameter, –ArgumentList, which acts similarly to unveil what
dynamic parameters might be attached to a cmdlet for a given parameterset and path/literalpath
if available on the chosen cmdlet. I’ve written a simple function that takes a cmdlet
name as an argument and will display all of the dynamic parameters available for a
cmdlet for each distinct provider:
&lt;/p&gt;
&lt;pre class="brush:powershell"&gt;# this function will pass a drive name in position 0 as an unnamed argument
# most path-oriented cmdlets accept this binding
function Get-DynamicParameter {
    param(        
        [string]$command
    ) 
  
    $parameters = @{}
    get-psdrive | sort -unique provider | % {
        $parameters[$_.provider.name] = gcm $command -args "$($_.name):" | % {
            $c = $_; @($_.parameters.keys) | sort | ? {
                $c.parameters[$_].isdynamic
            }
        }
    }
    $parameters    
}&lt;/pre&gt;
&lt;p&gt;
Example use:
&lt;/p&gt;
&lt;pre style="font-family: courier; font-size: 11pt"&gt;PS&amp;gt; Get-DynamicParameter get-content

Name                           Value
----                           -----
Alias
FileSystem                     {Delimiter, Encoding, Wait}
AssemblyCache
Registry
Environment
WSMan
Certificate
FeedStore
Function
Variable
PscxSettings&lt;/pre&gt;
&lt;p&gt;
&lt;strong&gt;NOTE: &lt;/strong&gt;when you don’t pass any context parameters to get-command via
–argumentlist, it will take your current location as the context for dynamic parameters
(if any are found.) So running get-command from c:\ instead hklm:\ will give you the
additional parameters Delimiter, Encoding and Wait.
&lt;/p&gt;
&lt;p&gt;
Have fun!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=a10ddb33-447c-4f5d-a9f5-aef32b8fc008" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,a10ddb33-447c-4f5d-a9f5-aef32b8fc008.aspx</comments>
      <category>Cmdlets</category>
      <category>Monad</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
      <category>Providers</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=2b297e92-f5cf-4c08-afd4-e50579878b99</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,2b297e92-f5cf-4c08-afd4-e50579878b99.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,2b297e92-f5cf-4c08-afd4-e50579878b99.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=2b297e92-f5cf-4c08-afd4-e50579878b99</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of the things that never quite fit well with me with the remoting feature in PowerShell
2.0 is that while you can “telnet” to remote systems with Enter-PSSession and import
commands and do all sorts of cool tricks, there is no way to send or retrieve files
from the console. It seems like such a waste that you configure WinRM up with SSL
and Kerberos and get this nice encrypted channel up, but if you want to transfer files
you have to revert to file shares, remote desktop or classic ftp. 
</p>
        <p>
Back in the “good ole’ days” of BBSs and <a href="http://en.wikipedia.org/wiki/FidoNet" target="_blank">FidoNet</a>,
people used to use simple protocols like <a href="http://en.wikipedia.org/wiki/XModem" target="_blank">XModem</a> (advancing
to YModem and then ZModem) or Kermit that worked by streaming character data directly
to your terminal. It wasn’t fast or particularly efficient, but it got the job done.
I thought I’d take a crack at building something similar for PowerShell, and this
first 0.5 release is the fruits of this weekend’s tinkering. At the moment it only
can “pull” a file to the local system from a remote session, but the next release
will allow “pushing” a file from a local system to a remote session. 
</p>
        <p>
          <a href="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0IntroducingthePModemFileTransferPro_11813/image_2.png">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0IntroducingthePModemFileTransferPro_11813/image_thumb.png" width="973" height="311" />
          </a>
        </p>
        <p>
The reason I named it after XModem is because it works in a similar way: files are
not “pulled” from the remote server, but instead are “pushed.” X[YZ]Modem file transfer
was initiated by the remote end. I’ll not spoil the fun by explaining how it works,
but I think you’ll enjoy pulling it apart. It’s in a module format and is implemented
in pure script. 
</p>
        <h4>Requirements
</h4>
        <ul>
          <li>
PowerShell 2.0 installed on both client and server with remoting enabled <em>to</em> the
location of the file being transferred.</li>
        </ul>
        <blockquote>
          <p>
            <em>E.g. if you want to grab a file using Get-RemoteFile from a remote server, you
must be able to create a valid PSSession to it with the New-PSSession cmdlet. When
Send-LocalFile is implemented, you’ll need remoting enabled in the other direction
too. </em>
          </p>
        </blockquote>
        <ul>
          <li>
The PMODEM module must be findable on both the client and server via import-module
and must be the same version.</li>
        </ul>
        <p>
Here’s the Get-RemoteFile function help (via –?):
</p>
        <pre style="background-color: #eeeeee; margin: 8px; font-size: 10pt">NAME
    Get-RemoteFile

SYNOPSIS
    Retrieves a file from a remote computer via a supplied PSession.


SYNTAX
    Get-RemoteFile [-Session] &lt;pssession&gt; [-RemoteFile] &lt;string&gt; [[-LocalPath] &lt;string&gt;] [[-PacketSize] &lt;int32&gt;]
	[-PassThru] [-AsJob] [&lt;commonparameters&gt;]


DESCRIPTION
    Retrieves a remote file from a server via a supplied PSSession. All communication
    is performed out-of-band, yet inside the secure WinRM channel.

    No other ports, file shares or any other special configuration is needed. However,
    the PMODEM module must be on the remote computer and findable in its $ENV:PSModulePath;
    the protocol versions must also match on both ends. You will be warned of any
    misconfiguration(s).

    When not running asynchronously, progress records are generated.


RELATED LINKS

REMARKS
    To see the examples, type: "get-help Get-RemoteFile -examples".
    For more information, type: "get-help Get-RemoteFile -detailed".
    For technical information, type: "get-help Get-RemoteFile -full".
</pre>
        <p>
        </p>
        <p>
Things coming in later releases: wildcards/multiple file support, compression and
integration via proxy functions (copy-item/move-item/remove-item/rename-item etc).
</p>
        <h4>Download PModem
</h4>
        <p>
Grab <a href="http://www.nivot.org/content/binary/pmodem-0.5.zip" target="_blank">pmodem-0.5.zip</a> and
unzip it into a folder in your $ENV:PSModulePath on the client and server computers
you want to use PMODEM on.
</p>
        <p>
Have fun!
</p>
        <img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=2b297e92-f5cf-4c08-afd4-e50579878b99" />
      </body>
      <title>PowerShell 2.0 – Introducing the PModem File Transfer Protocol</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,2b297e92-f5cf-4c08-afd4-e50579878b99.aspx</guid>
      <link>http://www.nivot.org/2009/11/02/PowerShell20IntroducingThePModemFileTransferProtocol.aspx</link>
      <pubDate>Mon, 02 Nov 2009 01:57:10 GMT</pubDate>
      <description>&lt;p&gt;
One of the things that never quite fit well with me with the remoting feature in PowerShell
2.0 is that while you can “telnet” to remote systems with Enter-PSSession and import
commands and do all sorts of cool tricks, there is no way to send or retrieve files
from the console. It seems like such a waste that you configure WinRM up with SSL
and Kerberos and get this nice encrypted channel up, but if you want to transfer files
you have to revert to file shares, remote desktop or classic ftp. 
&lt;/p&gt;
&lt;p&gt;
Back in the “good ole’ days” of BBSs and &lt;a href="http://en.wikipedia.org/wiki/FidoNet" target="_blank"&gt;FidoNet&lt;/a&gt;,
people used to use simple protocols like &lt;a href="http://en.wikipedia.org/wiki/XModem" target="_blank"&gt;XModem&lt;/a&gt; (advancing
to YModem and then ZModem) or Kermit that worked by streaming character data directly
to your terminal. It wasn’t fast or particularly efficient, but it got the job done.
I thought I’d take a crack at building something similar for PowerShell, and this
first 0.5 release is the fruits of this weekend’s tinkering. At the moment it only
can “pull” a file to the local system from a remote session, but the next release
will allow “pushing” a file from a local system to a remote session. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0IntroducingthePModemFileTransferPro_11813/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0IntroducingthePModemFileTransferPro_11813/image_thumb.png" width="973" height="311"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
The reason I named it after XModem is because it works in a similar way: files are
not “pulled” from the remote server, but instead are “pushed.” X[YZ]Modem file transfer
was initiated by the remote end. I’ll not spoil the fun by explaining how it works,
but I think you’ll enjoy pulling it apart. It’s in a module format and is implemented
in pure script. 
&lt;/p&gt;
&lt;h4&gt;Requirements
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
PowerShell 2.0 installed on both client and server with remoting enabled &lt;em&gt;to&lt;/em&gt; the
location of the file being transferred.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;E.g. if you want to grab a file using Get-RemoteFile from a remote server, you
must be able to create a valid PSSession to it with the New-PSSession cmdlet. When
Send-LocalFile is implemented, you’ll need remoting enabled in the other direction
too. &lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;
The PMODEM module must be findable on both the client and server via import-module
and must be the same version.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Here’s the Get-RemoteFile function help (via –?):
&lt;/p&gt;
&lt;pre style="background-color: #eeeeee; margin: 8px; font-size: 10pt"&gt;NAME
    Get-RemoteFile

SYNOPSIS
    Retrieves a file from a remote computer via a supplied PSession.


SYNTAX
    Get-RemoteFile [-Session] &amp;lt;pssession&amp;gt; [-RemoteFile] &amp;lt;string&amp;gt; [[-LocalPath] &amp;lt;string&amp;gt;] [[-PacketSize] &amp;lt;int32&amp;gt;]
	[-PassThru] [-AsJob] [&amp;lt;commonparameters&amp;gt;]


DESCRIPTION
    Retrieves a remote file from a server via a supplied PSSession. All communication
    is performed out-of-band, yet inside the secure WinRM channel.

    No other ports, file shares or any other special configuration is needed. However,
    the PMODEM module must be on the remote computer and findable in its $ENV:PSModulePath;
    the protocol versions must also match on both ends. You will be warned of any
    misconfiguration(s).

    When not running asynchronously, progress records are generated.


RELATED LINKS

REMARKS
    To see the examples, type: "get-help Get-RemoteFile -examples".
    For more information, type: "get-help Get-RemoteFile -detailed".
    For technical information, type: "get-help Get-RemoteFile -full".
&lt;/pre&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Things coming in later releases: wildcards/multiple file support, compression and
integration via proxy functions (copy-item/move-item/remove-item/rename-item etc).
&lt;/p&gt;
&lt;h4&gt;Download PModem
&lt;/h4&gt;
&lt;p&gt;
Grab &lt;a href="http://www.nivot.org/content/binary/pmodem-0.5.zip" target="_blank"&gt;pmodem-0.5.zip&lt;/a&gt; and
unzip it into a folder in your $ENV:PSModulePath on the client and server computers
you want to use PMODEM on.
&lt;/p&gt;
&lt;p&gt;
Have fun!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=2b297e92-f5cf-4c08-afd4-e50579878b99" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,2b297e92-f5cf-4c08-afd4-e50579878b99.aspx</comments>
      <category>Eventing</category>
      <category>Modules</category>
      <category>Monad</category>
      <category>PModem</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
      <category>Remoting</category>
      <category>Windows 7</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=8728c6eb-dd87-4153-ba51-0d021bd9ee0d</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,8728c6eb-dd87-4153-ba51-0d021bd9ee0d.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,8728c6eb-dd87-4153-ba51-0d021bd9ee0d.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=8728c6eb-dd87-4153-ba51-0d021bd9ee0d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>
            <strong>UPDATE</strong>: Some general information on remoting: </em>
          <a title="Hey, Scripting Guy! Tell Me About Remoting in Windows PowerShell 2.0" href="http://blogs.technet.com/heyscriptingguy/archive/2009/10/29/hey-scripting-guy-october-29-2009.aspx">
            <em>Hey,
Scripting Guy! Tell Me About Remoting in Windows PowerShell 2.0</em>
          </a>
          <em>
            <strong>
              <br />
UPDATE 2: </strong>This also applies to machines not attached to a domain (thanks
@alexandair)</em>
        </p>
        <p>
If you’re running Windows 7 (and if not, why not?) you may have noticed that premium
versions include a license for Virtual XP Mode. (read more at <a title="http://www.microsoft.com/windows/virtual-pc/download.aspx" href="http://www.microsoft.com/windows/virtual-pc/download.aspx">http://www.microsoft.com/windows/virtual-pc/download.aspx</a>)
Essentially it’s an integrated version of Virtual PC with a full copy of Windows XP
SP2 running in it. It’s pretty nice – you can have programs from the virtualized XP
instance in your Windows 7 Start Menu and they can even share your desktop. 
</p>
        <h3>Problem
</h3>
        <p>
First thing you might think as a PowerShell fan is to put PowerShell v2.0 on Virtual
XP Mode so you can tinker around with PowerShell Remoting (don’t forget to install
.NET Framework 3.5 SP1 first!) Unfortunately it’s not all plain sailing as a default
security configuration in Virtual XP prevents the Enable-PSRemoting Cmdlet from succeeding:
</p>
        <pre style="padding-bottom: 2px; background-color: #dddddd; margin: 10px; padding-left: 2px; padding-right: 2px; font-size: 10pt; padding-top: 2px">PS C:\Documents and Settings\XPMUser&gt; Enable-PSRemoting

WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable this machine for remote management through WinRM service.
 This includes:
    1. Starting or restarting (if already started) the WinRM service
    2. Setting the WinRM service type to auto start
    3. Creating a listener to accept requests on any IP address
    4. Enabling firewall exception for WS-Management traffic (for http only).

Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.

Set-WSManQuickConfig : 
<f:wsmanfault xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" code="5" machine="V&#xA;irtualXP-27806"><f:message>Access is denied. </f:message></f:wsmanfault>
At line:50 char:33 + Set-WSManQuickConfig &lt;&lt;&lt;&lt; -force + CategoryInfo :
InvalidOperation: (:) [Set-WSManQuickConfig], InvalidOperationException + FullyQualifiedErrorId
: WsManError,Microsoft.WSMan.Management.SetWSManQuickConfigCommand </pre>
        <h3>Resolution
</h3>
        <p>
Thankfully, it’s a quick fix; log into VXP and perform Start &gt; Run… “gpedit.msc”
and navigate your way to:
</p>
        <p>
          <strong>Computer Configuration &gt; Windows Settings &gt; Security Settings &gt; Local
Policies &gt; Security Options</strong>
        </p>
        <p>
…and change: <strong>Network access: Sharing and security model for local accounts</strong></p>
        <p>
…to: <strong>Classic – local users authenticate as themselves.</strong></p>
        <p>
Now run Enable-PSRemoting again and it should work. No need to reboot!
</p>
        <p>
          <a href="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0EnablingRemotingwithVirtualXPModeon_B833/fix_gpo_security_network_access.png">
            <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="fix_gpo_security_network_access" border="0" alt="fix_gpo_security_network_access" src="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0EnablingRemotingwithVirtualXPModeon_B833/fix_gpo_security_network_access_thumb.png" width="640" height="391" />
          </a>
        </p>
        <img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=8728c6eb-dd87-4153-ba51-0d021bd9ee0d" />
      </body>
      <title>PowerShell 2.0 - Enabling Remoting with Virtual XP Mode on Windows 7</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,8728c6eb-dd87-4153-ba51-0d021bd9ee0d.aspx</guid>
      <link>http://www.nivot.org/2009/10/30/PowerShell20EnablingRemotingWithVirtualXPModeOnWindows7.aspx</link>
      <pubDate>Fri, 30 Oct 2009 17:46:44 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: Some general information on remoting: &lt;/em&gt;&lt;a title="Hey, Scripting Guy! Tell Me About Remoting in Windows PowerShell 2.0" href="http://blogs.technet.com/heyscriptingguy/archive/2009/10/29/hey-scripting-guy-october-29-2009.aspx"&gt;&lt;em&gt;Hey,
Scripting Guy! Tell Me About Remoting in Windows PowerShell 2.0&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt;
&lt;br&gt;
UPDATE 2: &lt;/strong&gt;This also applies to machines not attached to a domain (thanks
@alexandair)&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
If you’re running Windows 7 (and if not, why not?) you may have noticed that premium
versions include a license for Virtual XP Mode. (read more at &lt;a title="http://www.microsoft.com/windows/virtual-pc/download.aspx" href="http://www.microsoft.com/windows/virtual-pc/download.aspx"&gt;http://www.microsoft.com/windows/virtual-pc/download.aspx&lt;/a&gt;)
Essentially it’s an integrated version of Virtual PC with a full copy of Windows XP
SP2 running in it. It’s pretty nice – you can have programs from the virtualized XP
instance in your Windows 7 Start Menu and they can even share your desktop. 
&lt;/p&gt;
&lt;h3&gt;Problem
&lt;/h3&gt;
&lt;p&gt;
First thing you might think as a PowerShell fan is to put PowerShell v2.0 on Virtual
XP Mode so you can tinker around with PowerShell Remoting (don’t forget to install
.NET Framework 3.5 SP1 first!) Unfortunately it’s not all plain sailing as a default
security configuration in Virtual XP prevents the Enable-PSRemoting Cmdlet from succeeding:
&lt;/p&gt;
&lt;pre style="padding-bottom: 2px; background-color: #dddddd; margin: 10px; padding-left: 2px; padding-right: 2px; font-size: 10pt; padding-top: 2px"&gt;PS C:\Documents and Settings\XPMUser&amp;gt; Enable-PSRemoting

WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable this machine for remote management through WinRM service.
 This includes:
    1. Starting or restarting (if already started) the WinRM service
    2. Setting the WinRM service type to auto start
    3. Creating a listener to accept requests on any IP address
    4. Enabling firewall exception for WS-Management traffic (for http only).

Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.

Set-WSManQuickConfig : 
&lt;f:wsmanfault xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" code="5" machine="V
irtualXP-27806"&gt;
&lt;f:message&gt;Access is denied. &lt;/f:message&gt;
&lt;/f:wsmanfault&gt;
At line:50 char:33 + Set-WSManQuickConfig &amp;lt;&amp;lt;&amp;lt;&amp;lt; -force + CategoryInfo :
InvalidOperation: (:) [Set-WSManQuickConfig], InvalidOperationException + FullyQualifiedErrorId
: WsManError,Microsoft.WSMan.Management.SetWSManQuickConfigCommand &lt;/pre&gt;
&lt;h3&gt;Resolution
&lt;/h3&gt;
&lt;p&gt;
Thankfully, it’s a quick fix; log into VXP and perform Start &amp;gt; Run… “gpedit.msc”
and navigate your way to:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Local
Policies &amp;gt; Security Options&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
…and change: &lt;strong&gt;Network access: Sharing and security model for local accounts&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
…to: &lt;strong&gt;Classic – local users authenticate as themselves.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Now run Enable-PSRemoting again and it should work. No need to reboot!
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0EnablingRemotingwithVirtualXPModeon_B833/fix_gpo_security_network_access.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="fix_gpo_security_network_access" border="0" alt="fix_gpo_security_network_access" src="http://www.nivot.org/content/binary/WindowsLiveWriter/Pow.0EnablingRemotingwithVirtualXPModeon_B833/fix_gpo_security_network_access_thumb.png" width="640" height="391"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=8728c6eb-dd87-4153-ba51-0d021bd9ee0d" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,8728c6eb-dd87-4153-ba51-0d021bd9ee0d.aspx</comments>
      <category>Monad</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
      <category>Remoting</category>
      <category>Virtual XP</category>
      <category>Windows 7</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=7b7a72ad-28d7-4a61-a5a1-3729cae67bd3</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,7b7a72ad-28d7-4a61-a5a1-3729cae67bd3.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,7b7a72ad-28d7-4a61-a5a1-3729cae67bd3.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=7b7a72ad-28d7-4a61-a5a1-3729cae67bd3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>( from: </em>
          <a title="http://support.microsoft.com/default.aspx/kb/968929" href="http://support.microsoft.com/default.aspx/kb/968929">
            <em>http://support.microsoft.com/default.aspx/kb/968929</em>
          </a>
          <em> –
downloads at foot of page )</em>
        </p>
        <p>
Windows PowerShell is a command-line shell and scripting language that is designed
for system administration and Automation. Built on the Microsoft .NET Framework, Windows
PowerShell enables IT professionals and developers to control and automate the administration
of Windows and applications.
</p>
        <p>
New features that are introduced in Windows PowerShell 2.0 include the following: 
</p>
        <ul>
          <li>
            <b>Remoting</b>
            <br />
Windows PowerShell 2.0 lets you run commands on one or more remote computers from
a single computer that is running Windows PowerShell. PowerShell remoting allows for
multiple ways of connecting. These ways include interactive (1:1), fan-out (1:many),
and fan-in (many:1 by using the IIS hosting model). 
</li>
          <li>
            <b>Integrated Scripting Environment</b>
            <br />
PowerShell Integrated Scripting Environment (ISE) enables you to run interactive commands
and edit and debug scripts in a graphical environment. The main features include color-coded
syntax, selective execution, graphical debugging, Unicode support, and context-sensitive
help. 
</li>
          <li>
            <b>Modules</b>
            <br />
Modules allow for script developers and administrators to partition and organize their
Windows PowerShell code in self-contained, reusable units. Code from a module executes
in its own self-contained context and does not affect the state outside the module. 
</li>
          <li>
            <b>Advanced functions</b>
            <br />
Advanced functions are functions that have the same capabilities and behavior as cmdlets.
However, they are written completely in the Windows PowerShell language, instead of
compiled C#. 
</li>
          <li>
            <b>Background jobs</b>
            <br />
Windows PowerShell 2.0 allows for running a command or expression asynchronously and
"in the background" without interacting with the console. 
</li>
          <li>
            <b>Eventing</b>
            <br />
This feature adds support to the Windows PowerShell engine infrastructure for listening,
forwarding, and acting on management and system events. 
</li>
          <li>
            <b>Script internationalization</b>
            <br />
This new feature enables Windows PowerShell scripts to display messages in the spoken
language that is specified by the UI culture setting on the user's computer. 
</li>
          <li>
            <b>Script debugging</b>
            <br />
New debugging features were added to Windows PowerShell that let you set breakpoints
on lines, columns, variables, and commands, and that let you specify the action that
occurs when the breakpoint is hit. 
</li>
          <li>
            <b>New cmdlets</b>
            <br />
Windows PowerShell 2.0 introduces over 100 built-in cmdlets. These cmdlets, excluding
other tasks, enables you to do computer-related, event log, and performance counter
management tasks.</li>
        </ul>
        <h3>WinRM 2.0
</h3>
        <p>
WinRM is the Microsoft implementation of WS-Management Protocol, a standard Simple
Object Access Protocol (SOAP)–based, firewall-friendly protocol that allows for hardware
and operating systems from different vendors to interoperate. The WS-Management Protocol
specification provides a common way for systems to access and exchange management
information across an IT infrastructure.
</p>
        <p>
WinRM 2.0 includes the following new features: 
</p>
        <ul>
          <li>
The WinRM Client Shell API provides functionality to create and manage shells and
shell operations, commands, and data streams on remote computers. 
</li>
          <li>
The WinRM Plug-in API provides functionality that enables a user to write plug-ins
by implementing certain APIs for supported resources and operations. 
</li>
          <li>
WinRM 2.0 introduces a hosting framework. Two hosting models are supported. One is
Internet Information Services (IIS)-based and the other is WinRM service-based. 
</li>
          <li>
Association traversal lets a user retrieve instances of Association classes by using
a standard filtering mechanism. 
</li>
          <li>
WinRM 2.0 supports delegating user credentials across multiple remote computers. 
</li>
          <li>
Users of WinRM 2.0 can use Windows PowerShell cmdlets for system management. 
</li>
          <li>
WinRM has added a specific set of quotas that provide a better quality of service
and allocate server resources to concurrent users. The WinRM quota set is based on
the quota infrastructure that is implemented for the IIS service.</li>
        </ul>
        <h3>System requirements
</h3>
        <p>
          <strong>WinRM 2.0</strong> and <strong>PowerShell 2.0</strong> can be installed on
the following supported operating systems: 
</p>
        <ul>
          <li>
Windows Server 2008 with Service Pack 2 
</li>
          <li>
Windows Server 2003 with Service Pack 2 
</li>
          <li>
Windows Vista with Service Pack 2 
</li>
          <li>
Windows Vista with Service Pack 1 
</li>
          <li>
Windows XP with Service Pack 3</li>
        </ul>
Windows PowerShell 2.0 requires the Microsoft .NET Framework 2.0 with Service Pack
1. 
<p><strong>BITS 4.0</strong></p>
BITS 4.0 can be installed on the following supported operating systems: 
<ul><li>
Windows Server 2008 with Service Pack 2 
</li><li>
Windows Vista with Service Pack 2 
</li><li>
Windows Vista with Service Pack 1</li></ul><img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=7b7a72ad-28d7-4a61-a5a1-3729cae67bd3" /></body>
      <title>PowerShell 2.0 goes RTM for ALL Platforms</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,7b7a72ad-28d7-4a61-a5a1-3729cae67bd3.aspx</guid>
      <link>http://www.nivot.org/2009/10/28/PowerShell20GoesRTMForALLPlatforms.aspx</link>
      <pubDate>Wed, 28 Oct 2009 14:27:29 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;( from: &lt;/em&gt;&lt;a title="http://support.microsoft.com/default.aspx/kb/968929" href="http://support.microsoft.com/default.aspx/kb/968929"&gt;&lt;em&gt;http://support.microsoft.com/default.aspx/kb/968929&lt;/em&gt;&lt;/a&gt;&lt;em&gt; –
downloads at foot of page )&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Windows PowerShell is a command-line shell and scripting language that is designed
for system administration and Automation. Built on the Microsoft .NET Framework, Windows
PowerShell enables IT professionals and developers to control and automate the administration
of Windows and applications.
&lt;/p&gt;
&lt;p&gt;
New features that are introduced in Windows PowerShell 2.0 include the following: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;Remoting&lt;/b&gt;
&lt;br&gt;
Windows PowerShell 2.0 lets you run commands on one or more remote computers from
a single computer that is running Windows PowerShell. PowerShell remoting allows for
multiple ways of connecting. These ways include interactive (1:1), fan-out (1:many),
and fan-in (many:1 by using the IIS hosting model). 
&lt;li&gt;
&lt;b&gt;Integrated Scripting Environment&lt;/b&gt;
&lt;br&gt;
PowerShell Integrated Scripting Environment (ISE) enables you to run interactive commands
and edit and debug scripts in a graphical environment. The main features include color-coded
syntax, selective execution, graphical debugging, Unicode support, and context-sensitive
help. 
&lt;li&gt;
&lt;b&gt;Modules&lt;/b&gt;
&lt;br&gt;
Modules allow for script developers and administrators to partition and organize their
Windows PowerShell code in self-contained, reusable units. Code from a module executes
in its own self-contained context and does not affect the state outside the module. 
&lt;li&gt;
&lt;b&gt;Advanced functions&lt;/b&gt;
&lt;br&gt;
Advanced functions are functions that have the same capabilities and behavior as cmdlets.
However, they are written completely in the Windows PowerShell language, instead of
compiled C#. 
&lt;li&gt;
&lt;b&gt;Background jobs&lt;/b&gt;
&lt;br&gt;
Windows PowerShell 2.0 allows for running a command or expression asynchronously and
"in the background" without interacting with the console. 
&lt;li&gt;
&lt;b&gt;Eventing&lt;/b&gt;
&lt;br&gt;
This feature adds support to the Windows PowerShell engine infrastructure for listening,
forwarding, and acting on management and system events. 
&lt;li&gt;
&lt;b&gt;Script internationalization&lt;/b&gt;
&lt;br&gt;
This new feature enables Windows PowerShell scripts to display messages in the spoken
language that is specified by the UI culture setting on the user's computer. 
&lt;li&gt;
&lt;b&gt;Script debugging&lt;/b&gt;
&lt;br&gt;
New debugging features were added to Windows PowerShell that let you set breakpoints
on lines, columns, variables, and commands, and that let you specify the action that
occurs when the breakpoint is hit. 
&lt;li&gt;
&lt;b&gt;New cmdlets&lt;/b&gt;
&lt;br&gt;
Windows PowerShell 2.0 introduces over 100 built-in cmdlets. These cmdlets, excluding
other tasks, enables you to do computer-related, event log, and performance counter
management tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;WinRM 2.0
&lt;/h3&gt;
&lt;p&gt;
WinRM is the Microsoft implementation of WS-Management Protocol, a standard Simple
Object Access Protocol (SOAP)–based, firewall-friendly protocol that allows for hardware
and operating systems from different vendors to interoperate. The WS-Management Protocol
specification provides a common way for systems to access and exchange management
information across an IT infrastructure.
&lt;/p&gt;
&lt;p&gt;
WinRM 2.0 includes the following new features: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
The WinRM Client Shell API provides functionality to create and manage shells and
shell operations, commands, and data streams on remote computers. 
&lt;li&gt;
The WinRM Plug-in API provides functionality that enables a user to write plug-ins
by implementing certain APIs for supported resources and operations. 
&lt;li&gt;
WinRM 2.0 introduces a hosting framework. Two hosting models are supported. One is
Internet Information Services (IIS)-based and the other is WinRM service-based. 
&lt;li&gt;
Association traversal lets a user retrieve instances of Association classes by using
a standard filtering mechanism. 
&lt;li&gt;
WinRM 2.0 supports delegating user credentials across multiple remote computers. 
&lt;li&gt;
Users of WinRM 2.0 can use Windows PowerShell cmdlets for system management. 
&lt;li&gt;
WinRM has added a specific set of quotas that provide a better quality of service
and allocate server resources to concurrent users. The WinRM quota set is based on
the quota infrastructure that is implemented for the IIS service.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;System requirements
&lt;/h3&gt;
&lt;p&gt;
&lt;strong&gt;WinRM 2.0&lt;/strong&gt; and &lt;strong&gt;PowerShell 2.0&lt;/strong&gt; can be installed on
the following supported operating systems: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Windows Server 2008 with Service Pack 2 
&lt;li&gt;
Windows Server 2003 with Service Pack 2 
&lt;li&gt;
Windows Vista with Service Pack 2 
&lt;li&gt;
Windows Vista with Service Pack 1 
&lt;li&gt;
Windows XP with Service Pack 3&lt;/li&gt;
&lt;/ul&gt;
Windows PowerShell 2.0 requires the Microsoft .NET Framework 2.0 with Service Pack
1. 
&lt;p&gt;
&lt;strong&gt;BITS 4.0&lt;/strong&gt;
&lt;/p&gt;
BITS 4.0 can be installed on the following supported operating systems: 
&lt;ul&gt;
&lt;li&gt;
Windows Server 2008 with Service Pack 2 
&lt;li&gt;
Windows Vista with Service Pack 2 
&lt;li&gt;
Windows Vista with Service Pack 1&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=7b7a72ad-28d7-4a61-a5a1-3729cae67bd3" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,7b7a72ad-28d7-4a61-a5a1-3729cae67bd3.aspx</comments>
      <category>.NET</category>
      <category>Cmdlets</category>
      <category>Microsoft</category>
      <category>Modules</category>
      <category>Monad</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=50a6639d-450d-4c70-b538-a9c9612e5d8c</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,50a6639d-450d-4c70-b538-a9c9612e5d8c.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,50a6639d-450d-4c70-b538-a9c9612e5d8c.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=50a6639d-450d-4c70-b538-a9c9612e5d8c</wfw:commentRss>
      <title>PowerShell 2.0 - Module Initializers</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,50a6639d-450d-4c70-b538-a9c9612e5d8c.aspx</guid>
      <link>http://www.nivot.org/2009/10/22/PowerShell20ModuleInitializers.aspx</link>
      <pubDate>Thu, 22 Oct 2009 03:05:08 GMT</pubDate>
      <description>&lt;p&gt;
You might not know it, but when you import a PowerShell module you can pass it one
or more arguments by way of Import-Module's -ArgumentList (aliased to -Args) parameter.
While it looks like passing parameters to a standard ps1 file, there are some limitations.
Take this module for an example:
&lt;/p&gt;
&lt;pre class="brush:powershell"&gt;# -- begin foo.psm1 --
param()
 
. {
  param(
     [validateset("a","b","c")]
     $letter
 
     function Get-Letter {
        "You initialized the module with $letter"
     }
} @args
# -- end foo.psm1

ps&amp;gt; import-module foo -args b
ps&amp;gt; get-letter
"You initialized the module with b"
&lt;/pre&gt;
&lt;p&gt;
You might notice that I am dotting (dot-sourcing or dot-executing) the scriptblock.
By doing this, you are ensuring that anything declared in the scriptblock is imported
into the calling scope. You can also apply advanced-function style validation to the
module initializer by splatting (@) the module arguments ($args). If the scriptblock
was called instead (via &amp;amp; { ... } @args) then the nested scope created from the
call (&amp;) operator prevents the function Get-Letter from being exported from the module
because it goes out of scope when the called scriptblock completes. So, why not put
the param block at the top of the module where param() is now you might ask? Because
that mechanism is broken and/or partially implemented in v2, and completely ignores
[cmdletbinding()] directives and validators. Note also that there is no way to use
switches in the traditional sense with module arguments; instead you can pass boolean
literals like $true or $false which will be mapped positionally to any declared switches. 
&lt;/p&gt;
&lt;p&gt;
So where might you use this technique of module initializers? You could create a generalized
custom module that works with your various development environments, or SQL clusters/servers.
You pass the name of the environment (or server) to the module on import, and all
of the functions exported then are "bound" to that cluster (or server) so you don't
have to continually pass each function the cluster (or server) name as an argument.
&lt;/p&gt;
&lt;p&gt;
Have fun! 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=50a6639d-450d-4c70-b538-a9c9612e5d8c" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,50a6639d-450d-4c70-b538-a9c9612e5d8c.aspx</comments>
      <category>Modules</category>
      <category>Monad</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=cf5692fe-f0ef-4dc7-aa9b-1473df68c984</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,cf5692fe-f0ef-4dc7-aa9b-1473df68c984.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,cf5692fe-f0ef-4dc7-aa9b-1473df68c984.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=cf5692fe-f0ef-4dc7-aa9b-1473df68c984</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <b>Updated</b>: now use a temporary file to set text to avoid overflowing command-line
buffer
</p>
        <p>
The Windows Clipboard – accessible via System.Windows.Forms.Clipboard – requires an
STA thread to read/write to it. By default, the console version of PowerShell 2.0
(i.e. not ISE) starts in MTA mode. This means that read/writing via this class is
unreliable. Rather than always starting up console PowerShell in STA mode via the
–STA flag, you can use this flag in a sneakier way to get what you want:<br /><br /></p>
        <pre class="brush:powershell">
function Set-ClipboardText {
        param($text)

        # need to use temp file to avoid exceeding command-line length limit
        $temp = [io.path]::GetTempFileName()

        try {
            set-content -Path $temp -Value $text

            $command = {
                    add-type -an system.windows.forms
                    [System.Windows.Forms.Clipboard]::SetText((get-content $args))
            }
            
            powershell -sta -noprofile -command $command -args $temp

        } finally {
            if ((test-path $temp)) {
                remove-item $temp
            }
        }
}

function Get-ClipboardText {
        $command = {
                add-type -an system.windows.forms
                [System.Windows.Forms.Clipboard]::GetText()
        }
        powershell -sta -noprofile -command $command
}</pre>
        <p>
Essentially we are running PowerShell as a child process temporarily in STA mode,
skipping loading the profile and executing a scriptblock.
</p>
        <img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=cf5692fe-f0ef-4dc7-aa9b-1473df68c984" />
      </body>
      <title>PowerShell 2.0 – Getting and setting text to and from the clipboard</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,cf5692fe-f0ef-4dc7-aa9b-1473df68c984.aspx</guid>
      <link>http://www.nivot.org/2009/10/14/PowerShell20GettingAndSettingTextToAndFromTheClipboard.aspx</link>
      <pubDate>Wed, 14 Oct 2009 15:53:35 GMT</pubDate>
      <description>&lt;p&gt;
&lt;b&gt;Updated&lt;/b&gt;: now use a temporary file to set text to avoid overflowing command-line
buffer
&lt;/p&gt;
&lt;p&gt;
The Windows Clipboard – accessible via System.Windows.Forms.Clipboard – requires an
STA thread to read/write to it. By default, the console version of PowerShell 2.0
(i.e. not ISE) starts in MTA mode. This means that read/writing via this class is
unreliable. Rather than always starting up console PowerShell in STA mode via the
–STA flag, you can use this flag in a sneakier way to get what you want:&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;pre class="brush:powershell"&gt;
function Set-ClipboardText {
        param($text)

        # need to use temp file to avoid exceeding command-line length limit
        $temp = [io.path]::GetTempFileName()

        try {
            set-content -Path $temp -Value $text

            $command = {
                    add-type -an system.windows.forms
                    [System.Windows.Forms.Clipboard]::SetText((get-content $args))
            }
            
            powershell -sta -noprofile -command $command -args $temp

        } finally {
            if ((test-path $temp)) {
                remove-item $temp
            }
        }
}

function Get-ClipboardText {
        $command = {
                add-type -an system.windows.forms
                [System.Windows.Forms.Clipboard]::GetText()
        }
        powershell -sta -noprofile -command $command
}&lt;/pre&gt;
&lt;p&gt;
Essentially we are running PowerShell as a child process temporarily in STA mode,
skipping loading the profile and executing a scriptblock.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=cf5692fe-f0ef-4dc7-aa9b-1473df68c984" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,cf5692fe-f0ef-4dc7-aa9b-1473df68c984.aspx</comments>
      <category>.NET</category>
      <category>Monad</category>
      <category>MTA</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
      <category>STA</category>
      <category>Threading</category>
    </item>
    <item>
      <trackback:ping>http://www.nivot.org/Trackback.aspx?guid=54bece4d-9670-4ac9-ae3c-6ad3ecbfd841</trackback:ping>
      <pingback:server>http://www.nivot.org/pingback.aspx</pingback:server>
      <pingback:target>http://www.nivot.org/PermaLink,guid,54bece4d-9670-4ac9-ae3c-6ad3ecbfd841.aspx</pingback:target>
      <dc:creator>Oisin Grehan</dc:creator>
      <wfw:comment>http://www.nivot.org/CommentView,guid,54bece4d-9670-4ac9-ae3c-6ad3ecbfd841.aspx</wfw:comment>
      <wfw:commentRss>http://www.nivot.org/SyndicationService.asmx/GetEntryCommentsRss?guid=54bece4d-9670-4ac9-ae3c-6ad3ecbfd841</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Asynchronous callback delegates are not a friend to PowerShell. They are serviced
by the .NET threadpool which means that if they point to script blocks, there will
be no Runspace available to execute them. Runspaces are thread-local resources in
the PowerShell threadpool. The .NET threadpool, operating independently, is not too
interested in coordinating callbacks with PowerShell. So what do we do? 
</p>
        <p>
There is one feature of PowerShell 2.0 that is capable of running scriptblocks in
a pseudo-asynchronous manner: Eventing. Any events bound to with Register-ObjectEvent,
EngineEvent or WmIEvent can have associated scriptblocks that will get executed when
the associated event is raised. So, if we can somehow convert an asynchronous callback
to a .NET event then we can run scriptblocks in response to Async .NET Callbacks.
I’ve written a simple function called New-ScriptBlockCallback that helps us do exactly
that:<br /></p>
        <pre class="brush:powershell">#requires -version 2.0

function New-ScriptBlockCallback {
    param(
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [scriptblock]$Callback
    )
&lt;#
    .SYNOPSIS
        Allows running ScriptBlocks via .NET async callbacks.

    .DESCRIPTION
        Allows running ScriptBlocks via .NET async callbacks. Internally this is
        managed by converting .NET async callbacks into .NET events. This enables
        PowerShell 2.0 to run ScriptBlocks indirectly through Register-ObjectEvent.         

    .PARAMETER Callback
        Specify a ScriptBlock to be executed in response to the callback.
        Because the ScriptBlock is executed by the eventing subsystem, it only has
        access to global scope. Any additional arguments to this function will be
        passed as event MessageData.
        
    .EXAMPLE
        You wish to run a scriptblock in reponse to a callback. Here is the .NET
        method signature:
        
        void Bar(AsyncCallback handler, int blah)
        
        ps&gt; [foo]::bar((New-ScriptBlockCallback { ... }), 42)                        

    .OUTPUTS
        A System.AsyncCallback delegate.
#&gt;
    # is this type already defined?    
    if (-not ("CallbackEventBridge" -as [type])) {
        Add-Type @"
            using System;
            
            public sealed class CallbackEventBridge
            {
                public event AsyncCallback CallbackComplete = delegate { };

                private CallbackEventBridge() {}

                private void CallbackInternal(IAsyncResult result)
                {
                    CallbackComplete(result);
                }

                public AsyncCallback Callback
                {
                    get { return new AsyncCallback(CallbackInternal); }
                }

                public static CallbackEventBridge Create()
                {
                    return new CallbackEventBridge();
                }
            }
"@
    }
    $bridge = [callbackeventbridge]::create()
    Register-ObjectEvent -input $bridge -EventName callbackcomplete -action $callback -messagedata $args &gt; $null
    $bridge.callback
}
</pre>
        <img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=54bece4d-9670-4ac9-ae3c-6ad3ecbfd841" />
      </body>
      <title>PowerShell 2.0 – Asynchronous Callbacks from .NET</title>
      <guid isPermaLink="false">http://www.nivot.org/PermaLink,guid,54bece4d-9670-4ac9-ae3c-6ad3ecbfd841.aspx</guid>
      <link>http://www.nivot.org/2009/10/09/PowerShell20AsynchronousCallbacksFromNET.aspx</link>
      <pubDate>Fri, 09 Oct 2009 18:09:30 GMT</pubDate>
      <description>&lt;p&gt;
Asynchronous callback delegates are not a friend to PowerShell. They are serviced
by the .NET threadpool which means that if they point to script blocks, there will
be no Runspace available to execute them. Runspaces are thread-local resources in
the PowerShell threadpool. The .NET threadpool, operating independently, is not too
interested in coordinating callbacks with PowerShell. So what do we do? 
&lt;/p&gt;
&lt;p&gt;
There is one feature of PowerShell 2.0 that is capable of running scriptblocks in
a pseudo-asynchronous manner: Eventing. Any events bound to with Register-ObjectEvent,
EngineEvent or WmIEvent can have associated scriptblocks that will get executed when
the associated event is raised. So, if we can somehow convert an asynchronous callback
to a .NET event then we can run scriptblocks in response to Async .NET Callbacks.
I’ve written a simple function called New-ScriptBlockCallback that helps us do exactly
that:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="brush:powershell"&gt;#requires -version 2.0

function New-ScriptBlockCallback {
    param(
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [scriptblock]$Callback
    )
&amp;lt;#
    .SYNOPSIS
        Allows running ScriptBlocks via .NET async callbacks.

    .DESCRIPTION
        Allows running ScriptBlocks via .NET async callbacks. Internally this is
        managed by converting .NET async callbacks into .NET events. This enables
        PowerShell 2.0 to run ScriptBlocks indirectly through Register-ObjectEvent.         

    .PARAMETER Callback
        Specify a ScriptBlock to be executed in response to the callback.
        Because the ScriptBlock is executed by the eventing subsystem, it only has
        access to global scope. Any additional arguments to this function will be
        passed as event MessageData.
        
    .EXAMPLE
        You wish to run a scriptblock in reponse to a callback. Here is the .NET
        method signature:
        
        void Bar(AsyncCallback handler, int blah)
        
        ps&amp;gt; [foo]::bar((New-ScriptBlockCallback { ... }), 42)                        

    .OUTPUTS
        A System.AsyncCallback delegate.
#&amp;gt;
    # is this type already defined?    
    if (-not ("CallbackEventBridge" -as [type])) {
        Add-Type @"
            using System;
            
            public sealed class CallbackEventBridge
            {
                public event AsyncCallback CallbackComplete = delegate { };

                private CallbackEventBridge() {}

                private void CallbackInternal(IAsyncResult result)
                {
                    CallbackComplete(result);
                }

                public AsyncCallback Callback
                {
                    get { return new AsyncCallback(CallbackInternal); }
                }

                public static CallbackEventBridge Create()
                {
                    return new CallbackEventBridge();
                }
            }
"@
    }
    $bridge = [callbackeventbridge]::create()
    Register-ObjectEvent -input $bridge -EventName callbackcomplete -action $callback -messagedata $args &amp;gt; $null
    $bridge.callback
}
&lt;/pre&gt;&lt;img width="0" height="0" src="http://www.nivot.org/aggbug.ashx?id=54bece4d-9670-4ac9-ae3c-6ad3ecbfd841" /&gt;</description>
      <comments>http://www.nivot.org/CommentView,guid,54bece4d-9670-4ac9-ae3c-6ad3ecbfd841.aspx</comments>
      <category>.NET</category>
      <category>Eventing</category>
      <category>Monad</category>
      <category>PowerShell</category>
      <category>PowerShell 2.0</category>
    </item>
  </channel>
</rss>