<?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 'Scripting Guy!' and 'Boe Prox'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=Scripting+Guy!,Boe+Prox&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'Scripting Guy!' and 'Boe Prox'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Installing WSUS on Windows Server 2012  </title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/15/installing-wsus-on-windows-server-2012.aspx</link><pubDate>Mon, 15 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:22789</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong style="font-size:12px;"&gt;Summary&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;: Honorary Scripting Guy, Boe Prox, talks about installing WSUS on Windows Server 2012 via Windows PowerShell.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Welcome back today to Honorary Scripting Guy, &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/boe+prox/" target="_blank"&gt;Boe Prox&lt;/a&gt;. Without further ado, here is Boe&amp;hellip;&lt;/p&gt;
&lt;p&gt;In a previous Hey, Scripting Guy! Blog post, &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/16/introduction-to-wsus-and-powershell.aspx" target="_blank"&gt;Introduction to WSUS and PowerShell&lt;/a&gt;, I demonstrated how you can download the Windows Server Update Services (WSUS) installation file and use various parameters to customize a WSUS installation on a local or remote system. With Windows Server 2012, we get a new version of WSUS that can be installed through Server Manager and also by&amp;hellip;you guessed it&amp;hellip;Windows PowerShell!&lt;/p&gt;
&lt;p&gt;We can do the installation by using the &lt;strong&gt;Install-WindowsFeature&lt;/strong&gt; cmdlet and specifying the proper feature names that you would like to have installed. In the case of WSUS, we are looking only at the update services feature. I will also take a look at some of the new cmdlets that are available in the UpdateServices module, which is available in Windows Server 2012 to help configure the WSUS server.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at the possible subfeatures that are available by using the &lt;strong&gt;Get-WindowsFeature&lt;/strong&gt; cmdlet and specifying &lt;strong&gt;UpdateServices*&lt;/strong&gt; for the &lt;strong&gt;Name&lt;/strong&gt; parameter.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WindowsFeature &amp;ndash;Name UpdateServices*&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/6012.hsg_2D00_4_2D00_15_2D00_13_2D00_1.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6012.hsg_2D00_4_2D00_15_2D00_13_2D00_1.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You could try to install everything, but that will end badly for you because there will be a conflict between using the Windows Internal Database (WID) and using another SQL Server database (local or remote) to store the SUSDB database on.&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/4188.hsg_2D00_4_2D00_15_2D00_13_2D00_2.png"&gt;&lt;img style="border:0px currentColor;" title="Image of error message" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4188.hsg_2D00_4_2D00_15_2D00_13_2D00_2.png" alt="Image of error message" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So which one should I choose? That depends on your environment and what your requirements are to support patching in your enterprise. Luckily for you, I will show examples of using the WID database or using another SQL Server database as part of the WSUS installation. After the installation, I will show one last thing you can do as a post installation that will allow you to specify a new location for the software update files and where the database is located.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with the easiest, which is the WID database. I say easiest because it really comes down to just running a single line of code to get everything installed. Just to see what might be installed, I can use the &lt;strong&gt;WhatIf&lt;/strong&gt; switch first.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Install-WindowsFeature -Name UpdateServices -IncludeManagementTools &amp;ndash;WhatIf&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/4812.hsg_2D00_4_2D00_15_2D00_13_2D00_3.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4812.hsg_2D00_4_2D00_15_2D00_13_2D00_3.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From the looks of it, not only will WSUS be installed, but we also will be installing the WID database and some IIS components that are used for client check-ins and other things. I am confident that this is what I need, so let&amp;rsquo;s remove &lt;strong&gt;WhatIf&lt;/strong&gt; and let it run again.&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/0743.hsg_2D00_4_2D00_15_2D00_13_2D00_4.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0743.hsg_2D00_4_2D00_15_2D00_13_2D00_4.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wait for a bit&amp;hellip;&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/8306.hsg_2D00_4_2D00_15_2D00_13_2D00_5.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8306.hsg_2D00_4_2D00_15_2D00_13_2D00_5.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And we are now finished with the installation. As you can see, we have a message stating some additional configuration may be required before our WSUS server can be up and running. In this case, we still need to configure a location for the update files to be stored.&lt;/p&gt;
&lt;p&gt;This is where wsusutil.exe will come into play. This executable is located at C:\Program Files\Update Services\Tools. Besides the usual parameters that you can use with this utility, there is another set of parameters that become available when you use the &lt;strong&gt;PostInstall&lt;/strong&gt; argument.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.\wsusutil.exe postinstall /?&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/6864.hsg_2D00_4_2D00_15_2D00_13_2D00_6.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6864.hsg_2D00_4_2D00_15_2D00_13_2D00_6.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We have parameters for specifying where to store the content and for where to build the database, if needed. Note that this can be used to specify a database that is local or remote (you will see this used on a remote system later).&lt;/p&gt;
&lt;p&gt;Before I say where I want the content, I had better create a folder to store it. I don&amp;rsquo;t want all of this on my system drive, so I will create the folder on my D: drive.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;New-Item -Path D: -Name WSUS -ItemType Directory&lt;/p&gt;
&lt;p&gt;Now I can run the following command to configure my content directory to download and save all of the update files to D:\WSUS.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.\wsusutil.exe postinstall CONTENT_DIR=D:\WSUS&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/8304.hsg_2D00_4_2D00_15_2D00_13_2D00_7.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8304.hsg_2D00_4_2D00_15_2D00_13_2D00_7.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And with that, we have now configured the content directory on another drive to save the update files. Very simple&amp;hellip;and a big recommendation to do it regardless!&lt;/p&gt;
&lt;h2&gt;Specify an alternate SQL Server&lt;/h2&gt;
&lt;p&gt;What if I want to specify a different SQL Server for saving the data instead of relying on a WID instance locally? Fortunately for us (and as you saw previously), this is an available option by using WSUSUtil.exe PostInstall. Going back to the beginning, I will perform a different installation of WSUS, this time specifying that I want a different SQL Server database.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Install-WindowsFeature -Name UpdateServices-Services,UpdateServices-DB -IncludeManagementTools&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/8508.hsg_2D00_4_2D00_15_2D00_13_2D00_8.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8508.hsg_2D00_4_2D00_15_2D00_13_2D00_8.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now we need to use WSUSUtil again to not only specify the Content directory, but also to specify the SQL Server database that I want to use for my WSUS server. The WSUS server must be on a domain for the remote SQL Server database build to work. If it isn&amp;rsquo;t, you will get a message that states the host is unknown.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;.\wsusutil.exe postinstall SQL_INSTANCE_NAME=&amp;quot;DC1\SQL2008&amp;quot; CONTENT_DIR=D:\WSUS&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/2870.hsg_2D00_4_2D00_15_2D00_13_2D00_9.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2870.hsg_2D00_4_2D00_15_2D00_13_2D00_9.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And after a few minutes, the configuration has completed with the Content directory on D:\WSUS and the SUSDB database configured on my remote SQL Server.&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/5076.hsg_2D00_4_2D00_15_2D00_13_2D00_10.png"&gt;&lt;img style="border:0px currentColor;" title="Image of menu" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5076.hsg_2D00_4_2D00_15_2D00_13_2D00_10.png" alt="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Inspect the WSUS Installation State&lt;/h2&gt;
&lt;p&gt;By using my current installation of WSUS and the remote SQL Server database, we can now check the Best Practices Analyzer to see if anything else is required before we configure the WSUS server and kick off synchronization get all of the update metadata.&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Invoke-BpaModel -ModelId Microsoft/Windows/UpdateServices&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/3733.hsg_2D00_4_2D00_15_2D00_13_2D00_11.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3733.hsg_2D00_4_2D00_15_2D00_13_2D00_11.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s see the results of our scan&amp;hellip;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-BpaResult -ModelId Microsoft/Windows/UpdateServices |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Select Title,Severity,Compliance | Format-List&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/3582.hsg_2D00_4_2D00_15_2D00_13_2D00_12.png"&gt;&lt;img style="border:0px currentColor;" title="Image of command output" src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3582.hsg_2D00_4_2D00_15_2D00_13_2D00_12.png" alt="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With the exception that I haven&amp;rsquo;t configured the WSUS server to use a required language pack (English in my case), everything else is compliant. Now it is time to finish configuring the WSUS server and get this synchronization kicked off.&lt;/p&gt;
&lt;p&gt;First I&amp;rsquo;ll configure the languages and tell my server where I want to synchronize. In this case I want to sync up with Microsoft Updates. After I do that, I will perform an initial synchronization to pull down all of the available categories, classifications, and possible updates that can be approved.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;For more information about some of the configuration properties that are set in the following code, see &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.updateservices.administration.iupdateserverconfiguration_properties(v=vs.85).aspx" target="_blank"&gt;IUpdateServerConfiguration Properties&lt;/a&gt; &amp;nbsp;on MSDN.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Get WSUS Server Object&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus = Get-WSUSServer&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Connect to WSUS server configuration&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsusConfig = $wsus.GetConfiguration()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Set to download updates from Microsoft Updates&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Set-WsusServerSynchronization &amp;ndash;SyncFromMU&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Set Update Languages to English and save configuration settings&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsusConfig.AllUpdateLanguagesEnabled = $false&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsusConfig.SetEnabledUpdateLanguages(&amp;quot;en&amp;quot;)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsusConfig.Save()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Get WSUS Subscription and perform initial synchronization to get latest categories&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription = $wsus.GetSubscription()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.StartSynchronizationForCategoryOnly()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;While ($subscription.GetSynchronizationStatus() -ne &amp;#39;NotProcessing&amp;#39;) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Host &amp;quot;.&amp;quot; -NoNewline&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Start-Sleep -Seconds 5&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Host &amp;quot;Sync is done.&amp;quot;&lt;/p&gt;
&lt;p&gt;You may have noticed that I didn&amp;rsquo;t have to run &lt;strong&gt;Import-Module&lt;/strong&gt; before using the UpdateServices module cmdlets. This is because Windows PowerShell&amp;nbsp;3.0 supports automatic loading of the modules when a specific cmdlet from a module is used.&lt;/p&gt;
&lt;p&gt;Now that we have pulled down the classifications and platforms, it is time to filter the platforms for which I want updates and the classifications I want. Your preference for platforms and classifications will vary based on your environment and requirements.&lt;/p&gt;
&lt;p&gt;When that is done, we will configure WSUS to synchronize once a day automatically at midnight, and kick off another synchronization to pull down the update metadata (not the actual update files) from the Microsoft Update server.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Configure the Platforms that we want WSUS to receive updates&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WsusProduct | where-Object {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_.Product.Title -in (&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;CAPICOM&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Silverlight&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;SQL Server 2008 R2&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;SQL Server 2005&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;SQL Server 2008&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Exchange Server 2010&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Windows Server 2003&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Windows Server 2008&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Windows Server 2008 R2&amp;#39;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} | Set-WsusProduct&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Configure the Classifications&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WsusClassification | Where-Object {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_.Classification.Title -in (&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Update Rollups&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Security Updates&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Critical Updates&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Service Packs&amp;#39;,&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;Updates&amp;#39;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} | Set-WsusClassification&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Configure Synchronizations&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.SynchronizeAutomatically=$true&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Set synchronization scheduled for midnight each night&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.SynchronizeAutomaticallyTimeOfDay= (New-TimeSpan -Hours 0)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.NumberOfSynchronizationsPerDay=1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.Save()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Kick off a synchronization&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.StartSynchronization()&lt;/p&gt;
&lt;p&gt;It may take a while to complete the synchronization. When it has completed, you can begin reviewing the available updates that your systems require. Whether you want to keep everything installed and configured on a single server or you want to keep your SUSDB database on a remote SQL Server, you will find that it is easily accomplished by using Windows PowerShell.&lt;/p&gt;
&lt;p&gt;That is all for today&amp;rsquo;s blog about working with WSUS on Windows Server&amp;nbsp;2012. The next blog I have lined up will deal with using the UpdateServices module to configure the clients and approve or decline updates. In addition, we will dip our toes into WSUS API to set up Computer Groups for the clients and to remove clients from WSUS.&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;Thank you, Boe, for a great blog post. Join us tomorrow for a guest blog by Honorary Scripting Guy and Windows PowerShell MVP, Don Jones.&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;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&lt;span style="font-size:12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3564383" width="1" height="1" alt="" /&gt;</description></item><item><title>Windows Software Update Services</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2013/04/02/windows-software-update-services.aspx</link><pubDate>Tue, 02 Apr 2013 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:22552</guid><dc:creator>Anonymous</dc:creator><description>&lt;p align="left"&gt;&lt;strong&gt;Summary&lt;/strong&gt;: Honorary Scripting Guy, Boe Prox, shares an excerpt from his contribution to the book, &lt;em&gt;PowerShell Deep Dives&lt;/em&gt;.&lt;/p&gt;
&lt;p align="left"&gt;Microsoft Scripting Guy, Ed Wilson, is here. This week we will not have our usual&amp;nbsp;&lt;strong&gt;PowerTip&lt;/strong&gt;. Instead we have excerpts from seven books from Manning Press. In addition, each blog will have a special code for 50% off the book being excerpted that day. Remember that the code is valid only for the day the excerpt is posted. The coupon code is also valid for a second book from the Manning collection.&lt;/p&gt;
&lt;p&gt;Today, the excerpt is from &lt;a href="http://www.manning.com/hicks/"&gt;PowerShell Deep Dives&lt;/a&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Edited by Jeffery Hicks, Richard Siddaway, Oisin Grehan, and Aleksandar Nikolic.&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/0184.hsg_2D00_4_2D00_2_2D00_13_2D00_1.jpg"&gt;&lt;img title="Photo of book cover" src="http://blogs.technet.com/resized-image.ashx/__size/200x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0184.hsg_2D00_4_2D00_2_2D00_13_2D00_1.jpg" alt="Photo of book cover" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Whether you just started using Windows PowerShell or are at a more advanced level, there are two things you should always look at while writing a script: performance and execution time. With the introduction of Windows PowerShell 3.0 there are a lot of new modules and cmdlets available to you. What a lot of people don&amp;rsquo;t realize is that Microsoft also improves and expands already existing modules, and their cmdlets. This is especially the case with Windows PowerShell 3.0.&lt;/p&gt;
&lt;p class="Body1" align="left"&gt;Here&amp;rsquo;s Boe&amp;hellip;&lt;/p&gt;
&lt;p class="Body1" align="left"&gt;Although the UI can be clunky and slow, there is an API with WSUS, a new module that is available in Windows Server 2012, and even an open source WSUS module that I wrote called &lt;a href="http://poshwsus.codeplex.com/"&gt;PoshWSUS&lt;/a&gt;, which can more effectively allow you to quickly manage and generate reports by using Windows PowerShell.&lt;/p&gt;
&lt;p class="Body1" align="left"&gt;Instead of looking at the existing cmdlets available in the 2012 Windows Server Update Services module, I will dive into the API and show you some tricks to further extend the reach of Windows PowerShell into WSUS. I&amp;rsquo;ll show how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Look at the WSUS configuration and events.&lt;/li&gt;
&lt;li&gt;Provide reporting on various client and patch statuses.&lt;/li&gt;
&lt;li&gt;Start and view synchronization progress and history.&lt;/li&gt;
&lt;li&gt;Viewing and create automatic installation rules to simplify patch management by approving the common updates that your clients require.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 class="Head2"&gt;WSUS server configuration and events&lt;/h2&gt;
&lt;p class="Body1" align="left"&gt;In WSUS, some of the most basic administration concepts are client management and patch management. Before Windows Server 2012, the only two solutions to this were working with the UI or digging into the API via scripts or the open source module, PoshWSUS. With Server 2012, we now have a WSUS module called UpdateServices that makes managing clients easier. The UpdateServices module is only available to use on the WSUS server, which isn&amp;rsquo;t bad if you plan to use Windows PowerShell remoting to manage the server. If you are not running Windows Server 2012, the module will not be available, and you need to use the API to manage a remote WSUS server.&lt;/p&gt;
&lt;h3 class="Head2"&gt;Initial connection&lt;/h3&gt;
&lt;p class="Body1" align="left"&gt;To make a connection to the WSUS server locally or remotely with the API, you need the WSUS Administration console installed on the system that you will be making the connection from. After the console has been installed, you will have access to the required assemblies that you can the load and use for the WSUS connection. So with that, lets load the assembly, and then we can make the initial connection to the WSUS server.&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;[reflection.assembly]::LoadWithPartialName(&amp;quot;Microsoft.UpdateServices.Administration&amp;quot;) | out-null&lt;/p&gt;
&lt;p class="Code"&gt;For the connection attempt, I will be using the Microsoft.UpdateServices.Administration.AdminProxy class along with the GetUpdateServer() method. This method accepts 1 of 3 parameter sets based on your WSUS configuration and if it is a remote or local connection. For the remote connection that I will be making, I need only supply the remote system name, a Boolean value that will say whether the connection is secure, and the remote port that I need to connect to on the WSUS server. (Acceptable ports for WSUS are 8080 and 8530 for non-secure ports and 443 and 8531 for SSL.)&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Boe-PC&amp;quot;,&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $False,&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;8530&amp;quot;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$Wsus&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;WebServiceUrl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : http://BOE-PC:8530/ApiRemoting30/WebService.asmx&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;BypassApiRemoting&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;IsServerLocal&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : BOE-PC&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Version&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 6.2.9200.16384&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;IsConnectionSecureForApiRemoting : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;PortNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 8530&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;PreferredCulture&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : en&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ServerName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : BOE-PC&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UseSecureConnection&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ServerProtocolVersion&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 1.8&lt;/p&gt;
&lt;p class="Code"&gt;From here, you can see what version of the WSUS software you are running, among other things. The most important thing here is that you can now see that we have successfully connected to the WSUS server.&lt;/p&gt;
&lt;h3 class="Head2"&gt;Viewing WSUS configuration&lt;/h3&gt;
&lt;p class="Body1" align="left"&gt;After the initial connection has been made, you can easily take a look at the internal configuration settings of the WSUS server by using the &lt;strong&gt;GetConfiguration()&lt;/strong&gt;&lt;strong&gt; &lt;/strong&gt;method of the Microsoft.UpdateServices.Internal.BaseApi.UpdateServer object.&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;$wsus.GetConfiguration()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;LastConfigChange&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 9/17/2012 2:22:43 AM&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ServerId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 64ad0f03-e81d-4539-883d-0c08066d1e82&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;SupportedUpdateLanguages&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : {he, cs, fr, es...}&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;TargetingMode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Server&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;SyncFromMicrosoftUpdate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;IsReplicaServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;HostBinariesOnMicrosoftUpdate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpstreamWsusServerName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpstreamWsusServerPortNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 8530&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpstreamWsusServerUseSsl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UseProxy&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ProxyName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ProxyServerPort&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 80&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UseSeparateProxyForSsl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;SslProxyName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;SslProxyServerPort&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 443&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;AnonymousProxyAccess&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ProxyUserName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ProxyUserDomain&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;HasProxyPassword&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;AllowProxyCredentialsOverNonSsl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;hellip;&lt;/p&gt;
&lt;p class="Code"&gt;This is just a marginal number of the 121 properties that are returned with this method. The majority of these properties are settable, meaning that you can easily update these from Windows PowerShell. Use caution when making any changes to the properties because it could leave your server in an unusable state!&lt;/p&gt;
&lt;h3 class="Head2"&gt;Viewing the WSUS database connection&lt;/h3&gt;
&lt;p class="Body1" align="left"&gt;You can take a look at the database connection and the database properties from your WSUS server by using the &lt;strong&gt;GetDatabaseConfiguration()&lt;/strong&gt; method and the &lt;strong&gt;CreateConnection()&lt;/strong&gt; method from the created Microsoft.UpdateServices.Internal.DatabaseConfiguration object.&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;$wsus.GetDatabaseConfiguration()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ServerName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : MICROSOFT##WID&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DatabaseName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : SUSDB&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;IsUsingWindowsInternalDatabase : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;AuthenticationMode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : WindowsAuthentication&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UserName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Password&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$wsus.GetDatabaseConfiguration().CreateConnection()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;QueryTimeOut&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;: 150&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;LoginTimeOut&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 60&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ConnectionPooling : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ApplicationName&amp;nbsp;&amp;nbsp; : WSUS:powershell:1824&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UserLoginName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UseIntegrated&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ConnectionString&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;MaxPoolSize&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 100&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DoRetry&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DefaultRetryTimes : 3&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ServerName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : MICROSOFT##WID&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DatabaseName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : SUSDB&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Password&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;IsConnected&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;InTransaction&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code"&gt;The amount of detail that you can get regarding the database is pretty nice. In fact, you could dive even deeper into the database if you wanted, but that is beyond the scope of this blog.&lt;/p&gt;
&lt;h3 class="Head2"&gt;Viewing WSUS event history&lt;/h3&gt;
&lt;p class="Body1" align="left"&gt;&amp;nbsp;If you are interested in viewing the event history of the WSUS server, it can be reached by calling the &lt;strong&gt;GetUpdateEventHistory(StartDate,EndDate)&lt;/strong&gt;&lt;strong&gt; &lt;/strong&gt;method and supplying a Start Date and an End Date. In this case, I just want to look at the events that have occurred during the past hour.&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;$wsus.GetUpdateEventHistory(&amp;quot;$((Get-Date).AddHours(-1))&amp;quot;,&amp;quot;$(Get-Date)&amp;quot;)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;HasAssociatedUpdate&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Administration.UpdateRevisionId&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;HasAssociatedComputer : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ComputerId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Status&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Unknown&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;WsusEventId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : ContentSynchronizationSucceeded&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;WsusEventSource&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Server&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : f01cb84f-9a0b-4da8-a12a-39a6866c5787&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;CreationDate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 9/23/2012 7:08:20 PM&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Message&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Content synchronization succeeded.&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;IsError&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ErrorCode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Row&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: Microsoft.UpdateServices.Internal.DatabaseAccess.EventHistoryTableRow&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;HasAssociatedUpdate&amp;nbsp;&amp;nbsp; : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Administration.UpdateRevisionId&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;HasAssociatedComputer : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ComputerId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Status&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Unknown&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;WsusEventId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : ContentSynchronizationFileDownloadSucceeded&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;WsusEventSource&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Server&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0c7ade08-87d6-4019-b676-0f50ce486591&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;CreationDate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 9/23/2012 7:08:20 PM&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Message&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Content file download succeeded. Digest:&amp;nbsp; Source File: /msdownload/update/v3-19990518/cabpool/w&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; indowsinstaller-kb893803-v2-x86_830994754ba721add8a13bd0266d2e092f21cab0.exe Destination File:&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; F:\WsusContent\B0\830994754BA721ADD8A13BD0266D2E092F21CAB0.exe.&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;IsError&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ErrorCode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Row&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.DatabaseAccess.EventHistoryTableRow&lt;/p&gt;
&lt;p class="Code"&gt;With this information, you could audit for any possible failures that have occurred with a recent synchronization or some other issue that might be cause for a WSUS issue.&lt;/p&gt;
&lt;h2 class="Head2"&gt;Automatic Approval Rules&lt;/h2&gt;
&lt;p class="Body1" align="left"&gt;With WSUS, you can automate your patch approvals simply by creating and configuring Automatic Approval Rules. You can specify categories, target groups among other things to use for the rules.&lt;/p&gt;
&lt;h3 class="Head2"&gt;Locating approval rules&lt;/h3&gt;
&lt;p class="Body1" align="left"&gt;To find out what approval rules are currently on the WSUS server, use the &lt;strong&gt;GetApprovalRules()&lt;/strong&gt; method from the Microsoft.UpdateServices.Internal.BaseApi.UpdateServer object created from the initial connection.&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;$wsus.GetInstallApprovalRules()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;UpdateServer&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Default Automatic Approval Rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Enabled&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Action&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Install&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Deadline&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;CanSetDeadline : True&lt;/p&gt;
&lt;p class="Code"&gt;This is not actually all of the information for the approval rules. To find out what Target Groups, Classifications, and Categories are contained in the Microsoft.UpdateServices.Internal.BaseApi.AutomaticUpdateApprovalRule object, you need to use the &lt;strong&gt;GetComputerTargetGroups()&lt;/strong&gt;, &lt;strong&gt;GetUpdateClassifications()&lt;/strong&gt;, and &lt;strong&gt;GetUpdateCategories()&lt;/strong&gt; methods, respectively.&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;$approvalRules = $wsus.GetInstallApprovalRules()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Get the Update Classifications&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$wsus.GetInstallApprovalRules()[0].GetUpdateClassifications()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateSer&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ver&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: e6cf1350-c01b-414d-a61f-263d14d133b4&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Title&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Critical Updates&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Description&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : A broadly released fix for a specific problem&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; addressing a critical, non-security related bug.&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ReleaseNotes&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DefaultPropertiesLanguage :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DisplayOrder&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2147483647&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ArrivalDate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 9/23/2012 6:51:37 PM&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateSer&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ver&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: 0fa1201d-4330-4fa8-8ae9-b877473b6441&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Title&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Security Updates&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Description&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : A broadly released fix for a product-specific&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; security-related vulnerability. Security&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vulnerabilities are rated based on their severity&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; which is indicated in the Microsoft&amp;reg; security&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bulletin as critical, important, moderate, or low.&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ReleaseNotes&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DefaultPropertiesLanguage :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DisplayOrder&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2147483647&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ArrivalDate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 9/23/2012 6:40:34 PM&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Get the Computer Target Groups&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$wsus.GetInstallApprovalRules()[0].GetComputerTargetGroups()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp; --&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Microsoft.UpdateService... a0a08746-4dbe-4a37-9adf... All Computers&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Get the Categories&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$wsus.GetInstallApprovalRules()[0].GetCategories()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Type&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Product&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ProhibitsSubcategories&amp;nbsp;&amp;nbsp;&amp;nbsp; : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ProhibitsUpdates&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateSource&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : MicrosoftUpdate&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateSer&lt;/p&gt;
&lt;p class="Code" 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ver&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : a105a108-7c9b-4518-bbbe-73f0fe30012b&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Title&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Windows Server 2012&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Description&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Windows Server 2012&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ReleaseNotes&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DefaultPropertiesLanguage :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;DisplayOrder&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2147483647&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;ArrivalDate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 9/23/2012 6:47:20 PM&lt;/p&gt;
&lt;h3 class="Head2"&gt;Creating approval rules&lt;/h3&gt;
&lt;p class="Body1" align="left"&gt;Creating an approval is a simple process that involves first creating the approval object with a name and then filling in the blanks for the rest of the configuration (Target Groups, Categories, Classifications, and so on) on the object before deploying it on the server. First, verify that the rule I am going to create (named &amp;ldquo;2012Servers&amp;rdquo;) doesn&amp;rsquo;t exist:&lt;/p&gt;
&lt;p class="Body" style="padding-left:30px;" align="left"&gt;#Look at current rules&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$wsus.GetInstallApprovalRules()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Default Automatic Approval Rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Enabled&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Action&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Install&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Deadline&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;CanSetDeadline : True&lt;/p&gt;
&lt;p class="Code"&gt;No Rules exist with the name I plan to use, so I can continue with the creation of the new Approval Rule.&lt;/p&gt;
&lt;h4 class="Head2"&gt;Listing 1: Creating an Approval Rule&lt;/h4&gt;
&lt;p class="Body1" style="padding-left:30px;"&gt;&amp;nbsp;[cmdletbinding()]&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Param (&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; [parameter(ValueFromPipeline=$True,Mandatory=$True,&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; HelpMessage=&amp;quot;Name of WSUS server to connect to.&amp;quot;)]&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; [Alias(&amp;#39;WSUSServer&amp;#39;)]&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; [string]$Computername,&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; [parameter()]&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; [Switch]$UseSSL&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;[reflection.assembly]::LoadWithPartialName(&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; &amp;quot;Microsoft.UpdateServices.Administration&amp;quot;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;) | out-null&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; $Computername,$UseSSL,$Port&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Create New Rule Object&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$newRule = $wsus.CreateInstallApprovalRule(&amp;quot;2012Servers&amp;quot;)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;##Categories&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Get Categories for Windows Server&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$updateCategories = $wsus.GetUpdateCategories() | Where {&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; $_.Title -LIKE &amp;quot;Windows Server 2012*&amp;quot;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Create collection for Categories&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$categoryCollection = New-Object Microsoft.UpdateServices.Administration.UpdateCategoryCollection&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$categoryCollection.AddRange($updateCategories)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Add the Categories to the Rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$newRule.SetCategories($categoryCollection)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;##Classifications&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Get all Classifications for specific Classifications&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$updateClassifications = $wsus.GetUpdateClassifications() | Where {&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; $_.Title -Match &amp;quot;Critical Updates|Service Packs|Updates|Security Updates&amp;quot;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Create collection for Categories&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$classificationCollection = New-Object Microsoft.UpdateServices.Administration.UpdateClassificationCollection&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$classificationCollection.AddRange($updateClassifications )&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Add the Classifications to the Rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$newRule.SetUpdateClassifications($classificationCollection)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;##Target Groups&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Get Target Groups required for Rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$targetGroups = $wsus.GetComputerTargetGroups() | Where {&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp; $_.Name -Match &amp;quot;All Computers&amp;quot;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Create collection for TargetGroups&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$targetgroupCollection = New-Object Microsoft.UpdateServices.Administration.ComputerTargetGroupCollection&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$targetgroupCollection.AddRange($targetGroups)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Add the Target Groups to the Rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$newRule.SetComputerTargetGroups($targetgroupCollection)&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Finalize the creation of the rule object&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$newRule.Enabled = $True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$newRule.Save()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;#Run the rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$newRule.ApplyRule()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Body1" style="padding-left:30px;" align="left"&gt;Let&amp;rsquo;s make sure that the rule is now created.&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;$wsus.GetInstallApprovalRules()&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Default Automatic Approval Rule&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Enabled&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Action&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Install&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Deadline&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;CanSetDeadline : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;UpdateServer&amp;nbsp;&amp;nbsp; : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 6&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2012Servers&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Enabled&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : True&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Action&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Install&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;Deadline&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p class="Code" style="padding-left:30px;"&gt;CanSetDeadline : True&lt;/p&gt;
&lt;p class="Body1" align="left"&gt;Now we have a new Approval Rule that will run to approve only the updates I specified to only Windows Server 2012 systems. Keep in mind that the automatic approval rules only run after WSUS synchronizes, and only synched updates will be eligible for the rule unless you run the rule manually.&lt;/p&gt;
&lt;p class="Body1" align="left"&gt;In today&amp;rsquo;s blog, I showed a number of things that you can do with Windows PowerShell to manage your WSUS server by using the available APIs, such as looking at the configuration settings of the WSUS server and auditing events. Auditing and building Automatic Approval Rules and providing more detailed reporting is easily accomplished by using the APIs.&lt;/p&gt;
&lt;p class="Body" align="left"&gt;With Windows Server 2012, you do have the option of using the Update Services module to perform some basic WSUS administration such as patch approvals, but for more advanced configurations and reporting, the APIs are definitely the way to go.&lt;/p&gt;
&lt;p class="Body" align="left"&gt;There is also a module that I wrote called &lt;a href="http://poshwsus.codeplex.com/" target="_blank"&gt;PoshWSUS&lt;/a&gt; that provides cmdlets that allow for a more advanced administration. With multiple options for automating your WSUS server, you can&amp;rsquo;t go wrong. If you write some scripts for your own WSUS server, I hope that you will share those with the rest of the community.&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here is the code for the discount offer today at&lt;/strong&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;a href="http://www.manning.com/" target="_blank"&gt;www.manning.com&lt;/a&gt;:&amp;nbsp;&lt;strong&gt;scriptw2&lt;/strong&gt;&lt;br /&gt; Valid for 50% off &lt;a href="http://www.manning.com/hicks/" target="_blank"&gt;PowerShell Deep Dives&lt;/a&gt; and &lt;a href="http://www.manning.com/nielsen/" target="_blank"&gt;SQL Server Deep MVP Dives&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Offer valid from April 2, 2013 12:01 AM until April 3 midnight (EST)&lt;/p&gt;
&lt;p&gt;I invite you to follow me on&amp;nbsp;&lt;a href="http://bit.ly/scriptingguystwitter" target="_blank"&gt;Twitter&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="http://bit.ly/scriptingguysfacebook" target="_blank"&gt;Facebook&lt;/a&gt;. If you have any questions, send email to me at&amp;nbsp;&lt;a href="mailto:scripter@microsoft.com" target="_blank"&gt;scripter@microsoft.com&lt;/a&gt;, or post your questions on the&amp;nbsp;&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;strong&gt;Ed Wilson, Microsoft Scripting Guy&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3561978" width="1" height="1" alt="" /&gt;</description></item><item><title>Expert Commentary: 2012 Scripting Games Advanced Event 2</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/04/17/expert-commentary-2012-scripting-games-advanced-event-2.aspx</link><pubDate>Tue, 17 Apr 2012 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:15994</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Microsoft community contributor, Boe Prox, provides expert commentary for 2012 Scripting Games Advanced Event 2.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Boe Prox is the expert commentator for Advanced Event 2.&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/7485.hsg_2D00_4_2D00_17_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/7485.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_1.jpg" alt="Photo of Boe Prox" title="Photo of Boe Prox" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Boe is currently a senior systems administrator with BAE Systems. He has been in the IT industry since 2003, and he has been working with&amp;nbsp;&lt;a href="http://technet.microsoft.com/en-us/scriptcenter/powershell.aspx" target="_blank"&gt;Windows PowerShell&lt;/a&gt;&amp;nbsp;since 2009. Boe looks to script whatever he can, whenever he can. He is also a moderator on the&amp;nbsp;&lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Official Scripting Guys Forum&lt;/a&gt;. Check out his current projects published on CodePlex:&amp;nbsp;&lt;a href="http://poshwsus.codeplex.com/" target="_blank"&gt;PoshWSUS&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="http://poshpaig.codeplex.com/" target="_blank"&gt;PoshPAIG&lt;/a&gt;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Blog:&amp;nbsp;&lt;a href="http://learn-powershell.net/" target="_blank"&gt;Learn PowerShell | Achieve More&lt;br /&gt; &lt;/a&gt;&lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/guest+blogger/boe+prox/" target="_blank"&gt;Guest posts on Hey, Scripting Guy! Blog&lt;br /&gt; &lt;/a&gt;Twitter:&amp;nbsp;&lt;a href="http://twitter.com/proxb" target="_blank"&gt;@proxb&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is an event that relates very nicely to something that would be done in the &amp;ldquo;real world.&amp;rdquo; Tracking your services on each server is something that should be done daily to ensure that everything is working normally and to make sure that there are no anomalies occurring.&lt;/p&gt;
&lt;p&gt;This event requires us to perform a query against local and/or remote servers to pull back all of the services and write out the data to a CSV file. This is definitely a job for Windows PowerShell!&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;Requirements&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;This event is not without requirements to give you more of a challenge, so let&amp;rsquo;s take a look at the key requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need to present your findings in a spreadsheet that includes the following information: the server name, the service name, the start mode of the service, the user account used to start the service, and the current status of the service.&lt;/li&gt;
&lt;li&gt;You should use the easiest method possible to display the information in a spreadsheet.&lt;/li&gt;
&lt;li&gt;You must include the ability to run the script on a local computer and on a remote computer.&lt;/li&gt;
&lt;li&gt;You must include the ability to run the script with alternate credentials when operating against a remote computer, and you should impersonate the logged on user when running locally.&lt;/li&gt;
&lt;li&gt;You do not need to add comment-based Help for this scenario, but additional points are awarded if you do include appropriate comment-based Help such as the description, examples, and parameters.&lt;/li&gt;
&lt;li&gt;If the script requires admin rights to run, you should check to ensure that the script is running with admin rights. If those rights are not present, you should display an appropriate message and exit.&lt;/li&gt;
&lt;li&gt;For the purposes of this exercise, do not write a module. You should make your script completely standalone and have no external dependencies. Therefore, everything needed should be put in this script. Failure to do so will cost you points.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that we know what is required for this script, we can begin to dive into the code and see what is going on. I will take the code apart in chunks to explain what I am doing and point out the areas that meet each requirement in addition to other areas that I feel are worth mentioning. I included some extra features for this script, and I will explain my reasoning behind this when I get to them.&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;The code&lt;/b&gt;&lt;/h3&gt;
&lt;p style="padding-left:30px;"&gt;Function Get-ServiceData {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;#&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .SYNOPSIS&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; Command used to find all services with option to write to a CSV File&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; .DESCRIPTION&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; Command used to find all services with option to write to a CSV File&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; .PARAMETER Computername&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; A single or collection of systems to perform the query against&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; .PARAMETER Credential&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; Alternate credentials to use for query of services&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; .PARAMETER ToCSV&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; Name of CSV to write the results of the query to&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; .PARAMETER Throttle&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; Number of asynchronous jobs that will run at a time&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;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .PARAMETER ShowProgress&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; Displays the progress of the services query&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; .NOTES&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; Author: Boe Prox&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; Created: 14March2012&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; .EXAMPLE&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;Get-ServiceData&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;&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; Description&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; -----------&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; Retrieves all services from the local 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;&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; .EXAMPLE&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; $Servers = &amp;#39;Server1&amp;#39;,&amp;#39;Server2&amp;#39;,&amp;#39;Server3&amp;#39;&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; Get-ServiceData -Computername $Servers -ShowProgress&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;&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; Description&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; -----------&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; Retrieves all services from the remote servers and displays a progress bar&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;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .EXAMPLE&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; $Servers = Get-Content Servers.txt&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; $Servers | Get-ServiceData -ShowProgress -Throttle 10&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;&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; Description&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; -----------&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; Retrieves all services from the remote servers while running 10 runspace jobs at a time&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 displays a progress bar to show the status of each runspace job.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .EXAMPLE&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; $Servers = Get-Content Servers.txt&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; $Servers | Get-ServiceData -Credential (Get-Credential) -ToCSV (Join-Path $pwd report.csv)&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;&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; Description&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; -----------&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; Retrieves all services for each system in the Servers.txt file while using the supplied&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; alternate credentials and outputs the data to a CSV file.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Requires -Version 2.0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [cmdletbinding(&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DefaultParameterSetName = &amp;#39;NonCSV&amp;#39;&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; Param (&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [parameter(ValueFromPipeline = $True,ValueFromPipeLineByPropertyName = $True)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Alias(&amp;#39;CN&amp;#39;,&amp;#39;__Server&amp;#39;)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [string[]]$Computername = $Env:Computername,&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; [parameter()]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [System.Management.Automation.PSCredential]$Credential,&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; [parameter(ParameterSetName = &amp;#39;CSV&amp;#39;)]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ValidateNotNullOrEmpty()]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [String]$ToCSV,&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; [parameter()]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [int]$Throttle = 5,&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; [parameter()]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [switch]$ShowProgress&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/p&gt;
&lt;p&gt;If you are going to create an advanced function, you definitely have to have inline Help within that function. This does not mean that you write your own Help function and offer that. It means that you use the Help in Windows PowerShell to accomplish this task. I included examples about how to use this function so others can reference it when trying to run the command.&lt;/p&gt;
&lt;p&gt;Also included is &lt;b&gt;[cmdletbinding()]&lt;/b&gt;,&lt;b&gt; &lt;/b&gt;which makes this advanced function advanced by adding extra parameters such as &lt;i&gt;&amp;ndash;Verbose&lt;/i&gt; and &lt;i&gt;&amp;ndash;WhatIf&lt;/i&gt;. I also make sure that I add a default parameter value for my &lt;i&gt;ComputerName&lt;/i&gt; parameter to point to the local machine if nothing is given. Also, if no file name is given with &lt;b&gt;ToCSV&lt;/b&gt;, it will throw an error until a file name is specified.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Begin {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Function that will be used to process runspace jobs&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function Get-RunspaceData {&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; [cmdletbinding()]&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; param(&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [switch]$Wait,&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [switch]$ShowProgress&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; )&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; Do {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $more = $false&amp;nbsp;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Foreach($runspace in $runspaces) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If ($runspace.Runspace.isCompleted) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Script:Report += $runspace.powershell.EndInvoke($runspace.Runspace) |&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Select SystemName,Name,State,StartMode,StartName&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $runspace.powershell.dispose()&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$runspace.Runspace = $null&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $runspace.powershell = $null&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Script:i++&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If ($PSBoundParameters[&amp;#39;ShowProgress&amp;#39;]) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Progress -Activity &amp;#39;Services Query&amp;#39; -Status (&amp;quot;Processing Runspace: {0}&amp;quot; -f $runspace.computer) `&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -PercentComplete (($i/$totalcount)*100)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } ElseIf ($runspace.Runspace -ne $null) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $more = $true&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;&amp;nbsp;&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;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If ($more -AND $PSBoundParameters[&amp;#39;Wait&amp;#39;]) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Start-Sleep -Milliseconds 100&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;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Clean out unused runspace jobs&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $temphash = $runspaces.clone()&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $temphash | Where {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_.runspace -eq $Null&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } | ForEach {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Verbose (&amp;quot;Removing {0}&amp;quot; -f $_.computer)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Runspaces.remove($_)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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; } while ($more -AND $PSBoundParameters[&amp;#39;Wait&amp;#39;])&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;&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;Performing inital Administrator check&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; $usercontext = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $IsAdmin = $usercontext.IsInRole([Security.Principal.WindowsBuiltInRole] &amp;quot;Administrator&amp;quot;)&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;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Counter for Write-Progress&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Script:i = 0&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;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Main collection to hold all data returned from runspace jobs&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Script:report = @()&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;&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;Building hash table for WMI parameters&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; $wmihash = @{&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; Query = &amp;quot;SELECT SystemName,Name,StartMode,State,Startname FROM Win32_Service&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ErrorAction = &amp;quot;Stop&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; }&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; #Supplied Alternate Credentials?&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 ($PSBoundParameters[&amp;#39;Credential&amp;#39;]) {&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; $wmihash.credential = $Credential&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;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Define hash table for Get-RunspaceData function&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $runspacehash = @{}&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 ($PSBoundParameters[&amp;#39;ShowProgress&amp;#39;]) {&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; $runspacehash.ShowProgress = $True&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; #Define Scriptblock for runspaces&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $scriptblock = {&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; Param (&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; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$Computer,&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $wmihash&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; )&amp;nbsp;&amp;nbsp;&amp;nbsp;&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; Write-Verbose (&amp;quot;{0}: Checking network connection&amp;quot; -f $Computer)&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; If (Test-Connection -ComputerName $Computer -Count 1 -Quiet) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Check if running against local system and perform necessary actions&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Verbose (&amp;quot;Checking for local system&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If ($Computer -eq $Env:Computername) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $wmihash.remove(&amp;#39;Credential&amp;#39;)&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;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $wmihash.Computername = $Computer&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;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Try {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get-WmiObject @wmihash&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } Catch {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Warning (&amp;quot;{0}: {1}&amp;quot; -f $Computer,$_.Exception.Message)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Break&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;&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; } 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Warning (&amp;quot;{0}: Unavailable!&amp;quot; -f $Computer)&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Break&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; }&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; }&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; Write-Verbose (&amp;quot;Creating runspace pool and session states&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; $sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $runspacepool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $runspacepool.Open()&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;&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;Creating empty collection to hold runspace jobs&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; $Script:runspaces = New-Object System.Collections.ArrayList&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $totalcount = $computername.count&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;The Begin block is pretty meaty but it sets up a lot of the code that will be processed later in the function.&lt;/p&gt;
&lt;p&gt;A few of the requirements are covered here with an initial check for Administrator rights and allowing the code to run on a local or a remote system. A gotcha is also presented here because the use of alternate credentials will not work against a local system.&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/3630.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3630.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_2.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If a local system is included with other remote systems, the alternate credentials are simply removed from the runspace.&lt;/p&gt;
&lt;p&gt;Although I do not have time to dive into everything here, I will say that this is where I set up a script block that handles each client computer, use two hash tables for splatting parameters (one for the &lt;b&gt;Get-WMIObject&lt;/b&gt; cmdlet and another for a function that will be defined later). I also make use of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.management.automation.runspaces.runspacefactory(v=vs.85).aspx"&gt;[runspacefactory]&lt;/a&gt; accelerator that allows me to set up some background runspace jobs and also allows throttling those runspaces, which allows for quicker processing of the queries. I chose this over using the &lt;b&gt;*-Job&lt;/b&gt; cmdlets because there is not an easy way to throttle jobs, and this is more of a lightweight method to run jobs in a background runspace.&lt;/p&gt;
&lt;p&gt;To quickly jump into an example, the following screenshots show the amount of time it took to run this function by using the background runspaces versus using a more synchronous command,&amp;nbsp;&lt;b&gt;ForEach&lt;/b&gt;, against 132 systems.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Get-ServiceData Function&lt;/b&gt;&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/2110.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2110.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Using ForEach&lt;/b&gt;&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/3124.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3124.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_4.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the difference is about 220 seconds. While not a massive amount of time, it is still a nice improvement over the synchronous way using &lt;b&gt;ForEach&lt;/b&gt;. Credit for the throttling technique goes to Windows PowerShell MVP, Dr. Tobias Weltner, for his webcast, &lt;a href="http://www.idera.com/Events/RegisterWC.aspx?EventID=297" target="_blank"&gt;Speeding Up PowerShell: Multithreading&lt;/a&gt;, which explained the use of &lt;b&gt;[runspacefactory]&lt;/b&gt; to provide throttling.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Process {&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; Write-Verbose (&amp;quot;Validating that current user is Administrator or supplied alternate credentials&amp;quot;)&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; If (-Not ($Computername.count -eq 1 -AND $Computername[0] -eq $Env:Computername)) {&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; #Now check that user is either an Administrator or supplied Alternate Credentials&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; If (-Not ($IsAdmin -OR $PSBoundParameters[&amp;#39;Credential&amp;#39;])) {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Warning (&amp;quot;You must be an Administrator to perform this action against remote systems!&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Break&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; }&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; ForEach ($Computer in $Computername) {&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; #Create the powershell instance and supply the scriptblock with the other parameters&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; $powershell = [powershell]::Create().AddScript($ScriptBlock).AddArgument($computer).AddArgument($wmihash)&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;&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; #Add the runspace into the powershell instance&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; $powershell.RunspacePool = $runspacepool&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;&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; #Create a temporary collection for each runspace&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; $temp = &amp;quot;&amp;quot; | Select-Object PowerShell,Runspace,Computer&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; $Temp.Computer = $Computer&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; $temp.PowerShell = $powershell&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;&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; #Save the handle output when calling BeginInvoke() that will be used later to end the runspace&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; $temp.Runspace = $powershell.BeginInvoke()&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; Write-Verbose (&amp;quot;Adding {0} collection&amp;quot; -f $temp.Computer)&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; $runspaces.Add($temp) | Out-Null&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;&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; Write-Verbose (&amp;quot;Checking status of runspace jobs&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get-RunspaceData @runspacehash&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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&gt;The Process block does just that: processes all of the computers and assigns each computer as a background runspace. More requirements are met here, including the finishing check of Administrator rights if running against remote systems. If there is only a local system and it is the only system in the collection, alternate credentials are not required nor are Administrator rights because any local user can perform a query against WMI.&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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; Write-Verbose (&amp;quot;Finish processing the remaining runspace jobs: {0}&amp;quot; -f (@(($runspaces | Where {$_.Runspace -ne $Null}).Count)))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $runspacehash.Wait = $true&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get-RunspaceData @runspacehash&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; Write-Verbose (&amp;quot;Closing the runspace pool&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; $runspacepool.close()&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; If ($PSBoundParameters[&amp;#39;ShowProgress&amp;#39;]) {&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; #Close the Write-Progress bar so it does not affect the displaying of data when completed.&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; Write-Progress -Activity &amp;#39;Services Query&amp;#39; -Status &amp;#39;Completed&amp;#39; -Completed&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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; }&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; If ($PSBoundParameters[&amp;#39;ToCSV&amp;#39;]) {&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; Write-Verbose (&amp;quot;Writing report to CSV: {0}&amp;quot; -f $ToCSV)&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; $Report | Export-Csv -Path $ToCSV -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; } 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Write-Verbose (&amp;quot;Displaying Report&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Output $Report&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;}&lt;/p&gt;
&lt;p&gt;The End block finishes up the remaining runspace jobs, and depending on what the user chose for output (CSV or no CSV), the function will output the data to the console or write all of the data to a specified CSV file (meeting an important requirement). I chose to use &lt;b&gt;Export-CSV&lt;/b&gt; because it meets the requirement for the easiest method possible to create a CSV file. If I was using Windows PowerShell 3.0, I could have thrown this in with the runspace script block and used the &lt;i&gt;&amp;ndash;Append&lt;/i&gt; parameter to further increase the performance of this function instead of holding all of the data until the end and writing out to the CSV file.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s give it a quick run to see it in action and view the final output.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Servers = Get-Content .\servers.txt&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-ServiceStartMode -Computername $servers -ShowProgress -ToCSV &amp;quot;C:\users\boe\desktop\report.csv&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6521.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6521.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_5.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&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/2656.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_5.jpg"&gt;&lt;/a&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1346.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_6.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1346.hsg_2D00_4_2D00_17_2D00_12_2D00_adv_2D00_6.jpg" border="0" alt="" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see, all of the data that was required is on the spreadsheet to view.&lt;/p&gt;
&lt;p&gt;The script is available to download from the &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/Get-ServiceData-Advanced-84d85d7a" target="_blank"&gt;Script Center Repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;2012 Scripting Games Guest Commentator Week will continue tomorrow when we will present the scenario for Event 3.&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;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3491585" width="1" height="1" alt="" /&gt;</description></item><item><title>Tips for Preparing for the 2012 PowerShell Scripting Games</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/03/30/tips-for-preparing-for-the-2012-powershell-scripting-games.aspx</link><pubDate>Fri, 30 Mar 2012 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:15691</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Guest commentator, Boe Prox, talks about practical tips for preparing for the 2012 Windows PowerShell Scripting Games.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Guest blogger, &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/guest+blogger/boe+prox/"&gt;Boe Prox&lt;/a&gt;, is with us today. He is going to talk to us about preparing for the 2012 Scripting Games. First, a little bit about Boe&amp;hellip;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1362.hsg3_2D00_30_2D00_12_2D00_1.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1362.hsg3_2D00_30_2D00_12_2D00_1.png" alt="Photo of Boe Prox" title="Photo of Boe Prox" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Boe Prox is currently a senior systems administrator with BAE Systems. He has been in the IT industry since 2003, and he has been working with &lt;a href="http://technet.microsoft.com/en-us/scriptcenter/powershell.aspx" target="_blank"&gt;Windows PowerShell&lt;/a&gt; since 2009. Boe looks to script whatever he can, whenever he can. He is also a moderator on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Hey, Scripting Guy! Forum&lt;/a&gt;. Check out his current projects published on CodePlex: &lt;a href="http://poshwsus.codeplex.com/" target="_blank"&gt;PoshWSUS&lt;/a&gt; and &lt;a href="http://poshpaig.codeplex.com/" target="_blank"&gt;PoshPAIG&lt;/a&gt;.&lt;br /&gt; Boe&amp;rsquo;s blog: &lt;a href="http://learn-powershell.net/" target="_blank"&gt;Learn PowerShell | Achieve More&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Take it away Boe&amp;hellip;&lt;/p&gt;
&lt;p&gt;With the Scripting Games coming up on April 2, you might be asking yourself, &amp;ldquo;What do I need to do to be prepared for these games?&amp;rdquo; You are in luck because I am going to show some things that will help you in your quest for scripting glory!&lt;/p&gt;
&lt;p&gt;These tips are in no particular order of importance, and they cover a wide variety of items that should be used to increase the readability of your code and to ease any issues that the people who are using your scripts may run into. So without further ado, let&amp;rsquo;s get started!&lt;/p&gt;
&lt;h2&gt;Variables that make sense&lt;/h2&gt;
&lt;p&gt;When you are deciding what you want to call the variables that are used in your code, keep in mind that others will be reading your code, whether it is in the Scripting Games or at your place of work. Or you might have to debug or add something to your code several months later, so using something like this for your code will only make the effort to read the code more difficult.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$strServers = &amp;#39;server1&amp;#39;,&amp;#39;server2&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$d = Get-Date&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ForEach ($C in $strServers) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; $objp = Get-WmiObject -computer $c Win32_Process&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;There are a couple of things here that can stand to be changed. First off, the &lt;b&gt;$strservers&lt;/b&gt; that is using Hungarian notation is not needed. Although it is often used in VBScript script, it isn&amp;rsquo;t needed in Windows PowerShell script. Using something that lets you know what the variable is holding&amp;mdash;in this case, &lt;b&gt;servers&lt;/b&gt;&amp;mdash;is suitable, rather than knowing the type of the variable.&lt;/p&gt;
&lt;p&gt;Although, I would rather use &lt;i&gt;ComputerName&lt;/i&gt; because that is a common parameter in Windows PowerShell cmdlets. &lt;b&gt;$d&lt;/b&gt;, &lt;b&gt;$objp&lt;/b&gt;, and &lt;b&gt;$c&lt;/b&gt; are the remaining the variables that fail to make it easy to know what is being used for each variable. Given, this is a small snippet of code, but imagine if you are working with 100+ lines of code. It would be more difficult to back track and find out what each variable is. Something like this would be much easier to read and understand.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Computername = &amp;#39;server1&amp;#39;,&amp;#39;server2&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$date = Get-Date&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ForEach ($computer in $Computername) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; $processes = Get-WmiObject -computer $computer Win32_Process&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;h2&gt;&lt;b&gt;Error handling&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;If you are writing functions or scripts (or whatever), you need to be using some sort of error handling in your code. This will prevent unwanted errors from popping up and preventing your code from working. Now, I don&amp;rsquo;t mean to add $ErrorActionPreference = &amp;lsquo;SilentlyContinue&amp;rsquo; at the top of your code and let it fly. If you are using that to solve your error handling, you are only fooling yourself. In other words, remove it immediately! It&amp;rsquo;s OK, I&amp;rsquo;ll wait.&lt;/p&gt;
&lt;p&gt;What you should be doing is investing in using &lt;b&gt;Try&lt;/b&gt;/&lt;b&gt;Catch&lt;/b&gt; in your code to handle any potential errors that might pop up. All cmdlets have the &lt;i&gt;ErrorAction&lt;/i&gt; parameter, and you can choose to use &lt;b&gt;Stop&lt;/b&gt;. Or if you really don&amp;rsquo;t want to catch any errors (or even know about errors), you can use &lt;b&gt;SilentlyContinue&lt;/b&gt;. The benefit of using this parameter is that it will only affect that command, not the all of the commands in the code. The following example of using this method will catch an error if something goes wrong.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ForEach ($Computer in $Computername) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; If (Test-Connection -ComputerName $Computer -Count 1 -Quiet) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Try {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get-WmiObject -Computer $Computer -Class Win32_Process -ErrorAction Stop&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } Catch {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Warning (&amp;quot;{0}: {1}&amp;quot; -f $Computer,$_.Exception.Message)&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; } Else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Warning (&amp;quot;{0}: Unavailable&amp;quot; -f $Computer)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;A couple of other types of error handling use specific cmdlets to test for. &lt;b&gt;Test-Connection&lt;/b&gt; checks if a system is online before making a connection for a query or some other operation. &lt;b&gt;Test-Path&lt;/b&gt; checks to see if a folder or file exists.&lt;/p&gt;
&lt;p&gt;Also, checking for Administrator rights is a useful thing to do within your code, especially when working with remote systems or accessing parts of a system that are otherwise off limits to a regular user account. It also helps if you have UAC enabled and are not running the script &amp;ldquo;as an Administrator.&amp;rdquo; I wrote a guest blog last year&amp;nbsp;that talked about this: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/11/check-for-admin-credentials-in-a-powershell-script.aspx" target="_blank"&gt;Check for Admin Credentials in a PowerShell Script&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Code formatting&lt;/h2&gt;
&lt;p&gt;Making your code readable can be just as important as making your code work properly to perform the action that you want it to do. Having code that is not readable makes it difficult to debug when something goes wrong. In addition, others trying to read the code may end up spending more time putting it into a proper format than actually debugging it or modifying it for their own environment. Things to consider when writing your code are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use spacing between areas of code to separate blocks of code.&lt;/li&gt;
&lt;li&gt;Use natural line breaks: &amp;ldquo;|&amp;rdquo;,&amp;rdquo;{&amp;ldquo;.&lt;/li&gt;
&lt;li&gt;Indent your code in areas where groups of code are being used logically, such as after an opening bracket &amp;ldquo;{&amp;ldquo; or after a pipeline character is used. This ensures that all the lines of code within the construct are easy to identify and work with.&lt;/li&gt;
&lt;li&gt;Use splatting for parameters where it threatens to force the use of a back tick (&amp;ldquo;`&amp;rdquo;) to enable a line break to continue the code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Following is an example of poorly formatted code:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1411.5.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1411.5.png" alt="Image of code" title="Image of code" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is a lot wrong with this code, ranging from no spacing, to indenting blocks of code where it is incased in a {} construct, to cmdlets using enough parameters to warrant a line break to keep everything from going off of the screen. Also, there are areas in the code that really aren&amp;rsquo;t needed, such as saving the result of the &lt;b&gt;Test-Connection&lt;/b&gt; cmdlet and then comparing the return when it is a Boolean value in the If statement.&lt;/p&gt;
&lt;p&gt;This is what it should look like:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7206.6.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7206.6.png" alt="Image of code" title="Image of code" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What you have now is something that is not only easier to read, but also takes advantage of other techniques, such as splatting the parameters for &lt;b&gt;Get-WmiObject&lt;/b&gt; and taking advantage of the Boolean return value for using the &lt;i&gt;Quiet&lt;/i&gt; parameter in &lt;b&gt;Test-Connection&lt;/b&gt; for the If statement. Instead of using something like @{L=&amp;#39;Computer&amp;#39;;E={$_.__Server}},@{L=&amp;#39;TimeGenerated&amp;#39;;E={Get-Date}}} to add a couple extra properties to the output that is difficult to read, I used a &lt;b&gt;ForEach&lt;/b&gt; loop and created my own object to make it easier to read. This really starts to show its usefulness when you are trying to add multiple properties to the output that are not available any other way.&lt;/p&gt;
&lt;p&gt;There are more lines of code being used here. But trust me, it is worth it to have more readable code than taking shortcuts by cramming it all together.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Comment-based Help&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Something that I saw last year (especially in the first few events), and I sometimes still see, are people writing their own Help in their code. Although it is great to see that some sort of Help is being added into their code so other people know what is going on with it, there is no reason to be doing this. The Windows PowerShell team has put together an amazing thing called comment-based Help that does practically all of the work for you. It has some great features such as displaying examples, viewing the full Help of the command, and looking at the details of a particular parameter. It is so simple that you can practically do it in your sleep! See this example:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7115.7.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7115.7.png" alt="Image of code" title="Image of code" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Everything within &amp;ldquo;&amp;lt;#&amp;rdquo; and &amp;ldquo; #&amp;gt;&amp;rdquo; that uses the appropriate keywords will be read by Windows PowerShell and used to format the Help correctly so it shows something similar to the following:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Help Get-StoppedService&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4571.hsg_2D00_3_2D00_30_2D00_12_2D00_2.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4571.hsg_2D00_3_2D00_30_2D00_12_2D00_2.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Everything that can help a person figure out what to do with this code is here. Want to know the specifics about the &lt;b&gt;ComputerName&lt;/b&gt; property? Simple! Just do this:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Help Get-StoppedService &amp;ndash;Parameter Computername&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1273.hsg_2D00_3_2D00_30_2D00_12_2D00_3.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1273.hsg_2D00_3_2D00_30_2D00_12_2D00_3.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;How cool is that? This is much better than only getting one option when writing your own Help&amp;mdash;which is typically to display everything at once. Need an example? Just do this:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Help Get-StoppedService -Example&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2821.hsg_2D00_3_2D00_30_2D00_12_2D00_4.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2821.hsg_2D00_3_2D00_30_2D00_12_2D00_4.png" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Remember, comment-based Help is your friend, and it should be used instead of writing your own Help. For more information about comment-based Help, run the following command:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-Help about_Comment_Based_Help&lt;/p&gt;
&lt;h2&gt;Other things to consider&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t have the time to dive into detail about these other items, but they are by no means any less important to think about and use while writing your code. It is just that I only have a limited amount of time and space to pick and choose which items to talk about.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use output objects instead of text, and make it pipeline friendly.&lt;/li&gt;
&lt;li&gt;Do not use aliases for anything (this includes cmdlets and parameters).&lt;/li&gt;
&lt;li&gt;Use properly named functions (Verb-Singular noun).&lt;/li&gt;
&lt;li&gt;Use &lt;b&gt;Get-Verb&lt;/b&gt; to see approved verbs.&lt;/li&gt;
&lt;li&gt;Keep inline comments to a minimum (consider using &lt;b&gt;Write-Verbose&lt;/b&gt; instead).&lt;/li&gt;
&lt;li&gt;Use [cmdletbinding()] and Param() in advanced functions; This allows the use of common parameters such as &lt;i&gt;Verbose&lt;/i&gt;, &lt;i&gt;Debug&lt;/i&gt;, &lt;i&gt;WhatIf&lt;/i&gt;, and &lt;i&gt;ErrorAction&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;Consider using &lt;b&gt;Write-Progress&lt;/b&gt; for long running tasks where you are looping through a collection; this allows the user to know where the script is and does not assume it has locked up.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Keep in mind that during the Scripting Games you may not always get the score that you were hoping for. But don&amp;rsquo;t let that get you down! Keep writing code and submitting your scripts, learn from what the judges say, and look at the scripts your fellow scripters have submitted. You will improve on your current skills and continue to put together great scripts!&lt;/p&gt;
&lt;p&gt;To quote myself from last year on twitter during the 2011 Scripting Games: &amp;ldquo;Remember that as long as you did your best on your script and are happy with what you did, then grading should be secondary.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Good luck to all of the scripters this year!&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;Thank you Boe. This is a great summary of things to keep in mind for the 2012 Scripting Games. Join us tomorrow for more Scripting Games prep week.&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=3488689" width="1" height="1" alt="" /&gt;</description></item><item><title>Use PowerShell to Automate SCOM Agent Installations</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/02/13/use-powershell-to-automate-scom-agent-installations.aspx</link><pubDate>Mon, 13 Feb 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14595</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Guest blogger, Boe Prox, shows how to use Windows PowerShell to automate SCOM agent installations.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Last month, guest blogger, Boe Prox, wrote a &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/tags/windows+powershell/boe+prox/wsus/" target="_blank"&gt;series of blogs about WSUS&lt;/a&gt;. Today he is back to talk about SCOM.&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/6180.hsg_2D00_2_2D00_13_2D00_12_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/6180.hsg_2D00_2_2D00_13_2D00_12_2D00_1.jpg" alt="Photo of Boe Prox" title="Photo of Boe Prox" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Boe Prox is currently a senior systems administrator with BAE Systems. He has been in the IT industry since 2003, and he has been working with &lt;a href="http://technet.microsoft.com/en-us/scriptcenter/powershell.aspx" target="_blank"&gt;Windows PowerShell&lt;/a&gt; since 2009. Boe looks to script whatever he can, whenever he can. He is also a moderator on the &lt;a href="http://bit.ly/scriptingforum" target="_blank"&gt;Hey, Scripting Guy! Forum&lt;/a&gt;. Check out his current projects published on CodePlex: &lt;a href="http://poshwsus.codeplex.com/" target="_blank"&gt;PoshWSUS&lt;/a&gt; and &lt;a href="http://poshpaig.codeplex.com/" target="_blank"&gt;PoshPAIG&lt;/a&gt;.&lt;br /&gt; &lt;strong&gt;Boe&amp;rsquo;s blog&lt;/strong&gt;: &lt;a href="http://learn-powershell.net/" target="_blank"&gt;Learn PowerShell | Achieve More&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s Boe&amp;hellip;&lt;/p&gt;
&lt;p&gt;Recently, I was asked to write a script to run against our new SCOM servers that would automate the SCOM agent installation for servers that are being joined to the domain and provide a report on those that successfully installed and also for those that failed to install. This way our SCOM administrators have a report of new systems that are managed by the agents, and they will also have a way to troubleshoot and, if required, manually install the agents on the systems that report failures.&lt;/p&gt;
&lt;p&gt;Although I was not completely familiar with SCOM like the SCOM admins are, I do know my way around Windows PowerShell, and I was able to put something together that would meet all of the requirements. So without further ado, let us dive into the script that I wrote, which is also available on the Script Repository: &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/SCOM-Agent-Installation-8c237afehttp:/gallery.technet.microsoft.com/scriptcenter/SCOM-Agent-Installation-8c237afe" target="_blank"&gt;SCOM Agent Installation and Reporting Script&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Requirements for script&lt;/h3&gt;
&lt;p&gt;Our goal for this script is to query Active Directory for all servers, query SCOM for all currently monitored servers on the network, and then filter out all of the systems that are in Active Directory so we only have unmanaged servers to work with. We can then attempt to discover those servers (a requirement before we can push an agent installation), filter out failed discoveries so only the successes remain, and finally attempt the installation of the agent on the rest of the servers. Lastly, we need to generate a report that lists&lt;b&gt; Successful Installations&lt;/b&gt;, &lt;b&gt;Failed Installations&lt;/b&gt;, and &lt;b&gt;Failed Discoveries&lt;/b&gt;, and email it to the system administrators. Simple enough with Windows PowerShell!&lt;/p&gt;
&lt;p&gt;For this script to run properly and do what we need it to do, we need to make sure that we can connect to Active Directory to gather all of the servers. We also need to ensure that we are running the script from a server that has the SCOM snap-in available. You can find this by running the following command.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-PSSnapin &amp;ndash;Registered&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/2804.hsg_2D00_2_2D00_13_2D00_12_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2804.hsg_2D00_2_2D00_13_2D00_12_2D00_2.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You should see the following item listed with everything else: &lt;b&gt;Microsoft.EnterpriseManagement.OperationsManager.Client &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This means that the SCOM snap-in is installed, and we can run this script from the server without worrying about it failing.&lt;/p&gt;
&lt;h3&gt;Digging into the script&lt;/h3&gt;
&lt;p&gt;Let us take a look at the first parts of the script.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$VerbosePreference = &amp;#39;continue&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Function Get-Server {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $strCategory = &amp;quot;computer&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $strOS = &amp;quot;Windows*Server*&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objSearcher = [adsisearcher]&amp;quot;&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objSearcher.Filter = (&amp;quot;(&amp;amp;(objectCategory=$strCategory)(OperatingSystem=$strOS))&amp;quot;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objSearcher.pagesize = 10&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objsearcher.sizelimit = 5000&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objSearcher.PropertiesToLoad.Add(&amp;quot;dnshostname&amp;quot;) | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objSearcher.Sort.PropertyName = &amp;quot;dnshostname&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $colResults = $objSearcher.FindAll()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($objResult in $colResults) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objComputer = $objResult.Properties&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $objComputer.dnshostname&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&gt;Here, I set up the VerbosePreference to &amp;ldquo;Continue&amp;rdquo; so I can track what the script is doing and where it is, in case something goes wrong. It is always good to include some sort of verbose/debug output in your scripts, so that not only you, but whoever uses your script will know what is going on during its use. Using my &lt;b&gt;Get-Server&lt;/b&gt; function is a quick and simple way to pull a list of servers from Active Directory, and I add the &lt;b&gt;DNSHostName&lt;/b&gt; attribute that I can use in my comparison later on. I chose the &lt;b&gt;DNSHostName&lt;/b&gt; attribute because it matches up with the data that I will later receive when performing the SCOM query.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;###User Defined Parameters&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Reviewing user defined parameters&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#SCOM Management Server&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$SCOMMgmtServer = &amp;#39;SCOMMGMT.rivendell.com&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#SCOM RMS Server&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$SCOMRMS = &amp;quot;SCOMMGMT.rivendell.com&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Systems to Exempt from SCOM&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Exempt = @(Get-Content Exempt.txt)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Emailparams = @{&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; To = &amp;#39;boeprox@rivendell.com&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; From = &amp;#39;SCOMAgentAudit@rivendell.com&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SMTPServer =&amp;#39;Exch.rivendell.com&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Subject = &amp;quot;SCOM Agent Audit&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BodyAsHTML = $True&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;Here I have my &amp;ldquo;user defined&amp;rdquo; parameters, where you need to update the existing parameters that match your environment. Listed are places for the SCOM management and RMS server, in addition to an optional exempt parameter in case you have systems that you cannot (for various reasons) have the SCOM agent installed on. If you notice the &lt;i&gt;$EmailParams&lt;/i&gt; parameter, you will see that it is actually a hash table of several parameters that will be used at the end of this script for an email notification. By the way, this is called &amp;ldquo;splatting.&amp;rdquo; Learn it, live it, love it.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Get list of AD Servers&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Getting list of servers from Active Directory&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$ADServers = Get-Server | Where {$Exempt -NotContains $_}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Initialize SCOM SnapIn&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Loading SCOM SnapIn&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client -ErrorAction SilentlyContinue&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Make SCOM Connection&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Connecting to SCOM RMS Server: {1}&amp;quot; -f (Get-Date),$SCOMRMS)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;New-ManagementGroupConnection -ConnectionString $SCOMRMS | Out-Null&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Connect to SCOM Provider&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Connecting to SCOM Provider&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Push-Location &amp;lsquo;OperationsManagerMonitoring::&amp;rsquo;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Connecting to SCOM Server: {1}&amp;quot; -f (Get-Date),$SCOMMgmtServer)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$MgmtServer = Get-ManagementServer | Where {$_.Name -eq $SCOMMgmtServer}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Get all SCOM Agent Servers&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Gathering all SCOM managed systems&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$SCOMServers = Get-Agent | Select -Expand NetworkName | Sort&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Compare list to find servers not in SCOM&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Filtering out all Non SCOM managed systems to audit&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$NonSCOMTEMP = @(Compare-Object -ReferenceObject $SCOMServers -DifferenceObject $ADServers | Where {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_.SideIndicator -eq &amp;#39;=&amp;gt;&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} | Select -Expand Inputobject)&lt;/p&gt;
&lt;p&gt;Now we are starting to perform some actions to get this script rolling. First, I use my little function to grab a list of all of the servers in Active Directory and filter out all of the systems that I listed in my exempt list. The next part loads up the SCOM snap-in so we are able to make use of the SCOM cmdlets. Next, I make the connection to the SCOM management server that was specified earlier in the script. When we have that connection, I switch directories to the &amp;ldquo;OperationsManagerMonitoring::&amp;rdquo; provider, which is required to run the commands later in the script. &amp;nbsp;After all of this, I begin my query of SCOM for all servers currently being managed via the SCOM agent, and I use &lt;b&gt;Compare-Object&lt;/b&gt; to filter out the servers from my Active Directory list that are already listed in SCOM. We now have our list of servers that we need to focus on to install the SCOM agent.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Attempt to Discover Systems&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Configuring SCOM discovery prior to use&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Discover = New-WindowsDiscoveryConfiguration -ComputerName $NonSCOM -PerformVerification -ComputerType &amp;quot;Server&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Discover.ComputerNameDiscoveryCriteria.getComputernames() | ForEach {Write-Verbose (&amp;quot;{0}: Attempting to discover&amp;quot; -f $_)}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Beginning SCOM discovery&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$DiscResults = Start-Discovery -WindowsDiscoveryConfiguration $Discover -ManagementServer $MgmtServer&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Check Alert history for failed Discoveries&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Checking for failed Discoveries&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$alerts = @(Get-Alert -Criteria &amp;quot;PrincipalName = &amp;#39;$SCOMMgmtServer&amp;#39; AND MonitoringClassId=&amp;#39;ab4c891f-3359-3fb6-0704-075fbfe36710&amp;#39;`&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;AND Name=&amp;#39;An error occurred during computer verification from the discovery wizard&amp;#39;&amp;quot;) | Where {&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Look for unresolved alerts&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_.ResolutionState -eq 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p&gt;Here I am setting up for my attempted discovery of the servers that need the SCOM agent installed.&amp;nbsp; I use my current collection of servers that is supplied to the &lt;i&gt;ComputerName&lt;/i&gt; parameter for &lt;b&gt;New-WindowsDiscoveryConfiguration&lt;/b&gt;, which I save to &lt;b&gt;$Discover&lt;/b&gt;. I then supply this variable to the &lt;b&gt;Start-Discovery&lt;/b&gt; cmdlet, and save the results of this discovery to &lt;b&gt;$DiscResults&lt;/b&gt;, which looks something like this:&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/6724.hsg_2D00_2_2D00_13_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6724.hsg_2D00_2_2D00_13_2D00_12_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This can be used later when I prepare to push out the SCOM agent installations.&lt;/p&gt;
&lt;p&gt;Now that I went through the discovery process, a check is performed against the SCOM management server by using &lt;b&gt;Get-Alert&lt;/b&gt;. I supply the principal name of the management server, filter to look only for failed discoveries, and save any results that are found so they can be parsed later and added to a collection for reporting.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;If ($Alerts.count -gt 0) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Start processing the failed discovery alerts&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $alert = $alerts&amp;nbsp; | Select -Expand Parameters&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Pattern = &amp;quot;Machine Name: ((\w+|\.)*)\s&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $FailedDiscover = $alert | ForEach {&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; $Server = ([regex]::Matches($_,$Pattern))[0].Groups[1].Value&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Try {&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; $ServerIP = ([net.dns]::Resolve($Server).AddressList[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; } Catch {&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; $ServerIP = $Null&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; If (-Not ([string]::IsNullOrEmpty($Server))) {&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; 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Server = $Server&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Reason = $_&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IP = $ServerIP&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; }&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;#&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Resolve the alerts for failed discoveries, otherwise we will have false positives that there were no failed discoveries.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Verbose (&amp;quot;[{0}] Resolving active alerts&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Alerts | ForEach {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Resolve-Alert -Alert $_ | Out-Null&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&gt;If failed discoveries are found in the alert log, the script digs out the &lt;b&gt;Parameters&lt;/b&gt; property of the &lt;b&gt;$alert&lt;/b&gt; collection, and the systems will get parsed from the log by using some regular expression magic. Then an attempt to get the IP address will be performed. The expanded &lt;b&gt;Parameters&lt;/b&gt; property will look similar to this:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;i&gt;Computer verification failure for Machine Name: DC1.Rivendell.com is 0x800706BA. The RPC server is unavailable.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Any generated reports will be saved to the &lt;b&gt;$FailedDiscover&lt;/b&gt; variable that will be sent in the email report at the end of the script. After this is done, all of the alerts that are found are resolved by the script.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;If ($DiscResults.CustomMonitoringObjects.count -gt 0) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Install Agent on Discovered Servers&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Verbose (&amp;quot;[{0}] Beginning installation of SCOM Agent on discovered systems&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $DiscResults.custommonitoringobjects | ForEach {Write-Verbose (&amp;quot;{0}: Attempting Agent Installation&amp;quot; -f $_.Name)}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Results = Install-Agent -ManagementServer $MgmtServer -AgentManagedComputer: $DiscResults.custommonitoringobjects&lt;/p&gt;
&lt;p&gt;Now for the installation of the systems that we were able to successfully discover! If you remember, I saved the results of the discovery to the &lt;b&gt;$DiscResults&lt;/b&gt; variable. Now I am able to use that to supply the collection of systems for the agent installation by using the &lt;b&gt;CustomMonitoringObjects&lt;/b&gt; property of the &lt;b&gt;$DiscResults&lt;/b&gt; collection. Note that I have saved the results of this agent installation to &lt;b&gt;$Results&lt;/b&gt; that will be parsed later in the script, and those results will be included in the email report.&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Check for failed installations&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $FailedInstall = @{}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $SuccessInstall = @{}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write-Verbose (&amp;quot;[{0}] Checking for Failed and Successful installations&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Results.MonitoringTaskResults | ForEach {&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; If (([xml]$_.Output).DataItem.ErrorCode -ne 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Failed Installation&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; $FailedInstall[([xml]$_.Output).DataItem.PrincipalName] = `&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; (([xml]$_.output).DataItem.Description.&amp;quot;#cdata-section&amp;quot; -split &amp;quot;\s{2,}&amp;quot;)[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; } 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #Successful Installation&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; $SuccessInstall[([xml]$_.Output).DataItem.PrincipalName] = `&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; Get-Date ([xml]$_.output).DataItem.Time&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;}&lt;/p&gt;
&lt;p&gt;And by later in the script, I mean now. I first create two empty hash tables that will hold the successes and failures that are found. The results of the agent installation were first split based on the error code that is in the XML data. From there, if a failure is detected, the code continues to parse the failure message from the XML and place it into the &lt;b&gt;$FailedInstall&lt;/b&gt; hash table. A failed installation result will look similar to this:&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/4341.hsg_2D00_2_2D00_13_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4341.hsg_2D00_2_2D00_13_2D00_12_2D00_4.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The task will register as a success, so I have to dig into the output XML to pull the actual error code for the agent installation. If it is a successful installation, the system is added to the &lt;b&gt;$SuccessInstall&lt;/b&gt; hash table, which will be sent in the email report at the end of the script.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$head = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;style&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TABLE{background-color:LightYellow;border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;/style&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;If ($SuccessInstall.Count -gt 0) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Adding {1} Successful installations to report&amp;quot; -f (Get-Date), $SuccessInstall.Count)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$html1 = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&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;lt;h5&amp;gt;&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; &amp;lt;font color=&amp;#39;white&amp;#39;&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Please view in html!&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; &amp;lt;/font&amp;gt;&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;lt;/h5&amp;gt;&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;lt;h2&amp;gt;&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; The following servers were found in Active Directory and had the SCOM Agent successfully installed:&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;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $($SuccessInstall.GetEnumerator() | Select Name, Value | Sort Name | ConvertTo-HTML -head $head)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} Else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $html1 = $Null&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;If ($FailedInstall.Count -gt 0) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Adding {1} Failed installations to report&amp;quot; -f (Get-Date), $FailedInstall.Count,)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$html2 = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&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;lt;h5&amp;gt;&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; &amp;lt;font color=&amp;#39;white&amp;#39;&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Please view in html!&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; &amp;lt;/font&amp;gt;&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;lt;/h5&amp;gt;&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;lt;h2&amp;gt;&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; The following servers are Active Directory and were discovered, but Failed to install the SCOM Agent:&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;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $($FailedInstall.GetEnumerator() | Select Name,Value | Sort Name | ConvertTo-HTML -head $head)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} Else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $html2 = $Null&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;If ($FailedDiscover.Count -gt 0) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Adding {1} Failed Discoveries to report&amp;quot; &amp;ndash;f (Get-Date), $FailedDiscover.Count)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$html3 = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&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;lt;h5&amp;gt;&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; &amp;lt;font color=&amp;#39;white&amp;#39;&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Please view in html!&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; &amp;lt;/font&amp;gt;&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;lt;/h5&amp;gt;&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;lt;h2&amp;gt;&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; The following servers are Active Directory but Failed to be Discovered by SCOM:&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;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $($FailedDiscover | Sort Server | ConvertTo-HTML -head $head)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} Else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $html3 = $Null&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;If ($html1 -OR $html2 -OR $html3) {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Emailparams[&amp;#39;Body&amp;#39;] = &amp;quot;$($Html1,$Html2,$Html3)&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;} Else {&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $Emailparams[&amp;#39;Body&amp;#39;] = @&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&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;lt;h5&amp;gt;&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; &amp;lt;font color=&amp;#39;white&amp;#39;&amp;gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Please view in html!&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; &amp;lt;/font&amp;gt;&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;lt;/h5&amp;gt;&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;lt;h2&amp;gt;&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; All servers in Active Directory are currently being managed by SCOM Agents.&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;lt;/h2&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;quot;@&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Write-Verbose (&amp;quot;[{0}] Sending Audit report to list of recipients.&amp;quot; -f (Get-Date))&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Send-MailMessage @Emailparams&lt;/p&gt;
&lt;p&gt;We are now at the end of the script where the data we have collected is compiled into HTML and added to the body of the email. Take note of the &lt;b&gt;@EmailParams&lt;/b&gt; that is supplied to the &lt;b&gt;Send-MailMessage&lt;/b&gt; cmdlet. This is &amp;ldquo;splatting&amp;rdquo; being used to supply all of the parameters to the cmdlet. Although I am sure that my HTML code could be a little better, it does well enough to provide a nice readable report to review. If there is nothing to report, an email will still go out. This is a reminder that if a report didn&amp;rsquo;t go out, it should be investigated for possible issues.&lt;/p&gt;
&lt;h3&gt;Script in action&lt;/h3&gt;
&lt;p&gt;Typically, this script is better run as a scheduled job to ensure that any server being brought into the domain receives the SCOM agent. But for this example, I am going to run it to show the verbose output that is generated and to show the email notification showing the HTML body.&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/3240.hsg_2D00_2_2D00_13_2D00_12_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3240.hsg_2D00_2_2D00_13_2D00_12_2D00_5.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The report that is emailed will look something like this, based on the data that was received during the duration of the script.&lt;/p&gt;
&lt;p&gt;So there you go&amp;hellip;&lt;/p&gt;
&lt;p&gt;With a little research and testing against a platform that I was not all that familiar with at the time, I was able to put together a nice script. My script automated the installation of SCOM agents for new servers that were brought into the domain, and provided a report on the installations and failures.&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;Thank you, Boe, for sharing. As always, it is an interesting and informative blog.&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=3480211" width="1" height="1" alt="" /&gt;</description></item><item><title>Use the Free PoshWSUS PowerShell Module for WSUS Administrative Work</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/01/22/use-the-free-poshwsus-powershell-module-for-wsus-administrative-work.aspx</link><pubDate>Sun, 22 Jan 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14144</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Learn how to use the free PoshWSUS Windows PowerShell module to administer your WSUS server.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. We wrap up the weekend and the week with guest blogger, Boe Prox. In case you missed them, here are links for Boe&amp;rsquo;s blogs:&lt;/p&gt;
&lt;p&gt;Day 1: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/16/introduction-to-wsus-and-powershell.aspx" target="_blank"&gt;Introduction to WSUS and PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 2: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/17/use-powershell-to-perform-basic-administrative-tasks-on-wsus.aspx" target="_blank"&gt;Use PowerShell to Perform Basic Administrative Tasks on WSUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 3: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/18/approve-or-decline-wsus-updates-by-using-powershell.aspx" target="_blank"&gt;Approve or Decline WSUS Updates by Using PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 4: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/19/use-powershell-to-find-missing-updates-on-wsus-client-computers.aspx" target="_blank"&gt;Use PowerShell to Find Missing Updates on WSUS Client Computers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 5: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/20/get-windows-update-status-information-by-using-powershell.aspx" target="_blank"&gt;Get Windows Update Status Information by Using PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 6: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/21/introduction-to-poshwsus-a-free-powershell-module-to-manage-wsus.aspx" target="_blank"&gt;Introduction to PoshWSUS, a Free PowerShell Module to Manage WSUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Take it away, Boe&amp;hellip;&lt;/p&gt;
&lt;p&gt;We are at the final stopping point in our week of WSUS and this final blog is all about WSUS administration using my PoshWSUS module. The past week has seen us create a WSUS server and managing the server by using Windows PowerShell and the WSUS assemblies, but now we are going to look at this using fewer commands by using the PoshWSUS module. I will now show some examples that use the module to perform some of the exact commands that were done earlier in the week.&lt;/p&gt;
&lt;h3&gt;Initial use of PoshWSUS&lt;/h3&gt;
&lt;p&gt;To download the module, see &lt;a href="http://poshwsus.codeplex.com/" target="_blank"&gt;PoshWSUS&lt;/a&gt; in CodePlex. Unzip the files to your Modules directory&amp;mdash;in my case for Windows&amp;nbsp;7, it is C:\Users\Boe\Documents\WindowsPowerShell\Modules. I saved the modules to a folder named PoshWSUS. This location is shown here.&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/0676.wes_2D00_1_2D00_22_2D00_12_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0676.wes_2D00_1_2D00_22_2D00_12_2D00_1.jpg" alt="Image of menu" title="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Load the module by using the &lt;b&gt;Import-Module&lt;/b&gt; cmdlet. This command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Import-Module PoshWSUS&lt;/p&gt;
&lt;p&gt;The following image shows me using the &lt;b&gt;Get-Module&lt;/b&gt; cmdlet to view the available cmdlets and using the &lt;b&gt;Import-Module&lt;/b&gt; cmdlet to import the module.&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/6102.wes_2D00_1_2D00_22_2D00_12_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6102.wes_2D00_1_2D00_22_2D00_12_2D00_2.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Make your initial connection to the WSUS server. To do this, use the &lt;b&gt;Connect-WSUSServer&lt;/b&gt; cmdlet as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Connect-WSUSServer -WsusServer DC1&lt;/p&gt;
&lt;p&gt;The following image shows the connection to the WSUS server named DC1.&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/5518.wes_2D00_1_2D00_22_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5518.wes_2D00_1_2D00_22_2D00_12_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now you are set to go!&lt;/p&gt;
&lt;h3&gt;Client and group management&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s start by looking at some basic client and group administration commands that you may find yourself using when you administer the server. The following example lists all clients that are registered in the WSUS Server.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSClient&lt;/p&gt;
&lt;p&gt;The output from the Get-WSUSClient cmdlet is shown here.&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/3323.wes_2D00_1_2D00_22_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3323.wes_2D00_1_2D00_22_2D00_12_2D00_4.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you only want to list a specific client that is registered on the WSUS server, you can run the following command to get the data.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSClient -Computer boe-pc&lt;/p&gt;
&lt;p&gt;The following image shows the result of running the Get-WSUSClient cmdlet. Note that it provides lots of good information about the client computer.&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/4478.wes_2D00_1_2D00_22_2D00_12_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4478.wes_2D00_1_2D00_22_2D00_12_2D00_5.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For some extra fun, you can even use the &lt;b&gt;Group-Object&lt;/b&gt; cmdlet to group all of your clients by operating system. A command to do this is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSClient | Group OSDescription | Select Count,Name&lt;/p&gt;
&lt;p&gt;The command and associated output are shown in the image that follows.&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/8688.wes_2D00_1_2D00_22_2D00_12_2D00_6.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8688.wes_2D00_1_2D00_22_2D00_12_2D00_6.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to display all of the target groups that are in the WSUS server, you can run use the &lt;b&gt;Get-WSUSGroup&lt;/b&gt; command.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSGroup&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/6303.wes_2D00_1_2D00_22_2D00_12_2D00_7.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6303.wes_2D00_1_2D00_22_2D00_12_2D00_7.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to add a client into a specific group, you can run this one-liner:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSClient boe-pc | Add-WSUSClientToGroup -Group TESTGROUP&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s verify that my client is actually in that group by using &lt;b&gt;Get-WSUSClientGroupMembership&lt;/b&gt;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSClientGroupMembership -Computer boe-pc&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/6266.wes_2D00_1_2D00_22_2D00_12_2D00_8.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6266.wes_2D00_1_2D00_22_2D00_12_2D00_8.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Looking at the returned data, it would appear that the client is in the TESTGROUP group.&lt;/p&gt;
&lt;p&gt;Removing a WSUS client from a group is just as simple as using &lt;b&gt;Remove-WSUSClientFromGroup&lt;/b&gt;. This command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Remove-WSUSClientFromGroup -Computer boe-pc -Group TESTGROUP&lt;/p&gt;
&lt;p&gt;One more check to see if my client is no longer in TESTGROUP. The results are shown here.&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/3386.wes_2D00_1_2D00_22_2D00_12_2D00_9.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3386.wes_2D00_1_2D00_22_2D00_12_2D00_9.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, my client is now a member of &lt;b&gt;Unassigned Computers&lt;/b&gt;, meaning that it is not a member of any group in WSUS other than the default &lt;b&gt;All Computers&lt;/b&gt; group.&lt;/p&gt;
&lt;p&gt;Creating a new group on WSUS is made simple by using &lt;b&gt;New-WSUSGroup&lt;/b&gt;. Here, I create a new group named &lt;b&gt;MyGroup&lt;/b&gt;&lt;i&gt;. &lt;/i&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;New-WSUSGroup &amp;ldquo;MYGROUP&amp;rdquo; &amp;ndash;PassThru&lt;/p&gt;
&lt;p&gt;The results of creating the new &lt;b&gt;MyGroup&lt;/b&gt;&lt;i&gt; &lt;/i&gt;group are shown in the following image.&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/0044.wes_2D00_1_2D00_22_2D00_12_2D00_10.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0044.wes_2D00_1_2D00_22_2D00_12_2D00_10.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition to creating new groups, I can remove a WSUS group. It is just as easy to remove a group, as it is to create a group. I use the &lt;b&gt;Remove-WSUSGroup&lt;/b&gt; cmdlet. An example of doing this is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSGroup -Name MYGROUP | Remove-WSUSGroup&lt;/p&gt;
&lt;h3&gt;Update administration&lt;/h3&gt;
&lt;p&gt;Now for some more fun stuff: using PoshWSUS to work with Update administration. I have two commands (&lt;b&gt;Approve-WSUSUpdate&lt;/b&gt; and &lt;b&gt;Deny-WSUSUpdate&lt;/b&gt;) that make approving and declining updates easy to do. Besides that, you can use &lt;b&gt;Get-WSUSUpdate&lt;/b&gt; to look for updates on the WSUS server.&amp;nbsp; Unfortunately, &amp;ldquo;Decline&amp;rdquo; is not an approved verb in Windows PowerShell, so I went with &amp;ldquo;Deny&amp;rdquo; instead.&lt;/p&gt;
&lt;p&gt;Using &lt;b&gt;Get-WSUSUpdate&lt;/b&gt; without any parameters will return every single update on the WSUS server. In this case, I want to see all of the Windows&amp;nbsp;7 updates.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates = Get-WSUSUpdate &amp;#39;Windows 7&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates.count&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates | Select -first 10&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/8611.wes_2D00_1_2D00_22_2D00_12_2D00_11.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8611.wes_2D00_1_2D00_22_2D00_12_2D00_11.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Approve-WSUSUpdate&lt;/b&gt; does take pipeline input from the Update object, so if you wanted to approve some updates that you queried, you could do the following:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates[1..10] | Approve-WSUSUpdate -Action Install -Group &amp;#39;All Computers&amp;#39; &amp;ndash;PassThru&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/7536.wes_2D00_1_2D00_22_2D00_12_2D00_12.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7536.wes_2D00_1_2D00_22_2D00_12_2D00_12.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the same way, you can decline updates by piping the updates into &lt;b&gt;Deny-WSUSUpdate&lt;/b&gt;. This command is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates[1..10] | Deny-WSUSUpdate&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/1663.wes_2D00_1_2D00_22_2D00_12_2D00_13.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1663.wes_2D00_1_2D00_22_2D00_12_2D00_13.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is a fun one! You can use &lt;b&gt;Get-WSUSUpdate &lt;/b&gt;and&lt;b&gt; New-WSUSUpdateScope&lt;/b&gt; to list all the updates that have been released on the last Patch Tuesday and are required by the clients, as shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSUpdate -UpdateScope (New-WSUSUpdateScope -IncludedInstallationStates NotInstalled -FromArrivalDate &amp;quot;12/13/2011&amp;quot;)&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/7711.wes_2D00_1_2D00_22_2D00_12_2D00_14.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7711.wes_2D00_1_2D00_22_2D00_12_2D00_14.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can then pipe this output into &lt;b&gt;Approve-WSUSUpdate&lt;/b&gt;:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSUpdate -UpdateScope (New-WSUSUpdateScope -IncludedInstallationStates NotInstalled -FromArrivalDate &amp;quot;12/13/2011&amp;quot;) | Approve-WSUSUpdate -Action Install -Group &amp;#39;All Computers&amp;#39; &amp;ndash;PassThru&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/4111.wes_2D00_1_2D00_22_2D00_12_2D00_15.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4111.wes_2D00_1_2D00_22_2D00_12_2D00_15.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is always a good idea to review each update to make sure that you want to approve it in your environment.&lt;/p&gt;
&lt;h3&gt;Reporting&lt;/h3&gt;
&lt;p&gt;So I have covered some administration examples that use this module, but what about some type of reporting capability? Well, I will show you some different types of reports that you can do with this module.&lt;/p&gt;
&lt;p&gt;I can look for updates that have failed to install by using the following command:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSUpdatePerClient -UpdateScope (New-WSUSUpdateScope -IncludedInstallationStates Failed)&lt;/p&gt;
&lt;p&gt;Fortunately for me (but unfortunate for this example), I do not have any updates that reported failures in the installation.&lt;/p&gt;
&lt;p&gt;I can mimic what is shown in the following example of the Administration Console by using &lt;b&gt;Get-WSUSUpdateSummaryPerClient&lt;/b&gt;.&lt;b&gt;&lt;/b&gt;&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/8270.wes_2D00_1_2D00_22_2D00_12_2D00_16.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8270.wes_2D00_1_2D00_22_2D00_12_2D00_16.jpg" alt="Image of menu" title="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSUpdateSummaryPerClient -ComputerScope (New-WSUSComputerScope) -UpdateScope (New-WSUSUpdateScope)&lt;/p&gt;
&lt;p&gt;The output is shown here:&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/2860.wes_2D00_1_2D00_22_2D00_12_2D00_17.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2860.wes_2D00_1_2D00_22_2D00_12_2D00_17.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We can even generate a report of update approvals by using &lt;b&gt;Get-WSUSUpdateApproval&lt;/b&gt; if you want to go back to see what has been approved and/or who approved a specific update. In this case, let&amp;rsquo;s go back and look at my update approvals for all of the updates from this Patch Tuesday.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope = New-WSUSUpdateScope -FromArrivalDate &amp;quot;12/13/2011&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSUpdateApproval -UpdateScope $updatescope&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/3124.wes_2D00_1_2D00_22_2D00_12_2D00_18.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3124.wes_2D00_1_2D00_22_2D00_12_2D00_18.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you wanted to get a report of patches that are needed by clients in a specific group, you can give this command a run:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSUpdateSummaryForGroup -GroupName &amp;#39;All Computers&amp;#39; -UpdateObject $updates[200..300]&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/3073.wes_2D00_1_2D00_22_2D00_12_2D00_19.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3073.wes_2D00_1_2D00_22_2D00_12_2D00_19.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Other commands to use&lt;/h3&gt;
&lt;p&gt;Besides the commands that I have shown in this blog post, there are other commands that you may find useful during your administration of a WSUS server. So, without further ado, here are some command examples:&lt;/p&gt;
&lt;p&gt;Show the current synchronization schedule by using &lt;b&gt;Get-WSUSSubscription&lt;/b&gt;:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSSubscription&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/8875.wes_2D00_1_2D00_22_2D00_12_2D00_20.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8875.wes_2D00_1_2D00_22_2D00_12_2D00_20.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Listing all Install Approval rules on your WSUS server is also easy by using &lt;b&gt;Get-WSUSInstallApprovalRule&lt;/b&gt;. For those of you who are not familiar with Install Approval, basically it allow you set up automatic approvals of specific products for specific computer target groups. Pretty nice if you know that you want to approve critical security updates for all of your clients every month.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Get-WSUSInstallApprovalRule&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/0876.wes_2D00_1_2D00_22_2D00_12_2D00_21.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0876.wes_2D00_1_2D00_22_2D00_12_2D00_21.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the same way, you can configure a new Install Approval rule by using &lt;b&gt;New-WSUSApprovalRule&lt;/b&gt; and &lt;b&gt;Set-WSUSApprovalRule&lt;/b&gt;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$group = Get-WSUSGroup -Name &amp;#39;All Computers&amp;#39;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$class = Get-WSUSUpdateClassification | Where {$_.Title -eq &amp;quot;Updates&amp;quot;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;New-WSUSInstallApprovalRule -Name &amp;quot;Rule1&amp;quot; -Category $cat -Classification $class -Group $group &amp;ndash;Enable &amp;ndash;PassThru&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/3343.wes_2D00_1_2D00_22_2D00_12_2D00_22.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3343.wes_2D00_1_2D00_22_2D00_12_2D00_22.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can even run the Install Approval rules by using &lt;b&gt;Start-WSUSInstallApprovalRule&lt;/b&gt;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Start-WSUSInstallApprovalRule -Name &amp;quot;Rule1&amp;quot;&lt;/p&gt;
&lt;p&gt;If you wanted to locate the files for each update and their location on the server, you can run the &lt;b&gt;Get-WSUSInstallableItem&lt;/b&gt; command.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates[0] | Get-WSUSInstallableItem&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/1715.wes_2D00_1_2D00_22_2D00_12_2D00_23.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1715.wes_2D00_1_2D00_22_2D00_12_2D00_23.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can dig into the files a little deeper to see how many files and where exactly they are located:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates[0] | Get-WSUSInstallableItem | Select &amp;ndash;Expand Files&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/6014.wes_2D00_1_2D00_22_2D00_12_2D00_24.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6014.wes_2D00_1_2D00_22_2D00_12_2D00_24.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That wraps it up for my week with WSUS and Windows PowerShell and also talking about my PoshWSUS module. I have more updates planned, including adding more commands (such as publishing non-Microsoft updates to WSUS) and updating existing commands. Remember that if you see something that you would like to see added to the module or you find a bug in it, please log your issues and ideas in the &lt;a href="http://poshwsus.codeplex.com/workitem/list/basic" target="_blank"&gt;CodePlex Issue Tracker&lt;/a&gt;. Thank you everyone for checking out my blogs and thanks to Ed for allowing me to take over a week of Hey, Scripting Guy! to talk WSUS and Windows PowerShell!&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;Thanks, Boe, for an awesome week of Windows PowerShell goodness. Join us tomorrow for a new week on the Hey, Scripting Guy! blog.&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=3475015" width="1" height="1" alt="" /&gt;</description></item><item><title>Introduction to PoshWSUS, a Free PowerShell Module to Manage WSUS</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/01/21/introduction-to-poshwsus-a-free-powershell-module-to-manage-wsus.aspx</link><pubDate>Sat, 21 Jan 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14136</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Guest blogger, Boe Prox, discusses the development of the free Windows PowerShell module that he wrote to manage WSUS.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Today we are celebrating our 2000&lt;sup&gt;th&lt;/sup&gt; Hey, Scripting Guy! blog. I think that in the spirit of community, it is appropriate that today we also have a guest blogger, Boe Prox, who is talking about a project that he developed and shared on CodePlex.&lt;/p&gt;
&lt;p&gt;I will let him speak for himself&amp;mdash;take it away Boe&amp;hellip;&lt;/p&gt;
&lt;p&gt;After a week of working with Windows PowerShell and WSUS and showing you some pretty cool things that you can do with the two, I am going to talk about a project that I have been working on that will make administering a WSUS server easier with Windows PowerShell.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here are the blogs from the past week if you would like to catch up:&lt;/p&gt;
&lt;p&gt;Day 1: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/16/introduction-to-wsus-and-powershell.aspx" target="_blank"&gt;Introduction to WSUS and PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 2: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/17/use-powershell-to-perform-basic-administrative-tasks-on-wsus.aspx" target="_blank"&gt;Use PowerShell to Perform Basic Administrative Tasks on WSUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 3: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/18/approve-or-decline-wsus-updates-by-using-powershell.aspx" target="_blank"&gt;Approve or Decline WSUS Updates by Using PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 4: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/19/use-powershell-to-find-missing-updates-on-wsus-client-computers.aspx" target="_blank"&gt;Use PowerShell to Find Missing Updates on WSUS Client Computers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 5: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/20/get-windows-update-status-information-by-using-powershell.aspx" target="_blank"&gt;Get Windows Update Status Information by Using PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My plan today is to give an overview of what PoshWSUS is and why I built it the way I did, plus show a couple of small examples. Tomorrow I will show you more examples of using PoshWSUS to accomplish some of the same tasks that I have been showing earlier in the week in addition to a few new things.&lt;/p&gt;
&lt;h3&gt;What is PoshWSUS?&lt;/h3&gt;
&lt;p&gt;PoshWSUS is a module that I designed and built to help a system administrator manage a WSUS server easily by using Windows PowerShell. To download the module, see &lt;a href="http://poshwsus.codeplex.com/" target="_blank"&gt;PoshWSUS&lt;/a&gt; in CodePlex.&lt;/p&gt;
&lt;p&gt;Currently, there are 60 commands that are available in version 2.0, which was recently released on Dec. 18, 2011. There are various commands that one can use with this module. Although a majority of commands are query-type commands, there are other commands that allow you to approve or decline updates, create groups, add clients to groups, and work with synchronizations (to name a few). Here is a full list of the commands available:&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/2625.wes_2D00_1_2D00_21_2D00_12_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2625.wes_2D00_1_2D00_21_2D00_12_2D00_1.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PoshWSUS originally started as one module file (.psm1) that contained approximately 45 commands. This file was over 2000 lines long, which made it extremely difficult to work with, especially when it came time to troubleshoot one of the commands.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When it came time to work on version 2.0 of PoshWSUS, I made the decision to separate each of the commands into its own file to make it much easier to work with. I can then use the module file to go through each of the files and dot source the functions from those files.&lt;/p&gt;
&lt;h3&gt;Why PoshWSUS?&lt;/h3&gt;
&lt;p&gt;I work with WSUS almost daily, and wanted a way to quickly perform a query or quick update approval against WSUS without having to jump onto the Administration Console and click, click, click my way to victory. Another piece of motivation that I used in writing this module is that there was no module for WSUS at all. Sure, there are various scripts available that perform various queries, approvals, and so on&amp;mdash;but never a module that really tied everything together and covered a wide threshold of things to do in WSUS. Thus, PoshWSUS comes into play to fill in that gap and allow people to manage their WSUS server from the command line.&lt;/p&gt;
&lt;p&gt;So with that, I will talk a little about some of the new things that my latest version brings into play.&lt;/p&gt;
&lt;h3&gt;Working with custom types&lt;/h3&gt;
&lt;p&gt;One of the things that I was determined to change was the way that the output from any command would be displayed in the console. By default, if you run a command that would list a client or update, you would be crushed by a sea of data for each client and update that was returned unless you used &lt;b&gt;Select-Object&lt;/b&gt; or &lt;b&gt;Format-Table&lt;/b&gt; and listed only the properties that you wanted to see. Obviously, I couldn&amp;rsquo;t add this into my commands because I would lose the object type and also limit the amount of data that was available to a user.&lt;/p&gt;
&lt;p&gt;Here is an example of such output from an update query:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Pretty wild, isn&amp;rsquo;t it?&amp;nbsp; Well, thanks to custom-type formatting, I can dictate what is displayed by each output while still preserving the object type.&amp;nbsp; Now, I won&amp;rsquo;t go into detail about how this works because that would be a blog (or two) in itself. But as you can see in the following example, it greatly simplifies the display of the output while still retaining the object&amp;rsquo;s type.&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/5824.wes_2D00_1_2D00_21_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5824.wes_2D00_1_2D00_21_2D00_12_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So it looks better AND retains the object type.&lt;/p&gt;
&lt;p&gt;Even if you use &lt;b&gt;Format-List&lt;/b&gt;, it will not show every property unless you specify by using the &amp;ldquo;&lt;b&gt;*&lt;/b&gt;&amp;rdquo;. This is shown here.&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/8461.wes_2D00_1_2D00_21_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8461.wes_2D00_1_2D00_21_2D00_12_2D00_4.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Adding properties to an existing type&lt;/h3&gt;
&lt;p&gt;While most of the data that is returned by a query is useful, sometimes you get some properties that aren&amp;rsquo;t as helpful in their current state. For instance, let&amp;rsquo;s look at the following output:&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/3731.wes_2D00_1_2D00_21_2D00_12_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3731.wes_2D00_1_2D00_21_2D00_12_2D00_5.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Updated is not exactly something that we can use because we have no idea what update it is referring to. By adding some extra properties for this type (Microsoft.UpdateServices.Internal.BaseApi.UpdateSummary), we can translate that ID into the following:&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/4861.wes_2D00_1_2D00_21_2D00_12_2D00_6.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4861.wes_2D00_1_2D00_21_2D00_12_2D00_6.jpg" border="0" alt="" /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1200.wes_2D00_1_2D00_21_2D00_12_2D00_7.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1200.wes_2D00_1_2D00_21_2D00_12_2D00_7.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can tell, there are a couple of properties that are null, and this is by design for this object. How this query is performed will determine which of the &lt;b&gt;UpdateTitle&lt;/b&gt;, &lt;b&gt;ComputerGroup&lt;/b&gt;, and &lt;b&gt;Computer&lt;/b&gt; properties would be populated. This technique is used with several types to provide clearer data that is returned on various queries.&lt;/p&gt;
&lt;p&gt;Most of the information about working with type formatting was via Jeffery Hicks and my time at the PowerShell Deep Dive where he presented on the subject. Here is some information about Jeff:&lt;br /&gt; Blog: &lt;a href="http://jdhitsolutions.com/blog/" target="_blank"&gt;The Lonely Administrator&lt;/a&gt;&lt;br /&gt; Twitter: &lt;a href="https://twitter.com/JeffHicks" target="_blank"&gt;https://twitter.com/JeffHicks&lt;/a&gt;&lt;br /&gt; YouTube video of Deep Dive session: &lt;a href="http://www.youtube.com/watch?v=dZsRc7EHIbc" target="_blank"&gt;Mastering Format and Type Extensions&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Removing plural nouns&lt;/h3&gt;
&lt;p&gt;Another thing that I changed was some of the names of the commands in the module. Originally, I had several modules that were named with a plural noun and another that was singular, such as &lt;b&gt;Get-WSUSClient&lt;/b&gt; and &lt;b&gt;Get-WSUSClients&lt;/b&gt;. It is poor practice in Windows PowerShell to have a plural-named noun for a command, so I made sure to merge those commands into one that used a singular noun.&lt;/p&gt;
&lt;h3&gt;Providing feedback&lt;/h3&gt;
&lt;p&gt;Feedback from the community drives any project, and this module is no different. I encourage anyone who uses this module to please let me know what they like and don&amp;rsquo;t like about it. Any bugs that you find or anything that you feel would make a good feature is always helpful to the growth of PoshWSUS. You can log issues and ideas in the &lt;a href="http://poshwsus.codeplex.com/workitem/list/basic" target="_blank"&gt;CodePlex Issue Tracker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That pretty much sums up my module, PoshWSUS and gives you a little more information about its beginnings and some of the new things I did with version 2.0. Tomorrow I will go into how to use PoshWSUS, explore some of the commands, show you how to achieve some of the same results from some of the commands we have been using during the past week, and show you a few new things. See you tomorrow!&lt;/p&gt;
&lt;p&gt;~Boe&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=3475009" width="1" height="1" alt="" /&gt;</description></item><item><title>Get Windows Update Status Information by Using PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/01/20/get-windows-update-status-information-by-using-powershell.aspx</link><pubDate>Fri, 20 Jan 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14113</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: Learn how to use the WSUS Update Scope with Windows PowerShell to get update status information for client computers.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. What a week. Boe Prox has certainly been sharing quite a bit of Windows PowerShell goodness. In case you have missed them, here are links to the blog series thus far. You can also see Boe&amp;rsquo;s biography in the Day&amp;nbsp;1 blog.&lt;/p&gt;
&lt;p&gt;Day 1: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/16/introduction-to-wsus-and-powershell.aspx" target="_blank"&gt;Introduction to WSUS and PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 2: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/17/use-powershell-to-perform-basic-administrative-tasks-on-wsus.aspx" target="_blank"&gt;Use PowerShell to Perform Basic Administrative Tasks on WSUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 3: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/18/approve-or-decline-wsus-updates-by-using-powershell.aspx" target="_blank"&gt;Approve or Decline WSUS Updates by Using PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 4: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/19/use-powershell-to-find-missing-updates-on-wsus-client-computers.aspx" target="_blank"&gt;Use PowerShell to Find Missing Updates on WSUS Client Computers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Today we are moving from working with the Computer Target Scope and generating some cool reports to working with the Update Scope on the WSUS server. Much like yesterday, I will dive into some of the objects that we have worked with throughout the week and make use of some of the methods that require the Update Scope object to work properly.&lt;/p&gt;
&lt;p&gt;If you are asking, &amp;ldquo;What is the Update Scope?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;hellip;As the name implies, this is a scope that can be used to filter a list of updates on the WSUS server.&lt;/p&gt;
&lt;h3&gt;Creating the Update Scope object&lt;/h3&gt;
&lt;p&gt;Much as we did with the Computer Target Scope object, we need first to create the Update Scope object so we can then look at its properties and make adjustments, if needed. To create this object, we need to use the &lt;b&gt;Microsoft.UpdateServices.Administration.UpdateScope&lt;/b&gt; class. For more information about this class, see &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.updateservices.administration.updatescope%28v=VS.85%29.aspx" target="_blank"&gt;UpdateScope Class&lt;/a&gt; on MSDN. The code that follows creates an instance of the &lt;b&gt;UpdateScope&lt;/b&gt;&lt;i&gt;.&lt;/i&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope&lt;/p&gt;
&lt;p&gt;OK, let&amp;rsquo;s take a look at these properties. The image that follows displays this information.&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/5001.hsg_2D00_1_2D00_20_2D00_12_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5001.hsg_2D00_1_2D00_20_2D00_12_2D00_1.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is a list of the editable properties for the Update Scope object:&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ApprovedStates&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the approval states to search for. An update will be included only if it matches at least one of the specified states. This value may be a combination of any number of values from ApprovedStates. Defaults to Any.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ExcludedInstallationStates&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the installation states to exclude. An update will be included only if it does not have any computers in any of the specified states. This value may be a combination of any number of values from UpdateInstallationStates. Defaults to 0.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ExcludeOptionalUpdates&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets whether to exclude optional updates from the list.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;FromArrivalDate&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the minimum arrival date to search for. An update will be included only if its arrival date is greater than or equal to this value.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;FromCreationDate&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the minimum creation date to search for. An update will be included only if its creation date is greater than or equal to this value.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;IncludedInstallationStates&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the installation states to search for. An update will be included only if it has at least one computer in one of the specified states. This value may be a combination of any number of values from &lt;b&gt;UpdateInstallationStates&lt;/b&gt;.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;IsWsusInfrastructureUpdate&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets whether or not to filter for WSUS infrastructure updates. If set to &lt;b&gt;true&lt;/b&gt;, only WSUS infrastructure updates will be included. If set to &lt;b&gt;false&lt;/b&gt;, all updates are included. Defaults to false.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;TextIncludes&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the string to search for. An update will be included only if its Title, Description, Knowledge Base articles, or security bulletins contains this string.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;TextNotIncludes&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the string to exclude. An update will be not be included if its Title, Description, Knowledge Base articles, or security bulletins contains this string.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ToArrivalDate&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the maximum arrival date to search for. An update will be included only if its arrival date is less than or equal to this value.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ToCreationDate&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the maximum creation date to search for. An update will be included only if its creation date is less than or equal to this value.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;UpdateApprovalActions&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the update approval actions to search for. An update will be included only if it is approved to at least one computer target group for one of the specified approval actions. This value may be a combination of any number of values from UpdateApprovalActions. Defaults to All.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;UpdateApprovalScope&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the UpdateApprovalScope object that can be used to filter updates based on their approval properties.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;UpdateSources&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the update sources to search for. An update will be included only if its update source is included in this value. This value may be a combination of any number of values from UpdateSources.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;UpdateTypes&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the update types to search for. An update will be included only if its update type is included in this value.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Yes, that is a fairly large list of properties that we can modify to suit our filtering needs. For the sake of simplicity, I am only going to update &lt;b&gt;ApprovedStates, IncludedInstallationStates&lt;/b&gt;,&lt;b&gt; &lt;/b&gt;and&lt;b&gt; FromArrivalTime&lt;/b&gt; to show how you can see all of the updates that are needed by all of the clients since the last patch Tuesday. The code that follows updates these three properties.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.ApprovedStates = [Microsoft.UpdateServices.Administration.ApprovedStates]::NotApproved&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.IncludedInstallationStates = [Microsoft.UpdateServices.Administration.UpdateInstallationStates]::NotInstalled&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.FromArrivalDate = [datetime]&amp;quot;12/13/2011&amp;quot;&lt;/p&gt;
&lt;p&gt;Note: For the purposes of this blog, the last patch Tuesday was December 13. I set the &lt;b&gt;ApprovedStates&lt;/b&gt; property to &lt;b&gt;NotApproved&lt;/b&gt; because I only want to see updates that are required by the clients that are not already approved for installation. I set the &lt;b&gt;IncludedInstallationStates&lt;/b&gt; to &lt;b&gt;NotInstalled&lt;/b&gt;. This will tell the filter to look for only updates that are required by the clients, but have not been installed yet. This works fine for us because these updates are new to us and because we only want those for the most recent patch Tuesday.&lt;/p&gt;
&lt;p&gt;First, I am going to show you the Administration Console and look at all updates that are required by the clients on the network since patch Tuesday. This is shown in the image that follows.&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/1537.hsg_2D00_1_2D00_20_2D00_12_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1537.hsg_2D00_1_2D00_20_2D00_12_2D00_2.jpg" alt="Image of menu" title="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note the number of updates (30) and some of the titles listed here. Although not all of the updates are listed in the image, I will show you a couple of methods that we can use to pull the exact same information by using Windows PowerShell!&lt;/p&gt;
&lt;p&gt;&lt;b&gt;GetUpdateCount()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This method, as you can probably tell, will allow us to view the number of updates that are returned by using the previously configured Update Scope.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetUpdateCount($updatescope)&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/0066.hsg_2D00_1_2D00_20_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0066.hsg_2D00_1_2D00_20_2D00_12_2D00_3.jpg" alt="Image of computer output" title="Image of computer output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Look at that, 30 updates&amp;mdash;just as if it showed on the console.&lt;/p&gt;
&lt;p&gt;I am going to expand on this slightly by using another method similar to one I showed you yesterday for the Computer Target Scope.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;GetUpdateStatus()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This will return a little more information about the updates, as you will see. Besides supplying the Update Scope object, I need to supply a Boolean value for whether to include DownStream Computers.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetUpdateStatue($updatescope,$False)&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/0508.hsg_2D00_1_2D00_20_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0508.hsg_2D00_1_2D00_20_2D00_12_2D00_4.jpg" alt="Image of computer output" title="Image of computer output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That is pretty cool, but we want to see those updates as well. Sure enough, we can use the &lt;b&gt;GetUpdates()&lt;/b&gt; method and supply our Update Scope object to pull this information.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetUpdates($updatescope) | Select Title&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/4380.hsg_2D00_1_2D00_20_2D00_12_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/4380.hsg_2D00_1_2D00_20_2D00_12_2D00_5.jpg" alt="Image of computer output" title="Image of computer output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And there you have it! You can compare the screenshots and you will see that the titles in the console match the titles from our query.&lt;/p&gt;
&lt;p&gt;Now I will show you how to view the update approvals by using the Update Scope object and the &lt;b&gt;GetUpdateApprovals()&lt;/b&gt; method. To make this work and to provide some useful information, I will make a couple of adjustments to the existing Update Scope. This revision is shown here.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.FromArrivalDate = [datetime]&amp;quot;10/01/2011&amp;quot;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.ApprovedStates = [Microsoft.UpdateServices.Administration.ApprovedStates]::LatestRevisionApproved&lt;/p&gt;
&lt;p&gt;Now we can use this scope in the method and pull some information. To do this, I use the &lt;b&gt;GetUpdateApprovals &lt;/b&gt;method, and pass it the Update Scope. This technique is shown in the code that follows.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetUpdateApprovals($updatescope)&lt;/p&gt;
&lt;p&gt;The result from the previous command is shown in the following image.&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/8078.hsg_2D00_1_2D00_20_2D00_12_2D00_6.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8078.hsg_2D00_1_2D00_20_2D00_12_2D00_6.jpg" alt="Image of computer output" title="Image of computer output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let us clean this up a little so it is more readable and not just a bunch of GUIDs. The code that follows produces an easier to read output.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetUpdateApprovals($updatescope) | Select @{L=&amp;#39;ComputerTargetGroup&amp;#39;;E={$_.GetComputerTargetGroup().Name}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;@{L=&amp;#39;UpdateTitle&amp;#39;;E={($wsus.GetUpdate([guid]$_.UpdateId.UpdateId.Guid)).Title}},GoLiveTime,AdministratorName,Deadline&lt;/p&gt;
&lt;p&gt;The result of the previous code is shown here.&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/8561.hsg_2D00_1_2D00_20_2D00_12_2D00_7.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8561.hsg_2D00_1_2D00_20_2D00_12_2D00_7.jpg" alt="Image of computer output" title="Image of computer output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The last two things I will show you in this blog are a couple of methods that require the Update Scope object and the Computer Target Scope object to work properly. They provide some nice reporting features similar to what you would see in the Administration Console.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;GetSummariesPerComputerTarget()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This method gets per-computer summaries for each of the specified computers, summed across all of the specified updates.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see this in action, where I use the following code to gather this information.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$computerscope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetSummariesPerComputerTarget($updatescope,$computerscope) |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Format-Table @{L=&amp;#39;ComputerTarget&amp;#39;;E={($wsus.GetComputerTarget([guid]$_.ComputerTargetId)).FullDomainName}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @{L=&amp;#39;NeededCount&amp;#39;;E={($_.DownloadedCount + $_.NotInstalledCount)}},DownloadedCount,NotApplicableCount,NotInstalledCount,InstalledCount,FailedCount&lt;/p&gt;
&lt;p&gt;The output from the previous code produces a nice table, as shown here.&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/5811.hsg_2D00_1_2D00_20_2D00_12_2D00_8.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5811.hsg_2D00_1_2D00_20_2D00_12_2D00_8.jpg" alt="Image of computer output" title="Image of computer output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how this compares to what you would see in the console. One thing you do not have available in the console is the &lt;b&gt;DownloadedCount&lt;/b&gt;, which our previous code nicely displayed.&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/7462.hsg_2D00_1_2D00_20_2D00_12_2D00_9.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7462.hsg_2D00_1_2D00_20_2D00_12_2D00_9.jpg" alt="Image of menu" title="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lastly, let&amp;rsquo;s look at the &lt;b&gt;GetSummariesPerUpdate()&lt;/b&gt; method to get per-update summaries for each of the specified updates, summed across all of the specified computers. The following code uses this method.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.ApprovedStates = [Microsoft.UpdateServices.Administration.ApprovedStates]::NotApproved&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.IncludedInstallationStates = [Microsoft.UpdateServices.Administration.UpdateInstallationStates]::NotInstalled&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updatescope.FromArrivalDate = [datetime]&amp;quot;12/13/2011&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetSummariesPerUpdate($updatescope,$computerscope) |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Format-Table @{L=&amp;#39;UpdateTitle&amp;#39;;E={($wsus.GetUpdate([guid]$_.UpdateId)).Title}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @{L=&amp;#39;NeededCount&amp;#39;;E={($_.DownloadedCount + $_.NotInstalledCount)}},DownloadedCount,NotApplicableCount,NotInstalledCount,InstalledCount,FailedCount&lt;/p&gt;
&lt;p&gt;Note: I changed the Update Scope to what I had at the beginning of this blog. This is so I can more accurately compare the output here with what is in the Administration Console.&lt;/p&gt;
&lt;p&gt;The output from the previous code is shown here.&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/3201.hsg_2D00_1_2D00_20_2D00_12_2D00_10.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3201.hsg_2D00_1_2D00_20_2D00_12_2D00_10.jpg" alt="Image of computer output" title="Image of computer output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now compare the previous image, with the console (shown here), and you will see that they match up as planned.&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/7848.hsg_2D00_1_2D00_20_2D00_12_2D00_11.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7848.hsg_2D00_1_2D00_20_2D00_12_2D00_11.jpg" alt="Image of menu" title="Image of menu" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So there you have it. We spent the week starting out with a WSUS server installation, then doing some basic administration, and we finished by providing some reports using Windows PowerShell&amp;mdash;and we haven&amp;rsquo;t even begun to scratch the surface of what we can do. But working with WSUS doesn&amp;rsquo;t end here! This weekend I will talk about update&amp;nbsp;2.0 to my WSUS module, &lt;a href="http://poshwsus.codeplex.com/" target="_blank"&gt;PoshWSUS&lt;/a&gt;, which you can use to more easily manage and maintain a WSUS server.&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;Boe, this is great stuff. Thank you for sharing with us. WSUS Week will continue tomorrow.&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=3474980" width="1" height="1" alt="" /&gt;</description></item><item><title>Use PowerShell to Find Missing Updates on WSUS Client Computers</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/01/19/use-powershell-to-find-missing-updates-on-wsus-client-computers.aspx</link><pubDate>Thu, 19 Jan 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14086</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;b&gt;ummary&lt;/b&gt;: Learn how to use the computer target scope with Windows PowerShell to find WSUS client computers that are missing updates.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. We are halfway through WSUS Week and some really good stuff from Boe Prox. You can see Boe&amp;rsquo;s biography in the Day 1 blog. In case you need to catch up with the series on Windows Software Update Services (WSUS), the following blogs will get you up to speed:&lt;/p&gt;
&lt;p&gt;Day 1: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/16/introduction-to-wsus-and-powershell.aspx" target="_blank"&gt;Introduction to WSUS and PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 2: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/17/use-powershell-to-perform-basic-administrative-tasks-on-wsus.aspx" target="_blank"&gt;Use PowerShell to Perform Basic Administrative Tasks on WSUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Day 3: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/18/approve-or-decline-wsus-updates-by-using-powershell.aspx" target="_blank"&gt;Approve or Decline WSUS Updates by Using PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, here is Boe&amp;hellip;&lt;/p&gt;
&lt;p&gt;Over the past few days, I have been showing you some basic administration examples of what you can do by using Windows PowerShell to manage a WSUS server. During the course of some of these examples, I alluded to some methods that required a Computer Target Scope object. Well, today is the day that I get to show you how you can build a Computer Target Scope object and use that with some of the existing objects we have already created.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;What is the Computer Target Scope?&amp;rdquo; you ask? The Computer Target Scope is, as the name implies, a scope that that can be used to filter a list of clients. For more information about this class, see &lt;a href="http://msdn.microsoft.com/en-us/library/aa354282%28v=VS.85%29.aspx" target="_blank"&gt;ComputerTargetScope Class&lt;/a&gt; on MSDN.&lt;/p&gt;
&lt;h3&gt;Creating the Computer Target Scope object&lt;/h3&gt;
&lt;p&gt;The first thing we need to do is create the scope object, which we can then use in some of the methods we have seen. To do this will require us to create the new object from the &lt;b&gt;Microsoft.UpdateServices.Administration.ComputerTargetScope &lt;/b&gt;class.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$computerscope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope&lt;/p&gt;
&lt;p&gt;Simple enough to do, and we can choose to leave the default properties that are already set for this object if we want to.&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/8244.hsg_2D00_1_2D00_19_2D00_12_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8244.hsg_2D00_1_2D00_19_2D00_12_2D00_1.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So as a default object, this will reference all clients on the WSUS server. Fortunately, you can edit most of these properties to narrow down the clients that you want to use. Here is a list of the editable properties:&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ExcludedInstallationStates&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the installation states to exclude.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;FromLastReportedStatusTime&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the earliest reported status time.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;FromLastSyncTime&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the earliest last synchronization time to search for.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;IncludedInstallationStates&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the update installation states to search for.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;IncludeDownstreamComputerTargets&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets whether or not clients of a downstream server, not clients of this server, should be included.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;IncludeSubgroups&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets whether the ComputerTargetGroups property should include descendant groups.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;NameIncludes&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets a name to search for.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;OSFamily&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the operating system family for which to search.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ToLastReportedStatusTime&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the latest last reported status time to search for.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;ToLastSyncTime&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Gets or sets the latest last synchronization time to search for.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Working with the Computer Target Scope&lt;/h3&gt;
&lt;p&gt;Now, if you remember from the previous posts, there are some methods from the &lt;b&gt;Update&lt;/b&gt; object (&lt;b&gt;Microsoft.UpdateServices.Internal.BaseApi.Update&lt;/b&gt;) and from the WSUS object (&lt;b&gt;Microsoft.UpdateServices.Internal.BaseApi.UpdateServer&lt;/b&gt;) that require a computer scope object to work.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at some of these methods from the respective objects and see what we are able to pull.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[void][reflection.assembly]::LoadWithPartialName(&amp;quot;Microsoft.UpdateServices.Administration&amp;quot;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Connect to the WSUS Server and create the wsus object&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer(&amp;#39;dc1&amp;#39;,$False)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Create a computer scope object&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$computerscope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;#Find all clients using the computer target scope&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetComputerTargets($computerscope)&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/8371.hsg_2D00_1_2D00_19_2D00_12_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/8371.hsg_2D00_1_2D00_19_2D00_12_2D00_2.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By leaving the default properties, we will pull every client from the WSUS server.&lt;/p&gt;
&lt;p&gt;Another method that we can use, which provides a report on the computers that match the scope filter is &lt;b&gt;GetComputerStatus()&lt;/b&gt;. This method requires that you have a computer scope object and that you define a &lt;b&gt;Microsoft.UpdateServices.Administration.UpdateSources&lt;/b&gt; object, which consists of &lt;b&gt;All&lt;/b&gt;, &lt;b&gt;Microsoft Update&lt;/b&gt;, or &lt;b&gt;Other&lt;/b&gt;. Let&amp;rsquo;s give it a look.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$Wsus.GetComputerStatus($computerscope,[&lt;b&gt; &lt;/b&gt;Microsoft.UpdateServices.Administration.UpdateSources]::All)&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/1732.hsg_2D00_1_2D00_19_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/1732.hsg_2D00_1_2D00_19_2D00_12_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You might be wondering why we are seeing mostly &lt;b&gt;0&lt;/b&gt;s here. If you look closely, you can see that only the areas where it mentions the computer targets are populated. This is by design for this object&amp;rsquo;s method because we only specified to get the status of the computers that match the scope filter.&lt;/p&gt;
&lt;p&gt;Now, looking at the update object&amp;rsquo;s method, I can see a couple of methods that are available and require the computer scope.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;GetSummary()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This will give us a summary of whether the clients that are specified in the scope require the update.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates = $wsus.SearchUpdates(&amp;#39;Update for Windows Server 2003 (KB938759)&amp;#39;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update = $updates[0]&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update.GetSummary($computerscope)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;UnknownCount&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;NotApplicableCount&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 2&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;NotInstalledCount&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;DownloadedCount&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 1&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;InstalledCount&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;InstalledPendingRebootCount : 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;FailedCount&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 0&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;IsSummedAcrossAllUpdates&amp;nbsp;&amp;nbsp;&amp;nbsp; : False&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;UpdateId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : c2cdd066-7a03-4e7f-976c-139b5de943ed&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ComputerTargetGroupId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : 00000000-0000-0000-0000-000000000000&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;ComputerTargetId&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;LastUpdated&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: 12/10/2011 7:08:29 AM&lt;/p&gt;
&lt;p&gt;By looking at the data provided, I can see that only 1 client out of the 3 require this update and that it has already been downloaded to that client. This is a nice way of providing a report of a specific update&amp;rsquo;s status for clients. But the problem is&amp;hellip;which client requires the update? I will show you how to use the &lt;b&gt;GetUpdateInstallationInfoPerComputerTarget()&lt;/b&gt; method on the Update object.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update.GetUpdateInstallationInfoPerComputerTarget($ComputerScope)&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/3652.hsg_2D00_1_2D00_19_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/3652.hsg_2D00_1_2D00_19_2D00_12_2D00_4.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Although it &lt;b&gt;does&lt;/b&gt; tell you which client ID requires the update, it&amp;rsquo;s not what I would call &amp;ldquo;humanly readable&amp;rdquo; by any means. But this is Windows PowerShell, after all, and we can certainly make this better for us to read.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update.GetUpdateInstallationInfoPerComputerTarget($ComputerScope) |&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;Select @{L=&amp;#39;Client&amp;#39;;E={$wsus.GetComputerTarget(([guid]$_.ComputerTargetId)).FulldomainName}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;@{L=&amp;#39;TargetGroup&amp;#39;;E={$wsus.GetComputerTargetGroup(([guid]$_.UpdateApprovalTargetGroupId)).Name}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;@{L=&amp;#39;Update&amp;#39;;E={$wsus.GetUpdate(([guid]$_.UpdateId)).Title}},&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&amp;nbsp;UpdateInstallationState,UpdateApprovalAction&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/0486.hsg_2D00_1_2D00_19_2D00_12_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0486.hsg_2D00_1_2D00_19_2D00_12_2D00_5.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Much better! Now we have something that not only tells us which client, but actually gives us the name of the client without giving us a GUID to try to guess with. I also translated the Target Group ID and the Update ID so that everything is much easier to read.&lt;/p&gt;
&lt;p&gt;Well, that wraps it up for today. Tomorrow I will jump into working with the Update&amp;nbsp;Scope object and performing queries that use that object.&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;Boe, thank you for another great blog about using the WSUS object model. WSUS Week will continue tomorrow.&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;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3474944" width="1" height="1" alt="" /&gt;</description></item><item><title>Approve or Decline WSUS Updates by Using PowerShell</title><link>http://powershell.com/cs/blogs/hey-scriptingguy/archive/2012/01/18/approve-or-decline-wsus-updates-by-using-powershell.aspx</link><pubDate>Wed, 18 Jan 2012 06:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:14060</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;: Guest blogger, Boe Prox, shows how to use Windows PowerShell to approve or to decline updates for WSUS.&lt;/p&gt;
&lt;p&gt;Microsoft Scripting Guy, Ed Wilson, is here. Welcome to the third day of Boe Prox as our guest blogger talking about using Windows PowerShell with WSUS.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Day 1: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/16/introduction-to-wsus-and-powershell.aspx" target="_blank"&gt;Introduction to WSUS and PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Day 2: &lt;a href="http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/17/use-powershell-to-perform-basic-administrative-tasks-on-wsus.aspx" target="_blank"&gt;Use PowerShell to Perform Basic Administrative Tasks on WSUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s Boe&amp;hellip;&lt;/p&gt;
&lt;p&gt;Continuing on from yesterday&amp;rsquo;s post where we looked at managing clients and groups, it is time to look at that one thing that really defines the WSUS server. I am talking about updates, of course! We will start by performing a basic query to locate updates and explore the update object to see what methods we have available, and then we will go into approving and declining updates.&lt;/p&gt;
&lt;h3&gt;Update queries&lt;/h3&gt;
&lt;p&gt;Using our existing connection from the previous day&amp;rsquo;s examples, let&amp;rsquo;s look at the possible methods related to locating updates on the WSUS server.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;GetUpdates()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This method will give you back EVERY SINGLE UPDATE on your WSUS server. (This is assuming that you have completed a successful synchronization&amp;mdash;if not, synchronize your WSUS server now.) This method is painfully slow to run and it is not a recommended method to gather information about updates.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetUpdates()&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/0005.hsg_2D00_1_2D00_18_2D00_12_2D00_1.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/450x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0005.hsg_2D00_1_2D00_18_2D00_12_2D00_1.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;Well, this is awkward. Oh wait, since I just installed this WSUS server, I have not performed a critical task that will allow me to start viewing updates. I need to synchronize this WSUS server with the Microsoft upstream server and get all of my update data.&lt;/p&gt;
&lt;h3&gt;WSUS synchronization&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s take a detour on our little trip through working with updates to get this server synced up and ready to go. To get this going, we need to look at the &lt;b&gt;GetSubscription() &lt;/b&gt;method to see when the last synchronization was and also to use that object&amp;rsquo;s method to work with the synchronization. The object that is returned when you use this method is &lt;b&gt;Microsoft.UpdateServices.Internal.BaseApi.Subscription&lt;/b&gt;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetSubscription()&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/7345.hsg_2D00_1_2D00_18_2D00_12_2D00_2.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7345.hsg_2D00_1_2D00_18_2D00_12_2D00_2.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Take a look at LastSynchronizationTime, and you will see that this WSUS server has not been synced yet. Synching this server is pretty simple. We will use this object&amp;rsquo;s method, which is conveniently named &lt;b&gt;StartSynchronization(). &lt;/b&gt;Let&amp;rsquo;s go ahead and kick this off.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription = $wsus.GetSubscription()&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.StartSynchronization()&lt;/p&gt;
&lt;p&gt;Nothing is returned when you kick this off, so we need a way to track this process and find out when it is finished. Enter the &lt;b&gt;GetSynchronizationProgress()&lt;/b&gt; method, which will tell us exactly where we are with the sync process.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$subscription.GetSynchronizationProgress()&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/5488.hsg_2D00_1_2D00_18_2D00_12_2D00_3.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/5488.hsg_2D00_1_2D00_18_2D00_12_2D00_3.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is slowly getting there. I will check back shortly and see if it has completed yet.&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/0508.hsg_2D00_1_2D00_18_2D00_12_2D00_4.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0508.hsg_2D00_1_2D00_18_2D00_12_2D00_4.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There we go. Now we are ready to jump back into working with updates.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try this again&amp;hellip;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$updates = $wsus.GetUpdates()&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/6763.hsg_2D00_1_2D00_18_2D00_12_2D00_5.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6763.hsg_2D00_1_2D00_18_2D00_12_2D00_5.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s more like it. Now I have over 5500 updates to work with.&lt;/p&gt;
&lt;p&gt;As you can see, calling &lt;b&gt;GetUpdates()&lt;/b&gt; will get every single update on the server. But, what if we only want to get a specific update or updates? Instead of getting all of the updates and using &lt;b&gt;Where-Object&lt;/b&gt; to filter them, you can use one of the following methods to accomplish that goal. (By the way, there is one more thing that we can use with &lt;b&gt;GetUpdates()&lt;/b&gt; to get specific updates, but I am leaving that piece out until later in the week.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;$wsus.GetUpdate()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This method is quick to get the update that you are looking for. The only issue is that this method requires you to know the update ID, which is a GUID. Not exactly something a person will know off of the top of one&amp;rsquo;s head, but it is an option regardless.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$wsus.GetUpdate([guid]&amp;rdquo; fc08b450-6bdd-400e-9a1a-2f86e23ce462&amp;rdquo;)&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/0412.hsg_2D00_1_2D00_18_2D00_12_2D00_6.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0412.hsg_2D00_1_2D00_18_2D00_12_2D00_6.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, on to the last way to get more specific updates&amp;mdash;this time using the following method:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;SearchUpdates()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This method is very flexible to use because it only requires a string for input. This string can be anything from the KB number for the patch, the actual patch name, or even something as simple as the type of system that the patch would be installed on (such as Exchange Server). Let&amp;rsquo;s look at a few examples of performing some searches:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$SQL = $wsus.SearchUpdates(&amp;lsquo;SQL&amp;rsquo;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$SQL.count&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$SQL | Select Title&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/0508.hsg_2D00_1_2D00_18_2D00_12_2D00_7.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/0508.hsg_2D00_1_2D00_18_2D00_12_2D00_7.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update = $wsus.SearchUpdates(&amp;#39;943485&amp;#39;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update.count&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update | Select Title&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/7457.hsg_2D00_1_2D00_18_2D00_12_2D00_8.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/7457.hsg_2D00_1_2D00_18_2D00_12_2D00_8.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$patches = $wsus.SearchUpdates(&amp;lsquo;Windows 7&amp;rsquo;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$patches.count&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$patches | Select Title&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/6330.hsg_2D00_1_2D00_18_2D00_12_2D00_9.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6330.hsg_2D00_1_2D00_18_2D00_12_2D00_9.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that we know how to find updates on the WSUS server, we can start to explore the update object (&lt;b&gt;Microsoft.UpdateServices.Internal.BaseApi.Update&lt;/b&gt;).&lt;/p&gt;
&lt;p&gt;There quite a few methods that are available for the update object, so we will focus on three methods that are pretty useful for administering updates on the server.&lt;/p&gt;
&lt;h3&gt;Accepting license agreements&lt;/h3&gt;
&lt;p&gt;You might be asking me why accepting license agreements would be one of the three things that I would want to focus on. Well, this is not an issue&amp;hellip;until it becomes an issue when you are trying to approve an update. There is a property that has a Boolean value called &lt;b&gt;RequireLicenseAgreementAcceptance&lt;/b&gt; that we can use in our filtering to locate any updates that require a license acceptance before you can approve the updates.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$license = $updates | Where {$_.RequiresLicenseAgreementAcceptance}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$license | Select Title&lt;/p&gt;
&lt;p&gt;We can use the method &lt;b&gt;AcceptLicenseAgreement()&lt;/b&gt; to accept the agreement for the update.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$license | ForEach {$_.AcceptLicenseAgreement()}&lt;/p&gt;
&lt;p&gt;With that, all of the updates that had a requirement to accept a license agreement have been taken care of, allowing us to start approving some updates!&lt;/p&gt;
&lt;h3&gt;Approving updates&lt;/h3&gt;
&lt;p&gt;There are three ways that you can approve updates on the WSUS server by using PowerShell&amp;mdash;one by using &lt;b&gt;ApproveForOptionalInstall()&lt;/b&gt; and two by using &lt;b&gt;Approve()&lt;/b&gt;. They require that we use the TargetGroup object to tell the server what group we will approve each update for. Yesterday, I talked about how to get a target group; now we can easily grab a group to use for each type of approval. The &lt;b&gt;Approve&lt;/b&gt; method also requires that you pick an installation action (I will go into more detail when we get to that method).&lt;/p&gt;
&lt;p&gt;The main difference between &lt;b&gt;ApproveForOptionalInstall&lt;/b&gt; and &lt;b&gt;Approve&lt;/b&gt; is that &lt;b&gt;ApproveForOptionalInstall&lt;/b&gt; will approve the update for the target group, but the update will not actually install. However, it is made available to the user for installation via &lt;b&gt;Add/Remove Programs&lt;/b&gt;. &lt;b&gt;Approve&lt;/b&gt; will approve the update with or without a deadline (your choice&amp;mdash;I will explain later how to do this).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with the optional installation first&amp;hellip;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update = $wsus.SearchUpdates(&amp;#39;Windows 7 for x64-based Systems (KB2639417)&amp;#39;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$group = $wsus.GetComputerTargetGroups() | where {$_.Name -eq &amp;#39;TESTGROUP&amp;#39;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update[0].ApproveForOptionalInstall($Group)&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/2626.hsg_2D00_1_2D00_18_2D00_12_2D00_10.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/2626.hsg_2D00_1_2D00_18_2D00_12_2D00_10.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here I approved a Windows&amp;nbsp;7 update for my TESTGROUP in which my laptop is currently a member. Notice that it returns another object called &lt;b&gt;Microsoft.UpdateServices.Internal.BaseApi.UpdateApproval&lt;/b&gt;. This object tells you when it was approved, the time that the update will &amp;ldquo;go live,&amp;rdquo; and who approved the update. It is important to note that the update object you get is a collection, even if you only get one item back. Therefore, I had to be sure to use the first index of the collection to use this method for approval.&lt;/p&gt;
&lt;p&gt;By using &lt;b&gt;Approve()&lt;/b&gt; method, we have two ways in which to approve the updates. Both require that you have the target group object, but one also has the requirement of setting a deadline by using the &lt;b&gt;[datetime]&lt;/b&gt; object.&lt;/p&gt;
&lt;p&gt;Do you remember when I mentioned using an installation action for the approval? Well, now it is time to use one of those actions for this approval. But how do we know what installation actions we can use? We will find out what our options are by using&lt;b&gt; Microsoft.UpdateServices.Administration.UpdateApprovalAction&lt;/b&gt;.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;[Microsoft.UpdateServices.Administration.UpdateApprovalAction] | gm -static -Type Property | Select &amp;ndash;expand Name&lt;/p&gt;
&lt;p&gt;The installation actions that are returned are:&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;b&gt;All&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;b&gt;Install&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;b&gt;NotApproved&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;b&gt;Uninstall&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now that we know what kinds of actions we can use, let&amp;rsquo;s make an approval without using a deadline.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update = $wsus.SearchUpdates(&amp;lsquo;Update for 2007 Microsoft Office System (KB932080)&amp;#39;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$group = $wsus.GetComputerTargetGroups() | where {$_.Name -eq &amp;#39;TESTGROUP&amp;#39;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update[0].Approve(&amp;ldquo;Install&amp;rdquo;,$Group)&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/6170.hsg_2D00_1_2D00_18_2D00_12_2D00_11.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6170.hsg_2D00_1_2D00_18_2D00_12_2D00_11.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Again, the same object type is returned with the same data that we would expect.&lt;/p&gt;
&lt;p&gt;We can set a deadline on our next update for approval. Basically, setting a deadline on a patch will force that update to be installed at that specific time. For instance, I will approve an update that will get installed on Dec. 15 at 11:00 PM.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update = $wsus.SearchUpdates(&amp;lsquo;932080&amp;rsquo;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$group = $wsus.GetComputerTargetGroups() | where {$_.Name -eq &amp;#39;TESTGROUP&amp;#39;}&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update[0].Approve(&amp;ldquo;Install&amp;rdquo;,$Group,[datetime]&amp;rdquo;12/15/2011 11:00PM&amp;rdquo;)&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/6735.hsg_2D00_1_2D00_18_2D00_12_2D00_12.jpg"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-76-18/6735.hsg_2D00_1_2D00_18_2D00_12_2D00_12.jpg" alt="Image of command output" title="Image of command output" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice that the &lt;b&gt;Deadline&lt;/b&gt; is set to the time that I specified instead of it being way out in the year 9999. Now the update will install on the server at that specific time without manual intervention.&lt;/p&gt;
&lt;p&gt;You might be asking, &amp;ldquo;How were you able to determine what updates were required by your systems?&amp;rdquo; Well, besides jumping into the WSUS Administration Console to view those updates, there is another way that I can locate updates, but that will have to wait until later this week when I introduce another object and way to search for updates.&lt;/p&gt;
&lt;h3&gt;Declining an update&lt;/h3&gt;
&lt;p&gt;So we have approved updates, but we also need to know how to decline updates that are not needed by any system or are deemed unneeded by us for various reasons. Luckily, declining an update is as simple as using the &lt;b&gt;Decline() &lt;/b&gt;method.&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update = $wsus.SearchUpdates(&amp;lsquo;932080&amp;rsquo;)&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;$update[0].Decline()&lt;/p&gt;
&lt;p&gt;Unlike the approvals, no object is returned when you decline an update. Regardless, this is a simple and effective way to decline updates that you do not need.&lt;/p&gt;
&lt;p&gt;That wraps it up for today&amp;rsquo;s blog focusing on update management by using Windows PowerShell. Although I really only scratched the surface of working with updates, I hope I was able to give you enough information to make the leap into patch management using Windows PowerShell. Tomorrow I will dive into working with the computer scope object and how you can use that object with some of the objects we have seen this week and some of their associated methods that only accept the computer scope object.&lt;/p&gt;
&lt;p&gt;~Boe&lt;/p&gt;
&lt;p&gt;Boe, thank you once again for a very useful and informative blog about using Windows PowerShell and WSUS. WSUS Week will continue tomorrow.&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=3474817" width="1" height="1" alt="" /&gt;</description></item></channel></rss>