<?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>My Website</title>
	<atom:link href="http://jansveld.net/powershell/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://jansveld.net/powershell</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Wed, 09 Oct 2013 18:31:27 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.6.1</generator>
		<item>
		<title>Split-Job 0.93</title>
		<link>http://jansveld.net/powershell/?p=11</link>
		<comments>http://jansveld.net/powershell/?p=11#comments</comments>
		<pubDate>Mon, 22 Dec 2008 20:29:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[background]]></category>
		<category><![CDATA[concurrent]]></category>
		<category><![CDATA[parallel processing]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[pipeline]]></category>
		<category><![CDATA[runspace]]></category>
		<category><![CDATA[split-job]]></category>
		<category><![CDATA[wmi]]></category>

		<guid isPermaLink="false">http://www.jansveld.net/powershell/?p=8</guid>
		<description><![CDATA[Wow, it has been a long time since I had time to post anything on this blog. However, I have been making some improvements to the Split-Job script over the last few months and the results are below. I use this script myself a lot and I hope this is useful for some of you as well.  Please [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Wow, it has been a long time since I had time to post anything on this blog. However, I have been making some improvements to the Split-Job script over the last few months and the results are below. I use this script myself a lot and I hope this is useful for some of you as well.  Please see the <a title="Split-Job 0.92" href="http://www.jansveld.net/powershell/2008/06/split-job-092/">previous version </a>for more information about the concept and usage of Split-Job.</p>
<p>The changes are listed in the script comments. One aspect that deserves extra attention is the runspace environment. As before, the runspaces that process the pipeline objects do not necessarily have the same variables, functions etc. that your main PowerShell session contains. If you do need those, you now have two options:</p>
<ul>
<li>Specify the -UseProfile switch. This will load your PS profile, which should give you (most of) your snapins, functions and aliases. This is most useful when using Split-Job interactively at the console.</li>
<li>Import the specific functions, variables etc. you need by using the SnapIn, Function, Alias and Variable switches. Each of these can take multiple arguments and wildcards. This is more efficient when using Split-Job inside a script. </li>
</ul>
<p>I am actually considering making -UseProfile the default and creating the opposite -NoProfile switch instead. This will make it even easier to use Split-Job at the command line. In my case this does not slow things down considerably. If you want, you can exclude portions of your profile (e.g. PowerTab) by testing whether $SplitJobRunSpace exists. Feedback is welcome!</p>
<p>Enjoy,</p>
<p>Arnoud</p>
<pre><code>
<span style="color: #008000;">#</span><span style="color: #008000;">requires -version 1.0</span><span style="color: #008000;">
#</span><span style="color: #008000;">###############################################################################</span><span style="color: #008000;">
#</span><span style="color: #008000;"># Run commands in multiple concurrent pipelines</span><span style="color: #008000;">
#</span><span style="color: #008000;">#   by Arnoud Jansveld - www.jansveld.net/powershell</span><span style="color: #008000;">
#</span><span style="color: #008000;"># Version History</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.93   Improve error handling: errors originating in the Scriptblock now</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        have more meaningful output</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Show additional info in the progress bar (thanks Stephen Mills)</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add SnapIn parameter: imports (registered) PowerShell snapins</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add Function parameter: imports functions</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add SplitJobRunSpace variable; allows scripts to test if they are </span><span style="color: #008000;">
#</span><span style="color: #008000;">#        running in a runspace </span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add seconds remaining to progress bar (experimental)</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.92   Add UseProfile switch: imports the PS profile</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add Variable parameter: imports variables</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add Alias parameter: imports aliases</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Restart pipeline if it stops due to an error</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Set the current path in each runspace to that of the calling process</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.91   Revert to v 0.8 input syntax for the script block</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add error handling for empty input queue</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.9    Add logic to distinguish between scriptblocks and cmdlets or scripts:</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        if a ScriptBlock is specified, a foreach {} wrapper is added</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.8    Adds a progress bar</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.7    Stop adding runspaces if the queue is already empty</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.6    First version. Inspired by Gaurhoth's New-TaskPool script</span><span style="color: #008000;">
#</span><span style="color: #008000;">###############################################################################</span><span style="color: #008000;">
</span><span style="color: #000000;">
</span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Split-Job</span><span style="color: #000000;"> {
    </span><span style="color: #0000ff;">param</span><span style="color: #000000;"> (
        </span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> $(</span><span style="color: #0000ff;">throw</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">You must specify a command or script block!</span><span style="color: #800000;">'</span><span style="color: #000000;">),
        [</span><span style="color: #008080;">int</span><span style="color: #000000;">]</span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;">=</span><span style="color: #000000;">10</span><span style="color: #000000;">,
        [</span><span style="color: #008080;">switch</span><span style="color: #000000;">]</span><span style="color: #800080;">$UseProfile</span><span style="color: #000000;">,
        [</span><span style="color: #008080;">string</span><span style="color: #000000;">[]]</span><span style="color: #800080;">$Variable</span><span style="color: #000000;">,
        [</span><span style="color: #008080;">string</span><span style="color: #000000;">[]]</span><span style="color: #800080;">$Function</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> @(),
        [</span><span style="color: #008080;">string</span><span style="color: #000000;">[]]</span><span style="color: #800080;">$Alias</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> @(),
        [</span><span style="color: #008080;">string</span><span style="color: #000000;">[]]</span><span style="color: #800080;">$SnapIn</span><span style="color: #000000;">
    ) 

    </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Init</span><span style="color: #000000;"> (</span><span style="color: #800080;">$InputQueue</span><span style="color: #000000;">){
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create the shared thread-safe queue and fill it with the input objects</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Queue</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> [</span><span style="color: #008080;">Collections.Queue</span><span style="color: #000000;">]::</span><span style="color: #8b4513;">Synchronized</span><span style="color: #000000;">([</span><span style="color: #008080;">Collections.Queue</span><span style="color: #000000;">]@(</span><span style="color: #800080;">$InputQueue</span><span style="color: #000000;">))
        </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Do not create more runspaces than input objects</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-gt</span><span style="color: #000000;"> </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">) {</span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">}
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create the script to be run by each runspace</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Script</span><span style="color: #000000;">  </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Set-Location '$PWD'; </span><span style="color: #800000;">"</span><span style="color: #000000;">
        </span><span style="color: #800080;">$Script</span><span style="color: #000000;"> </span><span style="color: #ff0000;">+=</span><span style="color: #000000;"> {
            </span><span style="color: #800080;">$SplitJobQueue</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> $(</span><span style="color: #000080;">$Input</span><span style="color: #000000;">)
            &amp; {
                </span><span style="color: #0000ff;">trap</span><span style="color: #000000;"> {</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">}
                </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (</span><span style="color: #800080;">$SplitJobQueue</span><span style="color: #000000;">.Count) {</span><span style="color: #800080;">$SplitJobQueue</span><span style="color: #000000;">.Dequeue()}
            } |
        }.ToString() </span><span style="color: #ff0000;">+</span><span style="color: #000000;"> </span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;">

        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create an array to keep track of the set of pipelines</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">New-Object</span><span style="color: #000000;"> </span><span style="color: #800000;">System.Collections.ArrayList</span><span style="color: #000000;">

        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Collect the functions and aliases to import</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$ImportItems</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Function</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-replace</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">^</span><span style="color: #800000;">'</span><span style="color: #000000;">,</span><span style="color: #800000;">'</span><span style="color: #800000;">Function:</span><span style="color: #800000;">'</span><span style="color: #000000;">) </span><span style="color: #ff0000;">+</span><span style="color: #000000;">
            (</span><span style="color: #800080;">$Alias</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-replace</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">^</span><span style="color: #800000;">'</span><span style="color: #000000;">,</span><span style="color: #800000;">'</span><span style="color: #800000;">Alias:</span><span style="color: #800000;">'</span><span style="color: #000000;">) |
            </span><span style="font-weight: bold; color: #5f9ea0;">Get-Item</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">select</span><span style="color: #000000;"> </span><span style="color: #800000;">PSPath</span><span style="color: #000000;">, </span><span style="color: #800000;">Definition</span><span style="color: #000000;">
        </span><span style="color: #800080;">$stopwatch</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">New-Object</span><span style="color: #000000;"> </span><span style="color: #800000;">System.Diagnostics.Stopwatch</span><span style="color: #000000;">
        </span><span style="color: #800080;">$stopwatch</span><span style="color: #000000;">.Start()
    }

    </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Add-Pipeline</span><span style="color: #000000;"> {
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> This creates a new runspace and starts an asynchronous pipeline with our script.</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #008000;">#</span><span style="color: #008000;"> It will automatically start processing objects from the shared queue.</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> [</span><span style="color: #008080;">System.Management.Automation.Runspaces.RunspaceFactory</span><span style="color: #000000;">]::</span><span style="color: #8b4513;">CreateRunspace</span><span style="color: #000000;">(</span><span style="color: #000080;">$Host</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.Open()
        </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.SessionStateProxy.SetVariable(</span><span style="color: #800000;">'</span><span style="color: #800000;">SplitJobRunSpace</span><span style="color: #800000;">'</span><span style="color: #000000;">, </span><span style="color: #0000ff;">$True</span><span style="color: #000000;">)

        </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">CreatePipeline</span><span style="color: #000000;"> {
            </span><span style="color: #0000ff;">param</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Data</span><span style="color: #000000;">, </span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;">)
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.CreatePipeline(</span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;">)
            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Data</span><span style="color: #000000;">) {
                </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Write(</span><span style="color: #800080;">$Data</span><span style="color: #000000;">, </span><span style="color: #0000ff;">$True</span><span style="color: #000000;">)
                </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Close()
            }
            </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Invoke()
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Dispose()
        }

        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Optionally import profile, variables, functions and aliases from the main runspace</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$UseProfile</span><span style="color: #000000;">) {
            CreatePipeline -Script </span><span style="color: #800000;">"</span><span style="color: #800000;">`$PROFILE = '$PROFILE'; . `$PROFILE</span><span style="color: #800000;">"</span><span style="color: #000000;">
        }
        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Variable</span><span style="color: #000000;">) {
            </span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (</span><span style="color: #800080;">$var</span><span style="color: #000000;"> </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> (</span><span style="font-weight: bold; color: #5f9ea0;">Get-Variable</span><span style="color: #000000;"> </span><span style="color: #800080;">$Variable</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Scope</span><span style="color: #000000;"> </span><span style="color: #000000;">2</span><span style="color: #000000;">)) {
                </span><span style="color: #0000ff;">trap</span><span style="color: #000000;"> {</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">}
                </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.SessionStateProxy.SetVariable(</span><span style="color: #800080;">$var</span><span style="color: #000000;">.Name, </span><span style="color: #800080;">$var</span><span style="color: #000000;">.Value)
            }
        }
        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$ImportItems</span><span style="color: #000000;">) {
            CreatePipeline </span><span style="color: #800080;">$ImportItems</span><span style="color: #000000;"> {
                </span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (</span><span style="color: #800080;">$item</span><span style="color: #000000;"> </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> </span><span style="color: #000080;">$Input</span><span style="color: #000000;">) {</span><span style="font-weight: bold; color: #5f9ea0;">New-Item</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Path</span><span style="color: #000000;"> </span><span style="color: #800080;">$item</span><span style="color: #000000;">.PSPath </span><span style="color: #5f9ea0; font-style: italic;">-Value</span><span style="color: #000000;"> </span><span style="color: #800080;">$item</span><span style="color: #000000;">.</span><span style="color: #800000;">Definition</span><span style="color: #000000;">}
            }
        }
        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$SnapIn</span><span style="color: #000000;">) {
            CreatePipeline (</span><span style="font-weight: bold; color: #5f9ea0;">Get-PSSnapin</span><span style="color: #000000;"> </span><span style="color: #800080;">$Snapin</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Registered</span><span style="color: #000000;">) {</span><span style="color: #000080;">$Input</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">Add-PSSnapin</span><span style="color: #000000;">}
        }
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.CreatePipeline(</span><span style="color: #800080;">$Script</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Write(</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Close()
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.InvokeAsync()
        </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Add(</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">)
    }

    </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Remove-Pipeline</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">) {
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Remove a pipeline and runspace when it is done</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.RunSpace.Close()
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Dispose()
        </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Remove(</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">)
    }

    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Main </span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Initialize the queue from the pipeline</span><span style="color: #008000;">
</span><span style="color: #000000;">    . Init </span><span style="color: #000080;">$Input</span><span style="color: #000000;">
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Start the pipelines</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">-lt</span><span style="color: #000000;"> </span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-and</span><span style="color: #000000;"> </span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count) {Add-Pipeline} 

    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Loop through the runspaces and pass their output to the main pipeline</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count) {
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Only update the progress bar once a second</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> ((</span><span style="color: #800080;">$stopwatch</span><span style="color: #000000;">.ElapsedMilliseconds </span><span style="color: #ff0000;">-</span><span style="color: #000000;"> </span><span style="color: #800080;">$LastUpdate</span><span style="color: #000000;">) </span><span style="color: #ff0000;">-gt</span><span style="color: #000000;"> </span><span style="color: #000000;">1000</span><span style="color: #000000;">) {
            </span><span style="color: #800080;">$Completed</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-</span><span style="color: #000000;"> </span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">-</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.count
            </span><span style="color: #800080;">$LastUpdate</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$stopwatch</span><span style="color: #000000;">.ElapsedMilliseconds
            </span><span style="color: #800080;">$SecondsRemaining</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> $(</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Completed</span><span style="color: #000000;">) {
                ((</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">+</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count)</span><span style="color: #ff0000;">*</span><span style="color: #800080;">$LastUpdate</span><span style="color: #000000;">/</span><span style="color: #000000;">1000</span><span style="color: #ff0000;">/</span><span style="color: #800080;">$Completed</span><span style="color: #000000;">)
            } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {-</span><span style="color: #000000;">1</span><span style="color: #000000;">})
            </span><span style="font-weight: bold; color: #5f9ea0;">Write-Progress</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">Split-Job</span><span style="color: #800000;">'</span><span style="color: #000000;"> (</span><span style="color: #800000;">"</span><span style="color: #800000;">Queues: $($Pipelines.Count)  Total: $($QueueLength)  </span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #ff0000;">+</span><span style="color: #000000;">
            </span><span style="color: #800000;">"</span><span style="color: #800000;">Completed: $Completed  Pending: $($Queue.Count)</span><span style="color: #800000;">"</span><span style="color: #000000;">)  </span><span style="font-weight: bold; color: #5f9ea0;">`</span><span style="color: #000000;">
            </span><span style="color: #5f9ea0; font-style: italic;">-PercentComplete</span><span style="color: #000000;"> ([</span><span style="color: #008080;">Math</span><span style="color: #000000;">]::</span><span style="color: #8b4513;">Max</span><span style="color: #000000;">((</span><span style="color: #000000;">100</span><span style="color: #ff0000;">-</span><span style="color: #000000;">[</span><span style="color: #008080;">Int</span><span style="color: #000000;">](</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count</span><span style="color: #ff0000;">+</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count)</span><span style="color: #ff0000;">/</span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">*</span><span style="color: #000000;">100</span><span style="color: #000000;">),</span><span style="color: #000000;">0</span><span style="color: #000000;">)) </span><span style="font-weight: bold; color: #5f9ea0;">`</span><span style="color: #000000;">
            </span><span style="color: #5f9ea0; font-style: italic;">-CurrentOperation</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Next item: $(trap {continue}; if ($Queue.Count) {$Queue.Peek()})</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">`</span><span style="color: #000000;">
            </span><span style="color: #5f9ea0; font-style: italic;">-SecondsRemaining</span><span style="color: #000000;"> </span><span style="color: #800080;">$SecondsRemaining</span><span style="color: #000000;">
        }
        </span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> @(</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">)) {
            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> ( </span><span style="color: #ff0000;">-not</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Output.EndOfPipeline </span><span style="color: #ff0000;">-or</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-not</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Error.EndOfPipeline ) {
                </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Output.NonBlockingRead()
                </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Error.NonBlockingRead() | </span><span style="font-weight: bold; color: #5f9ea0;">Out-Default</span><span style="color: #000000;">
            } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
                </span><span style="color: #008000;">#</span><span style="color: #008000;"> Pipeline has stopped; if there was an error show info and restart it</span><span style="color: #008000;">
</span><span style="color: #000000;">                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.PipelineStateInfo.State </span><span style="color: #ff0000;">-eq</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">Failed</span><span style="color: #800000;">'</span><span style="color: #000000;">) {
                    </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.PipelineStateInfo.Reason.ErrorRecord |
                        </span><span style="font-weight: bold; color: #5f9ea0;">Add-Member</span><span style="color: #000000;"> </span><span style="color: #800000;">NoteProperty</span><span style="color: #000000;"> </span><span style="color: #800000;">writeErrorStream</span><span style="color: #000000;"> </span><span style="color: #0000ff;">$True</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-PassThru</span><span style="color: #000000;"> |
                            </span><span style="font-weight: bold; color: #5f9ea0;">Out-Default</span><span style="color: #000000;">
                    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Restart the runspace</span><span style="color: #008000;">
</span><span style="color: #000000;">                    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">-lt</span><span style="color: #000000;"> </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">) {Add-Pipeline}
                }
                Remove-Pipeline </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">
            }
        }
        </span><span style="font-weight: bold; color: #5f9ea0;">Start-Sleep</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Milliseconds</span><span style="color: #000000;"> </span><span style="color: #000000;">100</span><span style="color: #000000;">
    }
}</span></code></pre>
]]></content:encoded>
			<wfw:commentRss>http://jansveld.net/powershell/?feed=rss2&#038;p=11</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Split-Job 0.92</title>
		<link>http://jansveld.net/powershell/?p=10</link>
		<comments>http://jansveld.net/powershell/?p=10#comments</comments>
		<pubDate>Fri, 20 Jun 2008 01:48:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[background]]></category>
		<category><![CDATA[concurrent]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[pipeline]]></category>
		<category><![CDATA[runspace]]></category>
		<category><![CDATA[split-job]]></category>
		<category><![CDATA[wmi]]></category>

		<guid isPermaLink="false">http://www.jansveld.net/powershell/?p=7</guid>
		<description><![CDATA[Here is an update to the Split-Job function. Based in part on some of the comments on the previous version, I made the following changes: The format for the scriptblock has changed; this was done to make it more straightforward to specify parameters for those commands/scripts that accept pipeline input. If you need a foreach (%) you will [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Here is an update to the Split-Job function. Based in part on some of the comments on the <a title="Split-Job: make your PC work harder" href="http://www.jansveld.net/powershell/2008/06/split-job-version-0-9/">previous version</a>, I made the following changes:</p>
<ol>
<li>The format for the scriptblock has changed; this was done to make it more straightforward to specify parameters for those commands/scripts that accept pipeline input. If you need a foreach (%) you will have to include that in the command line. Examples:
<p style="TEXT-ALIGN: left">&#8220;Server1&#8243;,&#8221;Server2&#8243;,&#8221;Server3&#8243; | Split-Job { c:test.ps1 -Force }</p>
<p style="TEXT-ALIGN: left">&#8220;Server1&#8243;,&#8221;Server2&#8243;,&#8221;Server3&#8243; | Split-Job { % {Get-WmiObject Win32_ComputerSystem -ComputerName $_}}</p>
</li>
<li>You can now import your profile, variables and/or aliases into the runspaces. This is somewhat of an experiment; I am not convinced this is even a good idea. Please give me your feedback if you think this is useful.</li>
<li>Each runspace will have its current directory ($PWD) set to that of the main runspace.</li>
</ol>
<p>There is also some error handling code to make the script more robust.</p>
<p>Enjoy!</p>
<p>Arnoud</p>
<pre><code><span style="color: #008000;">#</span><span style="color: #008000;">requires -version 1.0</span><span style="color: #008000;">
#</span><span style="color: #008000;">###############################################################################</span><span style="color: #008000;">
#</span><span style="color: #008000;"># Run commands in multiple concurrent pipelines</span><span style="color: #008000;">
#</span><span style="color: #008000;">#   by Arnoud Jansveld - www.jansveld.net/powershell</span><span style="color: #008000;">
#</span><span style="color: #008000;"># Version History</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.92   Add UseProfile switch: imports the PS profile into each runspace</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add Variable parameter: imports variable(s) into each runspace</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add Alias parameter: imports alias(es)</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Restart pipeline if it stops due to an error</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Set the current path in each runspace to that of the calling process</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.91   Revert to v 0.8 input syntax for the script block</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        Add error handling for empty input queue</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.9    Add logic to distinguish between scriptblocks and cmdlets or scripts:</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        if a ScriptBlock is specified, a foreach {} wrapper is added</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.8    Adds a progress bar</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.7    Stop adding runspaces if the queue is already empty</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.6    First version. Inspired by Gaurhoth's New-TaskPool script</span><span style="color: #008000;">
#</span><span style="color: #008000;">###############################################################################</span><span style="color: #008000;">
</span><span style="color: #000000;">
</span><span style="color: #0000ff;">function</span><span style="color: #000000;"> Split-Job (
    </span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> $(</span><span style="color: #0000ff;">throw</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">You must specify a command or script block!</span><span style="color: #800000;">'</span><span style="color: #000000;">),
    [</span><span style="color: #008080;">int</span><span style="color: #000000;">]</span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;">=</span><span style="color: #000000;">10</span><span style="color: #000000;">,
    [</span><span style="color: #008080;">switch</span><span style="color: #000000;">]</span><span style="color: #800080;">$UseProfile</span><span style="color: #000000;">,
    [</span><span style="color: #008080;">string</span><span style="color: #000000;">[]]</span><span style="color: #800080;">$Variable</span><span style="color: #000000;">,
    [</span><span style="color: #008080;">string</span><span style="color: #000000;">[]]</span><span style="color: #800080;">$Alias</span><span style="color: #000000;">

) {
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create the shared thread-safe queue and fill it with the input objects</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$Queue</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> [</span><span style="color: #008080;">Collections.Queue</span><span style="color: #000000;">]::</span><span style="color: #8b4513;">Synchronized</span><span style="color: #000000;">([</span><span style="color: #008080;">Collections.Queue</span><span style="color: #000000;">]@(</span><span style="color: #000080;">$Input</span><span style="color: #000000;">))
    </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-gt</span><span style="color: #000000;"> </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">) {</span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">}
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Set up the script to be run by each runspace</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$Script</span><span style="color: #000000;">  </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Set-Location '$PWD'; </span><span style="color: #800000;">"</span><span style="color: #000000;">
    </span><span style="color: #800080;">$Script</span><span style="color: #000000;"> </span><span style="color: #ff0000;">+=</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">$Queue = $($Input); </span><span style="color: #800000;">'</span><span style="color: #000000;">
    </span><span style="color: #800080;">$Script</span><span style="color: #000000;"> </span><span style="color: #ff0000;">+=</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">&amp; {trap {continue}; while ($Queue.Count) {$Queue.Dequeue()}} |</span><span style="color: #800000;">'</span><span style="color: #000000;">
    </span><span style="color: #800080;">$Script</span><span style="color: #000000;"> </span><span style="color: #ff0000;">+=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;">

    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create an array to keep track of the set of pipelines</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">New-Object</span><span style="color: #000000;"> </span><span style="color: #800000;">System.Collections.ArrayList</span><span style="color: #000000;">

    </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Add-Pipeline</span><span style="color: #000000;"> {
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> This creates a new runspace and starts an asynchronous pipeline with our script.</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #008000;">#</span><span style="color: #008000;"> It will automatically start processing objects from the shared queue.</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> [</span><span style="color: #008080;">System.Management.Automation.Runspaces.RunspaceFactory</span><span style="color: #000000;">]::</span><span style="color: #8b4513;">CreateRunspace</span><span style="color: #000000;">(</span><span style="color: #000080;">$Host</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.Open()
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Optionally import profile, variables and aliases from the main runspace</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$UseProfile</span><span style="color: #000000;">) {
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.CreatePipeline(</span><span style="color: #800000;">"</span><span style="color: #800000;">. '$PROFILE'</span><span style="color: #800000;">"</span><span style="color: #000000;">)
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Invoke()
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Dispose()
        }
        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Variable</span><span style="color: #000000;">) {
            </span><span style="font-weight: bold; color: #5f9ea0;">Get-Variable</span><span style="color: #000000;"> </span><span style="color: #800080;">$Variable</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Scope</span><span style="color: #000000;"> </span><span style="color: #000000;">2</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">foreach</span><span style="color: #000000;"> {
                </span><span style="color: #0000ff;">trap</span><span style="color: #000000;"> {</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">}
                </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.SessionStateProxy.SetVariable(</span><span style="color: #000080;">$_</span><span style="color: #000000;">.Name, </span><span style="color: #000080;">$_</span><span style="color: #000000;">.Value)
            }
        }
        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Alias</span><span style="color: #000000;">) {
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.CreatePipeline({</span><span style="color: #000080;">$Input</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">Set-Alias</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-value</span><span style="color: #000000;"> {</span><span style="color: #000080;">$_</span><span style="color: #000000;">.Definition}})
            </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Write((</span><span style="font-weight: bold; color: #5f9ea0;">Get-Alias</span><span style="color: #000000;"> </span><span style="color: #800080;">$Alias</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Scope</span><span style="color: #000000;"> </span><span style="color: #000000;">2</span><span style="color: #000000;">), </span><span style="color: #0000ff;">$True</span><span style="color: #000000;">)
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Close()
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Invoke()
            </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Dispose()
        }
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.CreatePipeline(</span><span style="color: #800080;">$Script</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Write(</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Close()
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.InvokeAsync()
        </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Add(</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">)
    }

    </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Remove-Pipeline</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">) {
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Remove a pipeline and runspace when it is done</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.RunSpace.Close()
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Dispose()
        </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Remove(</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">)
    }

    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Start the pipelines</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">-lt</span><span style="color: #000000;"> </span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-and</span><span style="color: #000000;"> </span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count) {Add-Pipeline} 

    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Loop through the pipelines and pass their output to the pipeline until they are finished</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count) {
        </span><span style="font-weight: bold; color: #5f9ea0;">Write-Progress</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">Split-Job</span><span style="color: #800000;">'</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Queues: $($Pipelines.Count)</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">`</span><span style="color: #000000;">
            </span><span style="color: #5f9ea0; font-style: italic;">-PercentComplete</span><span style="color: #000000;"> (</span><span style="color: #000000;">100</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-</span><span style="color: #000000;"> [</span><span style="color: #008080;">Int</span><span style="color: #000000;">](</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count)</span><span style="color: #ff0000;">/</span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">*</span><span style="color: #000000;">100</span><span style="color: #000000;">)
        </span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> (</span><span style="font-weight: bold; color: #5f9ea0;">New-Object</span><span style="color: #000000;"> </span><span style="color: #800000;">System.Collections.ArrayList</span><span style="color: #000000;">(,</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">))) {
            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> ( </span><span style="color: #ff0000;">-not</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Output.EndOfPipeline </span><span style="color: #ff0000;">-or</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-not</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Error.EndOfPipeline ) {
                </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Output.NonBlockingRead()
                </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Error.NonBlockingRead() | </span><span style="font-weight: bold; color: #5f9ea0;">Write-Error</span><span style="color: #000000;">
            } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.PipelineStateInfo.State </span><span style="color: #ff0000;">-eq</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">Failed</span><span style="color: #800000;">'</span><span style="color: #000000;">) {
                    </span><span style="font-weight: bold; color: #5f9ea0;">Write-Error</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.PipelineStateInfo.Reason
                    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Start a new runspace, unless there was a syntax error in the scriptblock</span><span style="color: #008000;">
</span><span style="color: #000000;">                    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">-lt</span><span style="color: #000000;"> </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">) {Add-Pipeline}
                }
                </span><span style="color: #5f9ea0;">Remove-Pipeline</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">
            }
        }
        </span><span style="font-weight: bold; color: #5f9ea0;">Start-Sleep</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Milliseconds</span><span style="color: #000000;"> </span><span style="color: #000000;">100</span><span style="color: #000000;">
    }
}</span></code></pre>
]]></content:encoded>
			<wfw:commentRss>http://jansveld.net/powershell/?feed=rss2&#038;p=10</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Get-ChildItem is not dir!</title>
		<link>http://jansveld.net/powershell/?p=9</link>
		<comments>http://jansveld.net/powershell/?p=9#comments</comments>
		<pubDate>Fri, 13 Jun 2008 01:57:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.jansveld.net/powershell/?p=6</guid>
		<description><![CDATA[Here is a simple but practical tip from the trenches. If you made the switch and are using PowerShell as your main console, you may have noticed that the dir command can be rather sluggish in large directories. While an attempt was made to make the transition to native PS CmdLets easier by making &#8220;dir&#8221; [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Here is a simple but practical tip from the trenches. If you made the switch and are using PowerShell as your main console, you may have noticed that the dir command can be rather sluggish in large directories. While an attempt was made to make the transition to native PS CmdLets easier by making &#8220;dir&#8221; an alias for Get-ChildItem, there is an important syntax difference.</p>
<p>If you are looking for a particular (set of) files, the trick is to split the full file name(s) into a path and file specification. To illustrate, just run the following commands and notice the performance difference:</p>
<p>PS C:&gt;dir c:windowssystem32*.ini</p>
<p>PS C:&gt;dir c:windowssystem32 *.ini</p>
<p>The second command is much faster because it uses the filtering mechanism from the file system provider. I have been burned by this many times and I suspect that others have too. Several scripts performed dramatically better after making this change. Incidentally, this is why <a title="PowerTab" href="http://thepowershellguy.com/blogs/posh/pages/powertab.aspx">PowerTab</a>&#8216;s (yes, you really SHOULD use this!) file system completion is pretty slow compared to that of the good old cmd prompt.</p>
<p>This is another good example of why it pays to scrutinize the PS help system:</p>
<p>PS C:&gt;help Get-ChildItem -detailed</p>
<p>[...]<br />
PARAMETERS<br />
    -path &lt;string[]&gt;<br />
        <strong>Specifies a path to one or more locations</strong>. Wildcards are permitted. The default location is the current directo<br />
        ry (.).</p>
<p>    -include &lt;string[]&gt;<br />
        <strong>Retrieves only the specified items</strong>. The value of this parameter qualifies the Path parameter. Enter a path elem<br />
        ent or pattern, such as &#8220;*.txt&#8221;. Wildcards are permitted.<br />
[...]</p>
<p> </p>
<p>Arnoud</p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://jansveld.net/powershell/?feed=rss2&#038;p=9</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Split-Job: make your PC work harder</title>
		<link>http://jansveld.net/powershell/?p=8</link>
		<comments>http://jansveld.net/powershell/?p=8#comments</comments>
		<pubDate>Fri, 06 Jun 2008 02:39:33 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[runspace]]></category>
		<category><![CDATA[split-job]]></category>

		<guid isPermaLink="false">http://www.jansveld.net/powershell/?p=5</guid>
		<description><![CDATA[When you need to run a simple process or gather (WMI) data from many machines, you need a lot of patience. Or, you can divide and conquer using multiple PowerShell runspaces. There are many ingenious scripts available on the web that allow us to launch and manage background processes (even for PS v1). For my [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>When you need to run a simple process or gather (WMI) data from many machines, you need a lot of patience. Or, you can divide and conquer using multiple PowerShell runspaces. There are many ingenious scripts available on the web that allow us to launch and manage background processes (even for PS v1). For my purposes, I found the necessary inspiration in a blog by <a title="Gaurhoth" href="http://www.skyeagle.net/blog/">Gaurhoth</a>. His <a title="New-TaskPool" href="http://thepowershellguy.com/blogs/gaurhoth/archive/2007/03/30/new-taskpool-ps1-threading-the-powershell-way-pt-2.aspx">New-TaskPool </a>script allows us to run multiple instances of a script block concurrently. Very cool!</p>
<p>The following script is a little different in that it pipes the data to each pipeline using a shared thread-safe queue rather than start a new pipeline for each input object. This reduces overhead and allows scripts that have a begin/process/end block to run more efficiently.</p>
<p>For instance, take this simple data gathering exercise:</p>
<p style="PADDING-LEFT: 30px; TEXT-ALIGN: left"><span style="font-weight: bold; color: #5f9ea0;">Get-Content</span><span style="color: #000000;"> </span><span style="color: #800000;">machines.txt</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">foreach</span><span style="color: #000000;"> {</span><span style="font-weight: bold; color: #5f9ea0;">Get-WmiObject</span><span style="color: #000000;"> </span><span style="color: #800000;">Win32_ComputerSystem</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-ComputerName</span><span style="color: #000000;"> </span><span style="color: #000080;">$_</span><span style="color: #000000;">} | </span><span style="font-weight: bold; color: #5f9ea0;">Export-Csv</span><span style="color: #000000;"> </span><span style="color: #800000;">ComputerInfo.csv</span></p>
<p>If you have a few hundred machines, this can take forever (especially if some machines are offline). Now replace the foreach alias with the Split-Job function:</p>
<p style="PADDING-LEFT: 30px; TEXT-ALIGN: left"><span style="font-weight: bold; color: #5f9ea0;">Get-Content</span><span style="color: #000000;"> </span><span style="color: #800000;">machines.txt</span><span style="color: #000000;"> | Split-Job {</span><span style="font-weight: bold; color: #5f9ea0;">Get-WmiObject</span><span style="color: #000000;"> </span><span style="color: #800000;">Win32_ComputerSystem</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-ComputerName</span><span style="color: #000000;"> </span><span style="color: #000080;">$_</span><span style="color: #000000;">} | </span><span style="font-weight: bold; color: #5f9ea0;">Export-Csv</span><span style="color: #000000;"> </span><span style="color: #800000;">ComputerInfo.csv</span></p>
<p>It will create 10 runspaces and run the WMI query concurrently, so this should be almost 10x faster. Even if one of the pipelines stalls, the others will keep going. If you already have some data gathering script that accepts pipeline input, you can just drop Split-Job in:</p>
<p style="PADDING-LEFT: 30px; TEXT-ALIGN: left"><span style="font-weight: bold; color: #5f9ea0;">Get-Content</span><span style="color: #000000;"> </span><span style="color: #800000;">machines.txt</span><span style="color: #000000;"> | Split-Job .MachineReport.ps1 | </span><span style="font-weight: bold; color: #5f9ea0;">Export-Csv</span><span style="color: #000000;"> </span><span style="color: #800000;">MachineReport.csv</span></p>
<p>It is important to note that the position of the script in the pipeline is important; the command preceding it should be quick, e.g. get objects from a text file, AD, SQL etc.</p>
<p>This is a work in progress and I will post more about this in the following weeks. In the meantime, comments and suggestions are welcome!</p>
<p>Arnoud</p>
<p>[UPDATE] The latest version can be found here: <a href="http://www.jansveld.net/powershell/2008/06/split-job-092/">http://www.jansveld.net/powershell/2008/06/split-job-092/</a></p>
<p> </p>
<pre><code><span style="color: #008000;">#</span><span style="color: #008000;">requires -version 1.0</span><span style="color: #008000;">
#</span><span style="color: #008000;">##################################################################################################</span><span style="color: #008000;">
#</span><span style="color: #008000;"># Run commands in multiple concurrent pipelines</span><span style="color: #008000;">
#</span><span style="color: #008000;">#   by Arnoud Jansveld</span><span style="color: #008000;">
#</span><span style="color: #008000;"># Version History</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.9    Includes logic to distinguish between scriptblocks and cmdlets or scripts. If a ScriptBlock</span><span style="color: #008000;">
#</span><span style="color: #008000;">#        is specified, a foreach {} wrapper is added</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.8    Adds a progress bar</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.7    Stop adding runspaces if the queue is already empty</span><span style="color: #008000;">
#</span><span style="color: #008000;"># 0.6    First version. Inspired by Gaurhoth's New-TaskPool script</span><span style="color: #008000;">
#</span><span style="color: #008000;">##################################################################################################</span><span style="color: #008000;">
</span><span style="color: #000000;">
</span><span style="color: #0000ff;">function</span><span style="color: #000000;"> Split-Job (
    </span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> $(</span><span style="color: #0000ff;">throw</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">You must specify a command or script block!</span><span style="color: #800000;">'</span><span style="color: #000000;">),
    [</span><span style="color: #008080;">int</span><span style="color: #000000;">]</span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;">=</span><span style="color: #000000;">10</span><span style="color: #000000;">
) {
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create the shared thread-safe queue and fill it with the input objects</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$Queue</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> [</span><span style="color: #008080;">System.Collections.Queue</span><span style="color: #000000;">]::</span><span style="color: #8b4513;">Synchronized</span><span style="color: #000000;">([</span><span style="color: #008080;">System.Collections.Queue</span><span style="color: #000000;">]@(</span><span style="color: #000080;">$Input</span><span style="color: #000000;">))
    </span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Set up the script to be run by each pipeline</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-is</span><span style="color: #000000;"> [</span><span style="color: #008080;">ScriptBlock</span><span style="color: #000000;">]) {</span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">foreach {$Scriptblock}</span><span style="color: #800000;">"</span><span style="color: #000000;">}
    </span><span style="color: #800080;">$Script</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">$Queue = $($Input); &amp; {while ($Queue.Count) {$Queue.Dequeue()}} | </span><span style="color: #800000;">'</span><span style="color: #000000;"> </span><span style="color: #ff0000;">+</span><span style="color: #000000;"> </span><span style="color: #800080;">$Scriptblock</span><span style="color: #000000;">
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create an array to keep track of the set of pipelines</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">New-Object</span><span style="color: #000000;"> </span><span style="color: #800000;">System.Collections.ArrayList</span><span style="color: #000000;">

    </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Add-Pipeline</span><span style="color: #000000;"> {
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> This creates a new runspace and starts an asynchronous pipeline with our script.</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #008000;">#</span><span style="color: #008000;"> It will automatically start processing objects from the shared queue.</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> [</span><span style="color: #008080;">System.Management.Automation.Runspaces.RunspaceFactory</span><span style="color: #000000;">]::</span><span style="color: #8b4513;">CreateRunspace</span><span style="color: #000000;">(</span><span style="color: #000080;">$Host</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.Open()
        </span><span style="color: #800080;">$PipeLine</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Runspace</span><span style="color: #000000;">.CreatePipeline(</span><span style="color: #800080;">$Script</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Write(</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">)
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Input.Close()
        </span><span style="color: #800080;">$PipeLine</span><span style="color: #000000;">.InvokeAsync()
        </span><span style="color: #800080;">$Null</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Add(</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">)
    }

    </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Remove-Pipeline</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">) {
        </span><span style="color: #008000;">#</span><span style="color: #008000;"> Remove a pipeline and runspace when it is done</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.RunSpace.Close()
        </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Dispose()
        </span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Remove(</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">)
    }

    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Start the pipelines</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #0000ff;">do</span><span style="color: #000000;"> {Add-Pipeline} </span><span style="color: #0000ff;">until</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">-ge</span><span style="color: #000000;"> </span><span style="color: #800080;">$MaxPipelines</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-or</span><span style="color: #000000;"> </span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count </span><span style="color: #ff0000;">-eq</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">)

    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Loop through the pipelines and pass their output to the pipeline until they are finished</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #0000ff;">while</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">.Count) {
        </span><span style="font-weight: bold; color: #5f9ea0;">Write-Progress</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">Split-Job</span><span style="color: #800000;">'</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Queues: $($Pipelines.Count)</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">`</span><span style="color: #000000;">
            </span><span style="color: #5f9ea0; font-style: italic;">-PercentComplete</span><span style="color: #000000;"> (</span><span style="color: #000000;">100</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-</span><span style="color: #000000;"> [</span><span style="color: #008080;">Int</span><span style="color: #000000;">](</span><span style="color: #800080;">$Queue</span><span style="color: #000000;">.Count)</span><span style="color: #ff0000;">/</span><span style="color: #800080;">$QueueLength</span><span style="color: #000000;">*</span><span style="color: #000000;">100</span><span style="color: #000000;">)
        </span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;"> </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> (</span><span style="font-weight: bold; color: #5f9ea0;">New-Object</span><span style="color: #000000;"> </span><span style="color: #800000;">System.Collections.ArrayList</span><span style="color: #000000;">(,</span><span style="color: #800080;">$Pipelines</span><span style="color: #000000;">))) {
            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> ( </span><span style="color: #ff0000;">-not</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Output.EndOfPipeline </span><span style="color: #ff0000;">-or</span><span style="color: #000000;"> </span><span style="color: #ff0000;">-not</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Error.EndOfPipeline ) {
                </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Output.NonBlockingRead()
                </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.Error.NonBlockingRead() | </span><span style="font-weight: bold; color: #5f9ea0;">foreach</span><span style="color: #000000;"> {</span><span style="font-weight: bold; color: #5f9ea0;">Write-Error</span><span style="color: #000000;"> </span><span style="color: #000080;">$_</span><span style="color: #000000;">}
            } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.PipelineStateInfo.State </span><span style="color: #ff0000;">-eq</span><span style="color: #000000;"> </span><span style="color: #800000;">'</span><span style="color: #800000;">Failed</span><span style="color: #800000;">'</span><span style="color: #000000;">) {
                    </span><span style="font-weight: bold; color: #5f9ea0;">Write-Error</span><span style="color: #000000;"> </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">.PipelineStateInfo.Reason
                }
                Remove-Pipeline </span><span style="color: #800080;">$Pipeline</span><span style="color: #000000;">
            }
        }
        </span><span style="font-weight: bold; color: #5f9ea0;">Start-Sleep</span><span style="color: #000000;"> </span><span style="color: #5f9ea0; font-style: italic;">-Milliseconds</span><span style="color: #000000;"> </span><span style="color: #000000;">100</span><span style="color: #000000;">
    }
}</span></code></pre>
]]></content:encoded>
			<wfw:commentRss>http://jansveld.net/powershell/?feed=rss2&#038;p=8</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Select-Properties: a helper for exporting DirectoryEntry objects</title>
		<link>http://jansveld.net/powershell/?p=7</link>
		<comments>http://jansveld.net/powershell/?p=7#comments</comments>
		<pubDate>Mon, 02 Jun 2008 02:44:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[DirectoryEntry]]></category>
		<category><![CDATA[export]]></category>
		<category><![CDATA[PropertyValueCollection]]></category>

		<guid isPermaLink="false">http://www.jansveld.net/powershell/?p=4</guid>
		<description><![CDATA[When you work with DirectoryEntry objects (AD or local accounts), you quickly run into the fact that their properties are actually PropertyValueCollections. This trips you up with certain operations, like exporting entries. For instance, the following will not work: # Get some user accounts $Users = ([ADSI]&#8216;WinNT://.&#8216;).PSBase.Children &#124; where {$_.PSBase.SchemaClassName -eq &#8216;User&#8216;} # Export them [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>When you work with DirectoryEntry objects (AD or local accounts), you quickly run into the fact that their properties are actually PropertyValueCollections. This trips you up with certain operations, like exporting entries. For instance, the following will not work:</p>
<p><span style="color: #008000;">#</span><span style="color: #008000;"> Get some user accounts</span><span style="color: #008000;"><br />
</span><span style="color: #800080;">$Users</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> ([</span><span style="color: #008080;">ADSI</span><span style="color: #000000;">]</span><span style="color: #800000;">&#8216;</span><span style="color: #800000;">WinNT://.</span><span style="color: #800000;">&#8216;</span><span style="color: #000000;">).PSBase.Children | </span><span style="color: #0000ff;">where</span><span style="color: #000000;"> {</span><span style="color: #000080;">$_</span><span style="color: #000000;">.PSBase.SchemaClassName </span><span style="color: #ff0000;">-eq</span><span style="color: #000000;"> </span><span style="color: #800000;">&#8216;</span><span style="color: #800000;">User</span><span style="color: #800000;">&#8216;</span><span style="color: #000000;">}<br />
</span><span style="color: #008000;">#</span><span style="color: #008000;"> Export them to a CSV file</span><span style="color: #008000;"><br />
</span><span style="color: #800080;">$Users</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">Export-Csv</span><span style="color: #000000;"> </span><span style="color: #800000;">Users</span><span style="color: #800000;">.csv</span><span style="color: #000000;"><br />
</span><br />
There are no errors, but the exported file will be filled with the text &#8220;System.DirectoryServices.PropertyValueCollection&#8221;. Not really what we were looking for. The solution is to let PowerShell turn those PropertyValueCollections into regular values. If we just want to get the names and descriptions, we can use:</p>
<p><span style="color: #800080;">$Users</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">select</span><span style="color: #000000;"> {</span><span style="color: #000080;">$_</span><span style="color: #000000;">.Name}, {</span><span style="color: #000080;">$_</span><span style="color: #000000;">.Description} | </span><span style="font-weight: bold; color: #5f9ea0;">Export-Csv</span><span style="color: #000000;"> </span><span style="color: #800000;">Users.csv</span></p>
<p>That&#8217;s good enough when you are in a hurry. But if you want the actual property names, and need many (or all) properties, this calls for a scripted solution. This is the version I came up with originally:</p>
<pre><span style="color: #0000ff;">filter</span><span style="color: #000000;"> </span><span style="color: #5f9ea0;">Select-Properties</span><span style="color: #000000;"> (</span><span style="color: #800080;">$filter</span><span style="color: #ff0000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">*</span><span style="color: #800000;">'</span><span style="color: #000000;">) {
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Create a custom object to hold the requested properties</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$custom</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #5f9ea0;">New-Object</span><span style="color: #000000;"> </span><span style="color: #800000;">PSObject</span><span style="color: #000000;">
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Get the properties of the object being processed</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$props</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #000080;">$_</span><span style="color: #000000;">.PSBase.Properties
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Add each property that matches our filter to the custom object</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$filter</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">foreach</span><span style="color: #000000;"> {
        </span><span style="color: #800080;">$props</span><span style="color: #000000;">.PropertyNames </span><span style="color: #ff0000;">-like</span><span style="color: #000000;"> </span><span style="color: #000080;">$_</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">foreach</span><span style="color: #000000;"> {
            </span><span style="color: #800080;">$custom</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">add-Member</span><span style="color: #000000;"> </span><span style="color: #800000;">noteProperty</span><span style="color: #000000;"> </span><span style="color: #000080;">$_</span><span style="color: #000000;"> $(</span><span style="color: #800080;">$props</span><span style="color: #000000;">.Item(</span><span style="color: #000080;">$_</span><span style="color: #000000;">))
        }
    }
    </span><span style="color: #008000;">#</span><span style="color: #008000;"> Return the custom object</span><span style="color: #008000;">
</span><span style="color: #000000;">    </span><span style="color: #800080;">$custom</span><span style="color: #000000;">
}
</span></pre>
<p>Now you can use</p>
<p><span style="color: #800080;">$Users</span><span style="color: #000000;"> | </span><span style="color: #5f9ea0;">Select-Properties</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">Export-Csv</span><span style="color: #000000;"> </span><span style="color: #800000;">Users.csv</span></p>
<p><span style="color: #800000;"><span style="color: #000000;">and get the data you really wanted. You can also specify one or more specific properties (with wildcards), just like the Select-Object command. The script has a few drawbacks, but we will save that (and an improved script) for a future post.</span></span></p>
<p>Arnoud</p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://jansveld.net/powershell/?feed=rss2&#038;p=7</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Show-Progress: a quick progress bar</title>
		<link>http://jansveld.net/powershell/?p=6</link>
		<comments>http://jansveld.net/powershell/?p=6#comments</comments>
		<pubDate>Mon, 26 May 2008 16:19:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[bar]]></category>
		<category><![CDATA[progress]]></category>

		<guid isPermaLink="false">http://www.jansveld.net/powershell/?p=3</guid>
		<description><![CDATA[Often times I need to run some command on a large set of objects, say a WMI query on a few hundred PCs. Here is a simple script to have an easy way to show a progress bar using the built-in Write-Progress cmdlet. In my PS profile it is aliased as &#8220;bar&#8221; so I can do the following: [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Often times I need to run some command on a large set of objects, say a WMI query on a few hundred PCs. Here is a simple script to have an easy way to show a progress bar using the built-in Write-Progress cmdlet. In my PS profile it is aliased as &#8220;bar&#8221; so I can do the following:</p>
<p style="text-align: left;">Get-Content computers.txt | <strong>bar</strong> |% {Get-WMIObject Win32_ComputerSystem -ComputerName $_} | Export-Csv ComputerInfo.csv</p>
<p>One thing to keep in mind is that the script should be placed early in the pipeline, as it consumes all objects before passing them on in order to count them. This is fine as long as the preceding commands are quick, like getting names from files, AD, SQL etc. It does not matter what kind of objects are passed through the script.</p>
<p>Here is the script (Show-Progress.ps1):</p>
<pre><code><span style="color: #008000;">#</span><span style="color: #008000;"> Store all pipeline objects in an array so we can count them</span><span style="color: #008000;">
</span><span style="color: #800080;">$InputArray</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> @(</span><span style="color: #000080;">$Input</span><span style="color: #000000;">)
</span><span style="color: #008000;">#</span><span style="color: #008000;"> Initialize the counter and length ( divided by 100 so we get the percentage)</span><span style="color: #008000;">
</span><span style="color: #800080;">$counter</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">
</span><span style="color: #800080;">$length</span><span style="color: #000000;"> </span><span style="color: #ff0000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">$InputArray</span><span style="color: #000000;">.Length </span><span style="color: #ff0000;">/</span><span style="color: #000000;"> </span><span style="color: #000000;">100</span><span style="color: #000000;">
</span><span style="color: #008000;">#</span><span style="color: #008000;"> Push the objects down the pipeline while updating our progress bar</span><span style="color: #008000;">
</span><span style="color: #800080;">$InputArray</span><span style="color: #000000;"> | </span><span style="font-weight: bold; color: #5f9ea0;">foreach</span><span style="color: #000000;"> {
    </span><span style="font-weight: bold; color: #5f9ea0;">Write-Progress</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Processing...</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">$_</span><span style="color: #800000;">"</span><span style="color: #000000;"> -perc ([</span><span style="color: #008080;">Int</span><span style="color: #000000;">]</span><span style="color: #800080;">$counter</span><span style="color: #ff0000;">++/</span><span style="color: #800080;">$length</span><span style="color: #000000;">)
    </span><span style="color: #000080;">$_</span><span style="color: #000000;">
}
</span></code></pre>
<p>Enjoy,</p>
<p>Arnoud</p>
]]></content:encoded>
			<wfw:commentRss>http://jansveld.net/powershell/?feed=rss2&#038;p=6</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
