<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://powershell.com/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results for 'app:weblogs' matching tags 'pipeline' and 'Attribute'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=pipeline,Attribute&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'pipeline' and 'Attribute'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Creating Pipeline-Aware Functions</title><link>http://powershell.com/cs/blogs/tobias/archive/2010/09/29/creating-pipeline-aware-functions.aspx</link><pubDate>Wed, 29 Sep 2010 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:7745</guid><dc:creator>Tobias</dc:creator><description>&lt;p&gt;In &lt;strong&gt;part 1&lt;/strong&gt; of this series &lt;a target="_blank" href="http://powershell.com/cs/blogs/tobias/archive/2010/09/22/creating-objects-yourself-and-a-bunch-of-cool-things-you-can-do-with-them.aspx" title="(Part 1)"&gt;(Part 1)&lt;/a&gt;&amp;nbsp;you learned&amp;nbsp;a lot about creating functions that return results as real objects. You also created a function called &lt;strong&gt;Get-Shortcut&lt;/strong&gt; which manages shortcuts in your start menu. &lt;/p&gt;
&lt;p&gt;As promised, today I&amp;#39;ll show you how to use that function to manage shortcuts, add or remote hotkeys or show property pages for the shortcuts. The &lt;strong&gt;real thing you learn&lt;/strong&gt; though is &lt;strong&gt;how to create functions that accept information via pipeline&lt;/strong&gt; so that you can create real PowerShell pipeline &amp;quot;chains&amp;quot; like this one to automatically add a hotkey to the PowerShell shortcut: &lt;/p&gt;
&lt;div class="pscode"&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Get-Shortcut&lt;/span&gt;&lt;/span&gt; | &lt;br /&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Where-Object&lt;/span&gt;&lt;/span&gt; { &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$_&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;LinkPath&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;-like&lt;/span&gt;&lt;/span&gt; &lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;*Windows PowerShell.lnk&amp;#39;&lt;/span&gt;&lt;/span&gt; } | &lt;br /&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Set-Shortcut&lt;/span&gt;&lt;/span&gt; &lt;span class="modifier"&gt;&lt;span style="color:#5f9ea0;"&gt;-hotkey&lt;/span&gt;&lt;/span&gt; F11&lt;/div&gt;
&lt;h2&gt;Creating Pipeline-Aware Functions&lt;/h2&gt;
&lt;p&gt;In order for functions to accept input over the pipeline, two things are necessary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The function needs to assign a special attribute to the parameter that can be received from the incoming objects&lt;/li&gt;
&lt;li&gt;The function needs a &lt;strong&gt;process&lt;/strong&gt; script block that indicates which part of the function code needs to be iterated for each incoming object&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;#39;s create a function that can open the property page of a file. This way, you could select a shortcut using &lt;a target="_blank" href="http://powershell.com/cs/media/p/7744.aspx" title="Get-Shortcut"&gt;Get-Shortcut&lt;/a&gt; and then pipe the result to the new function. Let&amp;#39;s call it &lt;strong&gt;Show-Properties&lt;/strong&gt;. This is what it looks like:&lt;/p&gt;
&lt;div class="pscode"&gt;&lt;span class="keyword"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;&lt;/span&gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Show-Properties&lt;/span&gt;&lt;/span&gt; {&lt;br /&gt;&lt;span class="keyword"&gt;&lt;span style="color:#0000ff;"&gt;param&lt;/span&gt;&lt;/span&gt;(&lt;br /&gt;[Parameter(ValueFromPipelineByPropertyName&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$true&lt;/span&gt;&lt;/span&gt;)]&lt;br /&gt;[Alias(&lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;LinkPath&amp;#39;&lt;/span&gt;&lt;/span&gt;)]&lt;br /&gt;[Alias(&lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;FileName&amp;#39;&lt;/span&gt;&lt;/span&gt;)]&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#800080;"&gt;&lt;span class="var"&gt;$Path&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;)&lt;br /&gt;begin {&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$shell&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;New-Object&lt;/span&gt;&lt;/span&gt; &lt;span class="modifier"&gt;&lt;span style="color:#5f9ea0;"&gt;-ComObject&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#8b4513;"&gt;&lt;span class="namespace"&gt;Shell.Application&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;}&lt;br /&gt;&lt;br /&gt;process {&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$parent&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Split-Path&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#800080;"&gt;&lt;span class="var"&gt;$Path&lt;/span&gt;&lt;br /&gt;&lt;span class="var"&gt;$child&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Split-Path&lt;/span&gt;&lt;/span&gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$Path&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#5f9ea0;"&gt;&lt;span class="modifier"&gt;-Leaf&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$folder&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$shell&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;NameSpace&lt;/span&gt;&lt;/span&gt;(&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$parent&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$file&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$folder&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;ParseName&lt;/span&gt;&lt;/span&gt;(&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$child&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$file&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;InvokeVerb&lt;/span&gt;&lt;/span&gt;(&lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;Properties&amp;#39;&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;}&lt;br /&gt;}&lt;/div&gt;
&lt;p&gt;Download this script from our Library: &lt;a target="_blank" href="http://powershell.com/cs/media/p/7746.aspx" title="Show-Properties"&gt;Show-Properties&lt;/a&gt;&lt;br /&gt;And don&amp;#39;t forget to also get &lt;a target="_blank" href="http://powershell.com/cs/media/p/7744.aspx" title="Get-Shortcut"&gt;Get-Shortcut&lt;/a&gt; from the previous part of this series!&lt;/p&gt;
&lt;p&gt;When you run both functions, you can now easily open the property page for any shortcut and manually assign hotkeys. Let&amp;#39;s assume you&amp;#39;d like to &lt;strong&gt;add a new shortcut&lt;/strong&gt; to your&amp;nbsp;&lt;strong&gt;PowerShell link&lt;/strong&gt;. Try this:&lt;/p&gt;
&lt;p&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Get-Shortcut&lt;/span&gt;&lt;/span&gt; | &lt;br /&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Where-Object&lt;/span&gt;&lt;/span&gt; { &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$_&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;LinkPath&lt;/span&gt;&lt;/span&gt; &lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;-like&lt;/span&gt;&lt;/span&gt; &lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;*Windows PowerShell.lnk&amp;#39;&lt;/span&gt;&lt;/span&gt; } | &lt;br /&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Show-Properties&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Voila, the property page of your PowerShell shortcut opens, and you can now click into the keyboard field and press &lt;strong&gt;F11&lt;/strong&gt; to set this key as new shortcut. Once you close the property dialog, you may be asked for Admin credentials as this shortcut affects all users. Once saved, &lt;strong&gt;pressing F11 will open PowerShell for&amp;nbsp;you&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;You can also open all dialogs for all shortcuts that have a hotkey, for example because you&amp;#39;d like to remove duplicate entries:&lt;/p&gt;
&lt;p&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Get-Shortcut&lt;/span&gt;&lt;/span&gt; | &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Where-Object&lt;/span&gt;&lt;/span&gt; { &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$_&lt;/span&gt;&lt;/span&gt;.&lt;span class="method"&gt;&lt;span style="color:#8b4513;"&gt;Hotkey&lt;/span&gt;&lt;/span&gt; } | &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Show-Properties&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Note how a simple Where-Object is able to filter out all instances that have a Null value in a certain property - because Null always gets converted to a boolean value of $false.&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Examining the Magic: Binding to a Parameter&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s check out how &lt;strong&gt;Show-Properties&lt;/strong&gt; works.&amp;nbsp;As you can see, it accepts the object provided by &lt;strong&gt;Get-Shortcut&lt;/strong&gt;. This is done by an attribute called&amp;nbsp;&lt;strong&gt;ValueFromPipelineByPropertyName&lt;/strong&gt;. When you look at the beginning of that function, you&amp;#39;ll see that the parameter &lt;strong&gt;Path&lt;/strong&gt; was decorated with that attribute.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span class="keyword"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;&lt;/span&gt; &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Show-Properties&lt;/span&gt;&lt;/span&gt; {&lt;br /&gt;&lt;span class="keyword"&gt;&lt;span style="color:#0000ff;"&gt;param&lt;/span&gt;&lt;/span&gt;(&lt;br /&gt;[Parameter(ValueFromPipelineByPropertyName&lt;span class="op"&gt;&lt;span style="color:#ff0000;"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$true&lt;/span&gt;&lt;/span&gt;)]&lt;br /&gt;[Alias(&lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;LinkPath&amp;#39;&lt;/span&gt;&lt;/span&gt;)]&lt;br /&gt;[Alias(&lt;span class="string"&gt;&lt;span style="color:#800000;"&gt;&amp;#39;FileName&amp;#39;&lt;/span&gt;&lt;/span&gt;)]&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#800080;"&gt;&lt;span class="var"&gt;$Path&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;)&lt;br /&gt;...&lt;/p&gt;
&lt;p&gt;What this means is that if a preceeding command in the pipeline emits an object with a property called &amp;quot;Path&amp;quot;, it is automatically bound to that parameter. &lt;/p&gt;
&lt;p&gt;However, &lt;strong&gt;Get-Shortcut&lt;/strong&gt; emits objects that have no property called &lt;strong&gt;Path&lt;/strong&gt;. Instead, the link to a &lt;strong&gt;lnk&lt;/strong&gt;-file is contained in a property called &lt;strong&gt;LinkPath&lt;/strong&gt;. The function could have used that name as a parameter, but since &lt;strong&gt;LinkPath&lt;/strong&gt; is specific for link files, we decided a more general parameter like &lt;strong&gt;Path&lt;/strong&gt; would work better. &lt;/p&gt;
&lt;p&gt;That&amp;#39;s why the function defines two more &lt;strong&gt;alias names&lt;/strong&gt; for this property called &lt;strong&gt;LinkPath&lt;/strong&gt; and &lt;strong&gt;FileName&lt;/strong&gt;. So the function accepts objects with properties called &lt;strong&gt;Path&lt;/strong&gt;, &lt;strong&gt;LinkPath&lt;/strong&gt; or &lt;strong&gt;FileName&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;#39;s cool because this makes your function really versatile. You can open any file property dialog, and you can use a multitude of cmdlets to find that path name. For example, to open the dialog for all running PowerShell instances, try this:&lt;/p&gt;
&lt;p&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Get-Process&lt;/span&gt;&lt;/span&gt; powershell &lt;span class="modifier"&gt;&lt;span style="color:#5f9ea0;"&gt;-FileVersionInfo&lt;/span&gt;&lt;/span&gt; | &lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Show-Properties&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here,&amp;nbsp;&lt;strong&gt;Get-Process&lt;/strong&gt; finds the file path and returns objects&amp;nbsp;with a &lt;strong&gt;FileName&lt;/strong&gt; property.&amp;nbsp;Because &lt;strong&gt;Show-Properties&lt;/strong&gt; uses alias names for its &lt;strong&gt;Path&lt;/strong&gt; property, it can still bind this information to its &lt;strong&gt;Path&lt;/strong&gt; property. If you wanted, you could also call the function directly like this:&lt;/p&gt;
&lt;div class="pscode"&gt;&lt;span class="verbnoun"&gt;&lt;span style="color:#5f9ea0;"&gt;Show-Properties&lt;/span&gt;&lt;/span&gt; &lt;span class="modifier"&gt;&lt;span style="color:#5f9ea0;"&gt;-Path&lt;/span&gt;&lt;/span&gt; &lt;span class="var"&gt;&lt;span style="color:#800080;"&gt;$env:windir&lt;/span&gt;&lt;/span&gt;\&lt;span class="namespace"&gt;&lt;span style="color:#8b4513;"&gt;explorer.exe&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;This would open the &lt;strong&gt;explorer.exe&lt;/strong&gt; properties page, as you submitted the file path directly to the &lt;strong&gt;Path&lt;/strong&gt; parameter.&lt;/p&gt;
&lt;h2&gt;Begin, Process, End - declaring which code is executed when...&lt;/h2&gt;
&lt;p&gt;Binding a parameter to the pipeline is only one of two requirements. The other one is that you declare which parts of your function code is actually executed for each object received. You do this by wrapping this code inside a &lt;strong&gt;process&lt;/strong&gt; block. Note that once you add a process block to your function, no code is permitted outside this block anymore.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Optionally&lt;/strong&gt;, you can also add a &lt;strong&gt;begin&lt;/strong&gt; and an &lt;strong&gt;end&lt;/strong&gt; block which is executed once when the function starts and ends. The function uses a &lt;strong&gt;begin&lt;/strong&gt; block to instantiate the necessary COM object which is a good idea because if you instantiated this object inside the process block, it would get instantiated for every single object received. This would impose performance and resource issues that you can easily avoid by placing initialization code inside &lt;strong&gt;begin&lt;/strong&gt;. Use an &lt;strong&gt;end&lt;/strong&gt; block if you want to clean up behind your function or emit final messages or collected results.&lt;/p&gt;
&lt;h2&gt;What&amp;#39;s next?&lt;/h2&gt;
&lt;p&gt;In the next part, we&amp;#39;ll look at how you can manage your shortcuts automatically rather than manually. Of course, you&amp;#39;ll again learn a lot about PowerShell intrinsics such as optional parameters and how&amp;nbsp;to determine which parameters were actually submitted by a user.&lt;/p&gt;
&lt;p&gt;Tobias&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Microsoft MVP PowerShell Germany&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;P.S.&lt;br /&gt;If you live in Germany or&amp;nbsp;other parts of Europe&amp;nbsp;and your company would like to set up a&amp;nbsp;truly great PowerShell training, just contact me! I regularly train mid- to large-size companies. Trainings are always a blast with tons of real-world-examples and solutions. Here&amp;#39;s how to get in touch with me:&amp;nbsp;&lt;a href="mailto:tobias.weltner@scriptinternals.de"&gt;&lt;span style="color:#3366cc;"&gt;tobias.weltner@scriptinternals.de&lt;/span&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;</description></item></channel></rss>