<?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 'Scripting Guy!'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=Pipeline,Scripting+Guy!&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'Pipeline' and 'Scripting Guy!'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Use the Pipeline to Create Robust PowerShell Functions</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2011/05/10/use-the-pipeline-to-create-robust-powershell-functions.aspx</link><pubDate>Tue, 10 May 2011 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:10328</guid><dc:creator>Anonymous</dc:creator><description>Summary : Microsoft Windows PowerShell MVP, Don Jones, shows how to use the pipeline to create robust reusable functions. 
 Microsoft Scripting Guy, Ed Wilson, is here. Our guest blogger today is Don Jones. 
 
 
 Don Jones is a Windows PowerShell MVP Award recipient, and he is one of the world&amp;rsquo;s most well-known Windows PowerShell authorities. He blogs about PowerShell, writes about PowerShell, and offers private on-site Windows PowerShell classes . He recently released a book for Windows PowerShell beginners, helping them Learn Windows PowerShell in a Month of Lunches . 
 
 &amp;ldquo;There&amp;rsquo;s a reason,&amp;rdquo; I am constantly telling my Windows PowerShell students, &amp;ldquo;That it&amp;rsquo;s called Power Shell and not Power Script. &amp;rdquo; Although Windows PowerShell obviously has an embedded scripting language, it is first and foremost a command-line shell based around the concept of a pipeline&amp;mdash;not unlike ages-old UNIX shells. Given the focus on the pipeline, it only makes sense for the tools you write to take advantage of that pipeline. Unfortunately, if your past experience is mainly in scripting languages like VBScript, or even programming languages like VB or C#, the pipeline can be a bit elusive. Here are two rules to always try to follow to keep the pipeline firmly in focus as you write functions in Windows PowerShell: 
 
 Never worry about where input is coming from. 
 Never worry about where the output is going. 
 
 If your functions accept input from the pipeline, and output to the pipeline, then they&amp;rsquo;ll achieve maximum flexibility&amp;mdash;not to mention all the PowerShell feng shui you could possibly desire. 
 Input from the Pipeline: Go Advanced 
 Windows PowerShell offers many different forms of a function, the basic unit of modularization within the shell. There are basic functions, filtering functions, and so on. Forget all of them except the pinnacle of function functionality: The advanced function&amp;mdash;fondly called a &amp;ldquo;script cmdlet&amp;rdquo; by its biggest fans. Honestly, advanced functions aren&amp;rsquo;t all that different from their non-advanced peers&amp;mdash;they just have a little bit more structure, which allows PowerShell to do some interesting work on your behalf. 
 Let&amp;rsquo;s say your goal is to write a function that retrieves management information from one or more computers. You don&amp;rsquo;t want your function worrying about where those computer names are coming from&amp;mdash;Rule #1 says that the function shouldn&amp;rsquo;t care about its input. Instead, your function should simply implement a ComputerName parameter and accept one or more computer names. Where those names come from doesn&amp;rsquo;t really matter. For example, any of the following should work (assuming that you named your function Get-Info ): 
 
 Get-ADComputer &amp;ndash;filter * | Select @{label=&amp;#39;computername&amp;#39;;expression={$_.name}} | Get-Info 
 Get-Info &amp;ndash;computername SERVER2,SERVER3 
 &amp;quot;localhost&amp;quot; | Get-Info 
 Get-Info &amp;ndash;computername (Get-Content names.txt) 
 Get-Content names.txt | Get-Info 
 Why so many variations? Well, because that&amp;rsquo;s how most native PowerShell cmdlets work. You can never tell which of these patterns someone else might be used to, so you want to support all of them. Fortunately, an advanced function makes it easy to do so. Here&amp;rsquo;s an example where I&amp;rsquo;ve also included a second parameter, LogName , which will be used to specify the name of an error log file (for computers that can&amp;rsquo;t be reached). That parameter defaults to C:\retries.txt, so you don&amp;rsquo;t even have to specify the parameter, meaning that all of the previous examples will still work. 
 
 Function Get-Info { 
 [CmdletBinding()] 
 Param( 
 [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
 [string[]]$computername, 
 [string]$logfile = &amp;#39;c:\retries.txt&amp;#39; 
 ) 
 PROCESS { 
 Foreach ($computer in $computername) { 
 # do stuff here with $computer 
 } 
 } 
 } 
 
 Simply providing all of that extra metadata around the parameter and using the CmdletBinding() directive, makes PowerShell do all the heavy lifting. I&amp;rsquo;ve indicated where you&amp;rsquo;ll use the $computer variable to do whatever it is you need to do with a single computer name at a time. Every one of the five original usage examples will work fine. In fact, let&amp;rsquo;s go ahead and document those by adding them as comment-based Help. These specially-formatted comments, which must immediately precede or follow the function declaration, will be interpreted by the shell. If someone runs Help Get-Info , they&amp;rsquo;ll get standard-formatted Help. 
 
 &amp;lt;# 
 .SYNOPSIS 
 Retrieves info from one or more computers. 
 .PARAMETER computername 
 The computer name(s) to retrieve the info from. 
 .PARAMETER logfile 
 The path and filename of a text file where failed computers will be logged. Defaults to c:\retries.txt. 
 .EXAMPLE 
 Get-ADComputer &amp;ndash;filter * | Select @{label=&amp;#39;computername&amp;#39;;expression={$_.name}} | Get-Info 
 .EXAMPLE 
 Get-Info &amp;ndash;computername SERVER2,SERVER3 
 .EXAMPLE 
 &amp;quot;localhost&amp;quot; | Get-Info 
 .EXAMPLE 
 Get-Info &amp;ndash;computername (Get-Content names.txt) 
 .EXAMPLE 
 Get-Content names.txt | Get-Info 
 #&amp;gt; 
 Function Get-Info { 
 [CmdletBinding()] 
 Param( 
 [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
 [string[]]$computername, 
 [string]$logfile = &amp;#39;c:\retries.txt&amp;#39; 
 ) 
 PROCESS { 
 Foreach ($computer in $computername) { 
 # do stuff here with $computer 
 } 
 } 
 } 
 
 (June Blender, one of the Windows PowerShell team and one of the folks chiefly responsible for the quality of PowerShell&amp;rsquo;s Help, buys me a drink every time I show folks how to comment their own functions like this. It helps document your function and makes it more accessible to Windows PowerShell users who know how to use the built-in help system. That means comment-based Help is a good idea. Run help about_comment_based_help within the shell for more details.) 
 Now all we have to do is make the function&amp;hellip;well&amp;hellip; do something. 
 Output: Pipeline 
 By spewing (that&amp;rsquo;s a technical term for &amp;ldquo;outputting&amp;rdquo;) data to the pipeline, you enable your function to work in an almost infinite variety of scenarios. Want CSV output? XML output? HTML? Databases? Need to filter or sort the output? No problem in the pipeline. The trick is to make sure your function is spewing objects, rather than some kind of preformatted text. In other words, Write-Host is almost always the wrong answer. If you&amp;rsquo;re using Write-Host , you&amp;rsquo;re probably doing it wrong. Instead: 
 
 Use Write-Debug to output debugging information, if needed. Running your function with the debug switch will enable this output. 
 Use Write-Verbose if you want to output step-by-step status information. Adding verbose to your function when running it will enable this information (for example, Get-Info &amp;ndash;computername localhost &amp;ndash;verbose ). 
 Use Write-Output to write information to the pipeline. 
 
 There are a LOT of techniques for constructing an object to output. Here&amp;rsquo;s the technique I prefer, mainly because I find it easiest to read: 
 
 &amp;lt;# 
 .SYNOPSIS 
 Retrieves info from one or more computers. 
 .PARAMETER computername 
 The computer name(s) to retrieve the info from. 
 .PARAMETER logfile 
 The path and filename of a text file where failed computers will be logged. Defaults to c:\retries.txt. 
 .EXAMPLE 
 Get-ADComputer &amp;ndash;filter * | Select @{label=&amp;#39;computername&amp;#39;;expression={$_.name}} | Get-Info 
 .EXAMPLE 
 Get-Info &amp;ndash;computername SERVER2,SERVER3 
 .EXAMPLE 
 &amp;quot;localhost&amp;quot; | Get-Info 
 .EXAMPLE 
 Get-Info &amp;ndash;computername (Get-Content names.txt) 
 .EXAMPLE 
 Get-Content names.txt | Get-Info 
 #&amp;gt; 
 Function Get-Info { 
 [CmdletBinding()] 
 Param( 
 [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
 [string[]]$computername, 
 [string]$logfile = &amp;#39;c:\retries.txt&amp;#39; 
 ) 
 BEGIN { 
 Remove-Item $logfile &amp;ndash;erroraction silentlycontinue 
 } 
 PROCESS { 
 Foreach ($computer in $computername) { 
 $continue = $true 
 try { 
 $os = Get-WmiObject &amp;ndash;class Win32_OperatingSystem &amp;ndash;computername $computer &amp;ndash;erroraction Stop 
 } catch { 
 $continue = $false 
 $computer | Out-File $logfile 
 } 
 if ($continue) { 
 $bios = Get-WmiObject &amp;ndash;class Win32_BIOS &amp;ndash;computername $computer 
 $obj = New-Object &amp;ndash;typename PSObject 
 $obj | Add-Member &amp;ndash;membertype NoteProperty &amp;ndash;name ComputerName &amp;ndash;value ($computer) &amp;ndash;passthru | 
 Add-Member &amp;ndash;membertype NoteProperty &amp;ndash;name OSVersion &amp;ndash;value ($os.caption) &amp;ndash;passthru | 
 Add-Member &amp;ndash;membertype NoteProperty &amp;ndash;name OSBuild &amp;ndash;version ($os.buildnumber) &amp;ndash;passthru | 
 Add-Member &amp;ndash;membertype NoteProperty &amp;ndash;name BIOSSerial &amp;ndash;value ($bios.serialnumber) &amp;ndash;passthru | 
 Add-Member &amp;ndash;membertype NoteProperty &amp;ndash;name SPVersion &amp;ndash;value ($os.servicepackmajorversion) 
 Write-Output $obj 
 } 
 
 } 
 } 
 } 
 
 Technically, I could have just added passthru to the final Add-Member and skipped Write-Output , but I wanted to reinforce the fact that Write-Output is your friend, because it writes to the pipeline. With this technique, almost anything can follow Get-Info in the pipeline. For example, check out this awesomeness: 
 
 Get-ADComputer &amp;ndash;filter * | Select-Object @{label=&amp;#39;computername&amp;#39;,expression={$_.Name}} | Get-Info | Where-Object &amp;ndash;filterscript { $_.OSBuild &amp;ndash;eq 7600 &amp;ndash;and $_.SPVersion &amp;ndash;ne 2 } | Export-CSV c:\needs-patched.txt 
 
 In other words, get me all of the computers running Windows build 7600 that don&amp;rsquo;t have Service Pack 2, and export their information to a .csv file that I can give to someone else who will be spending the weekend installing service packs. Ahem. Come Monday, I could run the same thing again and instead of outputting to a .csv file, do this: 
 
 Get-ADComputer &amp;ndash;filter * | Select-Object @{label=&amp;#39;computername&amp;#39;,expression={$_.Name}} | Get-Info | Where-Object &amp;ndash;filterscript { $_.OSBuild &amp;ndash;eq 7600 &amp;ndash;and $_.SPVersion &amp;ndash;ne 2 } | ConvertTo-HTML | Out-File \\webserver\webroot\fail.html 
 
 Now I have a simple HTML page sitting on my intranet server, listing the computers that still do not have the right service pack. The trick is all in the pipeline: By not worrying about input and output inside my function, and by instead letting the pipeline handle it, I have opened up a huge amount of flexibility. How my function is used can differ from day-to-day, without me doing any additional work. 
 Thank you, Don, for this awesome article. 
 I invite you to follow me on Twitter and Facebook . If you have any questions, send email to me at scripter@microsoft.com , or post your questions on the Official Scripting Guys Forum . See you tomorrow. Until then, peace. 
 Ed Wilson, Microsoft Scripting Guy...(&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/10/use-the-pipeline-to-create-robust-powershell-functions.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3427248" width="1" height="1" alt="" /&gt;</description></item><item><title>Dynamic Method Invocation in PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2010/12/14/dynamic-method-invocation-in-powershell.aspx</link><pubDate>Tue, 14 Dec 2010 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:8678</guid><dc:creator>Anonymous</dc:creator><description>Summary: Learn how to create a Windows PowerShell function to implement dynamic method invocation. Hey, Scripting Guy! What can you tell me about dynamic method invocation? -- PG Hello PG, Microsoft Scripting Guy Ed Wilson here. Today is day 2 of guest...(&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2010/12/14/dynamic-method-invocation-in-powershell.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3374830" width="1" height="1" alt="" /&gt;</description></item><item><title>Weekend Scripter: Where.exe—The What, Why, and How</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2010/07/24/weekend-scripter-where-exe-the-what-why-and-how.aspx</link><pubDate>Sat, 24 Jul 2010 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:7262</guid><dc:creator>Anonymous</dc:creator><description>Microsoft Scripting Guy Ed Wilson here. The sounds outside seems amplified by the inky darkness that grudgingly gives way to the early morning sun. I am sitting on the front porch sipping a cup of English Breakfast Tea, munching on a freshly baked cinnamon...(&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2010/07/24/weekend-scripter-where-exe-the-what-why-and-how.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3346218" width="1" height="1" alt="" /&gt;</description></item><item><title>Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (6/18/10)</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2010/06/18/hey-scripting-guy-quick-hits-friday-the-scripting-guys-respond-to-a-bunch-of-questions-6-18-10.aspx</link><pubDate>Fri, 18 Jun 2010 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:6869</guid><dc:creator>Anonymous</dc:creator><description>In this post : In Windows PowerShell, How Can I Pipe the Contents of a Property to a Command? Using WMI for Security Event Log Tracing &amp;#160; In Windows PowerShell, How Can I Pipe the Contents of a Property to a Command? &amp;#160; Hey, Scripting Guy! I’m...(&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2010/06/18/hey-scripting-guy-quick-hits-friday-the-scripting-guys-respond-to-a-bunch-of-questions-6-18-10.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3338744" width="1" height="1" alt="" /&gt;</description></item></channel></rss>