<?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 'Event 6' and 'guest blogger'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=Event+6,guest+blogger&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'Event 6' and 'guest blogger'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Expert Commentary: 2012 Scripting Games Advanced Event 6</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/04/23/expert-commentary-2012-scripting-games-advanced-event-6.aspx</link><pubDate>Mon, 23 Apr 2012 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:16099</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Microsoft senior software engineer on the Windows PowerShell team, Lee Holmes, provides expert commentary for 2012 Scripting Games Advanced Event 6.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Lee Holmes is the expert commentator for Advanced Event 6.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7077.hsg_2D00_4_2D00_23_2D00_12_2D00_adv_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7077.hsg_2D00_4_2D00_23_2D00_12_2D00_adv_2D00_1.jpg" alt="Photo of Lee Holmes" title="Photo of Lee Holmes" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Lee is a senior software engineer on the Microsoft Windows PowerShell team, and he has been an authoritative source of information about Windows PowerShell since its earliest betas. He is the author of the Windows PowerShell Cookbook, Windows PowerShell Pocket Reference, and the Windows PowerShell Quick Reference.&amp;nbsp;&lt;br /&gt; &amp;nbsp;&lt;br /&gt; Blog:&amp;nbsp;&lt;a href="http://www.leeholmes.com/blog" target="_blank"&gt;Precision Computing&lt;/a&gt;&amp;nbsp;&lt;br /&gt; Twitter:&amp;nbsp;&lt;a href="http://www.twitter.com/Lee_Holmes" target="_blank"&gt;http://www.twitter.com/Lee_Holmes&lt;/a&gt;&amp;nbsp;&lt;br /&gt; LinkedIn:&amp;nbsp;&lt;a href="http://www.linkedin.com/pub/lee-holmes/1/709/383" target="_blank"&gt;http://www.linkedin.com/pub/lee-holmes/1/709/383&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The script for the 2012 Scripting Games Advanced Event 6 is pretty descriptive, so rather than go over it again line-by-line, I thought it&amp;rsquo;d be helpful to talk about two of the main ideas that went into creating the script: jobs and streaming.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Networking is slow, parallel jobs are not&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;When running a large network-bound operation (such as retrieving the &lt;b&gt;Win32_OperatingSystem&lt;/b&gt; class from a long list of computers), your computer spends the vast majority of its time waiting on the network: waiting for the connection, waiting for the computer to respond, and waiting for the data to get back.&lt;/p&gt;
&lt;p&gt;To address this problem, Windows PowerShell 2.0 introduced the concept of &amp;ldquo;jobs&amp;rdquo;&amp;ndash;primarily in remoting, WMI, and eventing. When you assign a multimachine task to a job, Windows PowerShell distributes your commands among many worker threads, which it then runs in parallel. Each worker thread processes one computer at a time. As each child job completes (for example, a remote WMI query against a specific computer), Windows PowerShell feeds that worker thread a command for another computer. By default, Windows PowerShell launches 32 child jobs in parallel.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s most amazing about Windows PowerShell jobs running 32 tasks in parallel is not that it makes things 32 times faster. It&amp;rsquo;s that it makes them even faster than that! The reason is a branch of computer science called &amp;ldquo;queueing theory.&amp;rdquo; Here&amp;rsquo;s a summary for the busy admin&amp;hellip;&lt;/p&gt;
&lt;p&gt;As a thought experiment, consider running a query against 92 computers one-by-one. Also, imagine that your first and second computers are rebooting, and they take a minute before failing to return their response. The other 90 return their responses in two seconds each.&lt;/p&gt;
&lt;p&gt;The total time for that query is five minutes, for an average of about 3.3 seconds per successful computer. This is the same problem that happens when a bunch of hungry shoppers get stuck behind the crazy person paying with 100 coupons at the grocery store: every delay impacts everybody in line.&lt;/p&gt;
&lt;p&gt;Now, consider the impact of parallel jobs in Windows PowerShell. Those first two rebooting computers use up two of our available worker threads for an entire minute, but we still have 30 more to process the remaining 90 computers. The total time for that query is about six seconds, giving an average time of about 0.07 seconds per successful computer. That&amp;rsquo;s 50 times faster than processing one computer at a time! Surprising, but incredibly cool. In the grocery store, this is like waiting in a single line, but having 32 cashiers serving from it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Streaming is important&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Given that this is likely to be a long-running script, you&amp;rsquo;re going to want to keep your results as dynamic as possible.&lt;/p&gt;
&lt;p&gt;As the first step toward that, this script makes good use of the &lt;b&gt;&amp;ndash;Verbose&lt;/b&gt; and &lt;b&gt;&amp;ndash;Progress&lt;/b&gt; streams. As the script processes computers, it emits a progress message telling you which one it&amp;rsquo;s working on. If you specify the &lt;b&gt;&amp;ndash;Verbose&lt;/b&gt; parameter, you get even more detail&amp;mdash;specifically, the uptime information as it writes it to the CSV.&lt;/p&gt;
&lt;p&gt;This approach solves a common problem that I see: scripts that force their verbose or debugging information on the end user. The ultimate example of this sin is aggressive use of the &lt;b&gt;Write-Host&lt;/b&gt; cmdlet. When you run this kind of script, you get reams and reams of text on screen, with no way to silence it. You can&amp;rsquo;t tell good information from bad, and other scripts can&amp;rsquo;t use it without this internal debugging information spewing all over the screen.&lt;/p&gt;
&lt;p&gt;In addition to streaming progress, the script also streams its output. Although it would be easiest to collect all of the job output into a variable and then dump it to the CSV, all of your data is lost if you ever cancel the script while it is executing. When your script streams its output, you can easily monitor the results as they are received with this simple command:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Content 20120409_Uptime.csv -Wait&lt;/p&gt;
&lt;p&gt;If your query takes an hour to complete, it&amp;rsquo;s nice to be able to check its progress before then.&lt;/p&gt;
&lt;p&gt;Jobs and streaming&amp;mdash;two useful techniques to maximize the efficiency of long-running tasks. Now, here is my solution for Advanced Event 6:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;##############################################################################&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;##&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## Get-DistributedUptime&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;##&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;##############################################################################&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;#&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.SYNOPSIS&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Retrieves the uptime information (as of 8:00 AM local time) for the list of&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;computers defined in the $computers variable. Output is stored in a&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;date-stamped CSV file in the &amp;quot;My Documents&amp;quot; folder, with a name ending in&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;_Uptime.csv&amp;quot;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.EXAMPLE&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-DistributedUptime&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;param(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## Overwrites the output file, if it exists&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Parameter()]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Switch] $Force&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## Set up common configuration options and constants&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$reportStart = Get-Date -Hour 8 -Minute 0 -Second 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$outputPath = Join-Path ([Environment]::GetFolderPath(&amp;quot;MyDocuments&amp;quot;)) `&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&amp;quot;{0:yyyyddMM}_Uptime.csv&amp;quot; -f $reportStart)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## See if the file exists. If it does (and the user has not specified -Force),&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## then exit because the script has already been run today.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;if(Test-Path $outputPath)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(-not $Force)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Verbose &amp;quot;$outputPath already exists. Exiting&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Remove-Item $outputPath&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## Get the list of computers. If desired, this list could be ready from&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## a test file as well:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## $computers = Get-Content computers.txt&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$computers = &amp;quot;EDLT1&amp;quot;,&amp;quot;EDLT2&amp;quot;,&amp;quot;EDLT3&amp;quot;,&amp;quot;EDLT4&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## Start the job to process all of the computers. This makes 32&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## connections at a time, by default.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$j = Get-WmiObject Win32_OperatingSystem -ComputerName $computers -AsJob&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;## While the job is running, process its output&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;do&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## Wait for some output, then retrieve the new output&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $output = @(Wait-Job $j | Receive-Job)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach($result in $output)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## We got a result, start processing it&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Progress -Activity &amp;quot;Processing&amp;quot; -Status $result.PSComputerName&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## Convert the DMTF date to a .NET Date&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $lastbootupTime = $result.ConvertToDateTime($result.LastBootUpTime)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## Subtract the time the report run started. If the system&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## booted after the report started, ignore that for today.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $uptimeUntilReportStart = $reportStart - $lastbootupTime&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($uptimeUntilReportStart -lt 0)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $uptimeUntilReportStart = New-TimeSpan&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## Generate the output object that we&amp;#39;re about to put&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## into the CSV. Add a call to Select-Object at the end&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## so that we can ensure the order.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $outputObject = New-Object PSObject -Property @{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ComputerName = $result.PSComputerName;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Days = $uptimeUntilReportStart.Days;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Hours = $uptimeUntilReportStart.Hours;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Minutes = $uptimeUntilReportStart.Minutes;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Seconds = $uptimeUntilReportStart.Seconds;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Date = &amp;quot;{0:M/dd/yyyy}&amp;quot; -f $reportStart&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } | Select ComputerName, Days, Hours, Minutes, Seconds, Date&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Verbose $outputObject&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## Append it to the CSV. If the CSV doesn&amp;#39;t exist, create it and&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## PowerShell will create the header as well.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(-not (Test-Path $outputPath))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $outputObject | Export-Csv $outputPath -NoTypeInformation&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## Otherwise, just append the data to the file. Lines&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## zero and one that we are skipping are the header&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ## and type information.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ($outputObject | ConvertTo-Csv)[2]&amp;nbsp; &amp;gt;&amp;gt; $outputPath&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} while($output)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;~Lee&lt;/p&gt;
&lt;p&gt;2012 Scripting Games Guest Commentator Week Part 2 will continue tomorrow when we will present the scenario for Event 7.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ed Wilson, Microsoft Scripting Guy&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3491357" width="1" height="1" alt="" /&gt;</description></item><item><title>Expert Commentary: 2012 Scripting Games Beginner Event 6</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/04/23/expert-commentary-2012-scripting-games-beginner-event-6.aspx</link><pubDate>Mon, 23 Apr 2012 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:16098</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Microsoft Windows PowerShell MVP, Sean Kearney, provides expert commentary for 2012 Scripting Games Beginner Event 6.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Sean Kearney is the expert commentator for Beginner Event 6.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0243.hsg_2D00_4_2D00_23_2D00_12_2D00_beg_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0243.hsg_2D00_4_2D00_23_2D00_12_2D00_beg_2D00_1.jpg" alt="Photo of Sean Kearney" title="Photo of Sean Kearney" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Sean&amp;nbsp;&lt;i&gt;&amp;ldquo;The Kraken&amp;rdquo;&lt;/i&gt;&amp;nbsp;Kearney is an infrastructure support analyst, Microsoft MVP in Windows PowerShell, and member of the Springboard Technical Experts Program. He is also one of this year&amp;rsquo;s first ever Honorary Scripting Guys and the mystery persona behind&amp;nbsp;&lt;i&gt;The BATCHman and Cmdlet&lt;/i&gt;. He is presently writing a book about Windows PowerShell.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;He is so passionate about Windows PowerShell that he tried naming a pet gerbil &amp;ldquo;Cmdlet,&amp;rdquo; and then he attempted to use a&amp;nbsp;&lt;b&gt;Get-Wheel | Invoke-Run&lt;/b&gt;&amp;nbsp;on it. We have been advised that he is also barred from any caffeinated beverages when he is presenting due to &amp;ldquo;The Edmonton Affair&amp;rdquo; at TechDays Canada.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re staring at the desk trying desperately to concentrate and force it to fold into the shape of an Armadillo, when the phone rings breaking your concentration&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;BARK!&amp;rdquo; a voice barks at you from the other end of the wire.&amp;nbsp; It&amp;rsquo;s the boss.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;I need to be able pull up metrics on our various servers and have to see how long any one of them has been running. Can you solve this for me? I&amp;rsquo;ve done some research, and I found that there is information in WMI that could help, but I&amp;rsquo;m not much of a programmer.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;You smile knowing this is a job Windows PowerShell can solve easily. &amp;ldquo;Sure! What do you have from WMI?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Well there&amp;rsquo;s a property called &lt;b&gt;win32_operatingsystem&lt;/b&gt; that should have the time the computer started up, do you think you could calculate that against the current date somehow?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;No problem sir&amp;hellip;.give me a few minutes, and I&amp;rsquo;ll create a simple script in Windows PowerShell to solve it all.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;You immediately head into the task by firing up Windows PowerShell to see what properties are available from &lt;b&gt;win32_operatingsystem&lt;/b&gt;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;GET-WMIOBJECT win32_operatingsystem | GET-MEMBER&lt;/p&gt;
&lt;p&gt;Drilling down the list you note that there is one called &lt;b&gt;LastBootupTime&lt;/b&gt;. &amp;ldquo;Aha!&amp;nbsp; I&amp;rsquo;ll just pull up this property and subtract todays date!&amp;rdquo; you smile to yourself. Sometimes the boss IS right.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;GET-WMIOBJECT win32_operatingsystem | SELECT-OBJECT &amp;ndash;expandproperty LastBootupTime&lt;/p&gt;
&lt;p&gt;But you stare at the screen with the results with a blank look.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;20110201055602.000000-300&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Whaaaaaaa??????????????????!!!!!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Your eyeballs pop out and roll on the desk. After you pick them up and put them back in your sockets, you take a second look and realize that you are looking at the date. It&amp;rsquo;s just in a different format. You decide to see if there might be some help from &lt;b&gt;Get-Help&lt;/b&gt; about how to parse the date differently.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;GET-HELP GET-DATE &amp;ndash;examples&lt;/p&gt;
&lt;p&gt;Drilling down near example #7, you notice a scenario that almost matches&amp;mdash;manipulating the date from win32_bios. It appears that the WMI date is stored differently and there is an available method to convert it to a &lt;b&gt;DotNet&lt;/b&gt; format.&lt;/p&gt;
&lt;p&gt;You grab the object from &lt;b&gt;win32_operatingsystem&lt;/b&gt; and store it away to mimic how the example presented it.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$A= GET-WMIOBJECT win32_operatingsystem&lt;/p&gt;
&lt;p&gt;Using the example from &lt;b&gt;Get-Help&lt;/b&gt;, you then try to convert the WMI object for &lt;b&gt;LastBootupTime&lt;/b&gt; to a normal &lt;b&gt;DotNet&lt;/b&gt; date.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$A.converttodatetime($A.LastBootupTime)&lt;/p&gt;
&lt;p&gt;You blink and look at the screen in wonder and amazement.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Tuesday, February 01, 2011 5:56:02 AM&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Yes!&amp;rdquo; You nearly jump out of your shorts, knocking over the gerbil cage. &amp;ldquo;Now all I need to do is subtract this date from the current date and show the difference! Oh, I can&amp;rsquo;t wait to have this running on the servers!&amp;rdquo;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;# Get name of local Server&lt;br /&gt; $Machine=Hostname&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;# Get today&amp;rsquo;s date&lt;br /&gt; $Today=GET-DATE&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;# Get the WMI object for the start time&lt;br /&gt; $A=GET-WMIOBJECT win32_operatingsystem&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;# Obtain the Boot time in DOTNET format&lt;br /&gt; $BootTime=$A.ConverttoDateTime($A.LastBootupTime)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;# Calculate how many days the system has been up&lt;br /&gt; $Uptime=$Today-$Boottime&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;# Obtain all the data for the output string&lt;br /&gt; $Days=$Uptime.Days&lt;br /&gt; $Hours=$Uptime.Hours&lt;br /&gt; $Minutes=$Uptime.Minutes&lt;br /&gt; $Seconds=$Uptime.Seconds&lt;br /&gt; $JustDate=$Today.toshortdatestring()&lt;br /&gt; $JustTime=$Today.toshorttimestring()&lt;/p&gt;
&lt;p&gt;&amp;ldquo;The computer &lt;b&gt;$Machine&lt;/b&gt; has been up for &lt;b&gt;$Days&lt;/b&gt; days, &lt;b&gt;$Hours&lt;/b&gt; hours, &lt;b&gt;$Minutes&lt;/b&gt; minutes, &lt;b&gt;$Seconds&lt;/b&gt; seconds, as of &lt;b&gt;$JustDate $JustTime&lt;/b&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;You save the file as GETUPTIME.PS1 and hand it to the boss. He pops onto the security server to test it. He smiles.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Great job! I knew investing in an IT Pro who knew Windows PowerShell would save me in the long term!&amp;nbsp; Thanks!&amp;rdquo; And he hands you keys to the most hallowed place in the office&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;hellip;the executive coffee room!&lt;/p&gt;
&lt;p&gt;2012 Scripting Games Guest Commentator Week Part 2 will continue tomorrow when we will present the scenario for Event 7.&lt;/p&gt;
&lt;p&gt;I invite you to follow me on &lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt; and &lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at &lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. See you tomorrow. Until then, peace.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ed Wilson, Microsoft Scripting Guy&lt;/b&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3491354" width="1" height="1" alt="" /&gt;</description></item><item><title>Expert Solution for 2011 Scripting Games Beginner Event 6: Parse the Windows Update Log for Errors with PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2011/04/25/expert-solution-for-2011-scripting-games-beginner-event-6-parse-the-windows-update-log-for-errors-with-powershell.aspx</link><pubDate>Mon, 25 Apr 2011 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:10115</guid><dc:creator>Anonymous</dc:creator><description>Summary : Microsoft MVP, Sean Kearney, uses Windows PowerShell to solve 2011 Scripting Games Beginner Event 6 and parse the Windows update log for errors. Microsoft Scripting Guy, Ed Wilson, here. Today we have Sean Kearney to provide his solution for...(&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/04/25/expert-solution-for-2011-scripting-games-beginner-event-6-parse-the-windows-update-log-for-errors-with-powershell.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3421662" width="1" height="1" alt="" /&gt;</description></item></channel></rss>