{"id":54223,"date":"2009-03-10T21:21:00","date_gmt":"2009-03-10T21:21:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/03\/10\/hey-scripting-guy-how-can-i-tell-which-software-updates-are-available-via-windows-update\/"},"modified":"2009-03-10T21:21:00","modified_gmt":"2009-03-10T21:21:00","slug":"hey-scripting-guy-how-can-i-tell-which-software-updates-are-available-via-windows-update","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-tell-which-software-updates-are-available-via-windows-update\/","title":{"rendered":"Hey, Scripting Guy! How Can I Tell Which Software Updates Are Available Via Windows Update?"},"content":{"rendered":"<h2><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Question\" border=\"0\" title=\"Hey, Scripting Guy! Question\" class=\"nearGraphic\" \/> <\/h2>\n<p>Hey, Scripting Guy! I am curious about the updates that are available from Windows Update. The whole process seems so nebulous. It is like some kind of Impressionist painting that suggests things, but I never really get a feel for the updates that are coming down or the ones that are available. I like having a better handle on things than this. Do you have a script that will tell me which software updates are available via Windows Update? If I could see the list, then I would understand better what is really going on. Does this make sense?<\/p>\n<p>&#8211; TC<\/p>\n<p><img decoding=\"async\" height=\"5\" width=\"5\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" alt=\"Spacer\" border=\"0\" \/><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Answer\" border=\"0\" title=\"Hey, Scripting Guy! Answer\" class=\"nearGraphic\" \/><\/p>\n<p>Hi TC,<\/p>\n<p>Sure it makes sense. Incidentally, I love the <a target=\"_blank\" href=\"http:\/\/au.encarta.msn.com\/encyclopedia_761553672\/Impressionism_(art).html\">Impressionists<\/a>, who were as it turns out named after a Claude Monet painting &#8220;Impression, soleil levant de retour.<a href=\"http:\/\/blogs.technet.com\/controlpanel\/blogs\/posteditor.aspx\/&quot;Impression, soleil levant de retour.&quot;\">&#8221; <\/a>Like the interplay between the light and the shadows that enthralled the Impressionists, these are the kinds of questions that I hate to get sometimes. Why? Well, I do not want to be like a lot of people who might say, &#8220;Why would you want to do that?&#8221; I figure, hey, you are an adult (perhaps) and if you want to do something, go ahead and do it if you wish. Anyway, we can certainly create a script that will return all the software updates from the Windows Update Web site. What you decide to do with such a list is up to you. We will call the script, <strong>ListSoftwareUpdates.ps1<\/strong>, and I can write that script in three lines. (Actually, I can write the script in a single line. I just prefer the three-line version for readability.)<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EDD\">\n<thead><\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">This week we will be looking at using the Windows Update API to work with Windows Update. The Windows Update API is documented <a target=\"_blank\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa387099.aspx\">on MSDN<\/a>. There is also a good collection of VBScripts that use the Windows Update API in the <a target=\"_blank\" href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\">Script Center Script Repository<\/a>. For information about manually configuring Windows Update on workstations, refer to <a target=\"_blank\" href=\"http:\/\/www.microsoft.com\/windows\/downloads\/windowsupdate\/learn\/windowsvista.mspx\">this page<\/a>. These scripts use Windows PowerShell. <a target=\"_blank\" href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\">The Windows PowerShell getting started page<\/a> has basic information for learning about Windows PowerShell and about downloading Windows PowerShell.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>For a VBScript version of the <strong>ListSoftwareUpdates.ps1 script<\/strong>, check the <a target=\"_blank\" href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\">Script Center Script Repository<\/a>. The complete <strong>ListSoftwareUpdates.ps1<\/strong> script is seen here.<\/p>\n<pre class=\"codeSample\">$Searcher = New-Object -ComObject Microsoft.Update.Searcher\n$Results = $Searcher.Search(\"Type='Software'\")\n$Results.Updates\n<\/pre>\n<p>The script begins by creating a COM object. To do this, we use the <strong>New-Object<\/strong> cmdlet with the <strong>&ndash;ComObject<\/strong> parameter. We do not need to surround the program ID of the COM object in quotation marks because the <strong>&ndash;ComObject<\/strong> parameter already expects a string. We store the returned <strong>Searcher<\/strong> object (<strong>IUpdateSearcher<\/strong> interface) in the <strong>$Searcher<\/strong> variable. The line of the <strong>ListSoftwareUpdates.ps1 <\/strong>script that creates the <strong>Searcher<\/strong> object is seen here:<\/p>\n<pre class=\"codeSample\">$Searcher = New-Object -ComObject Microsoft.Update.Searcher<\/pre>\n<p>The <strong>Searcher<\/strong> object can do more than just search for updates on the server; it can also query the history, get the history count, and do other things. The members of the <strong>Searcher<\/strong> object are seen in <strong>Table 1<\/strong>.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EPF\">\n<thead>\n<tr>\n<td colspan=\"3\" class=\"tableHeader\">Table 1 Members of the Searcher object<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"stdHeader\">\n<td id=\"colESF\">Name<\/td>\n<td id=\"colEWF\">Type<\/td>\n<td id=\"colE1F\">Definition<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">BeginSearch<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">ISearchJob BeginSearch (strin<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">EndSearch<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">ISearchResult EndSearch (ISea<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">EscapeString<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">string EscapeString (string)<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">GetTotalHistoryCount<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">int GetTotalHistoryCount ()<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">QueryHistory<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IUpdateHistoryEntryCollection<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">Search<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">ISearchResult Search (string)<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">CanAutomaticallyUpgradeService<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">bool CanAutomaticallyUpgradeS<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">ClientApplicationID<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">string ClientApplicationID ()<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">IgnoreDownloadPriority<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">bool IgnoreDownloadPriority (<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">IncludePotentiallySupersededUpdates<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">bool IncludePotentiallySupers<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">Online<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">bool Online () {get} {set}<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">SearchScope<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">SearchScope SearchScope () {g<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">ServerSelection<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">ServerSelection ServerSelecti<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">ServiceID<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">string ServiceID () {get} {set}<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>Because we are interested in searching for all the software updates, we use the <strong>Search<\/strong> method. The custom search language that is used with the <strong>Search<\/strong> method is documented <a target=\"_blank\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa386526(VS.85).aspx\">on MSDN<\/a>. Basically it consists of a property and an associated value for that property. In the <strong>ListSoftwareUpdates.ps1<\/strong> script, we are looking for a search result type that is equal to <strong>Software<\/strong>. This line of the script is seen here:<\/p>\n<pre class=\"codeSample\">$Results = $Searcher.Search(\"Type='Software'\")<\/pre>\n<p>The custom search language that is used with the <strong>Search<\/strong> method allows us to use the <strong>and<\/strong> operator and the <strong>or<\/strong> operator. If we wanted to find software updates that were not installed, we could use this line of code:<\/p>\n<pre class=\"codeSample\">$results = $searcher.search(\"Type='software' AND IsInstalled = 0\")<\/pre>\n<p>Tthe MSDN documentation for the <strong>Search<\/strong> method tells us that the <strong>IsInstalled<\/strong> property is an integer (Boolean) value. The search criteria produces an error when I try to use <strong>$true<\/strong> or <strong>$false<\/strong>. This means we are back to the old-fashioned days of using 0 for <strong>false<\/strong> and 1 for <strong>true<\/strong> (it will not even accept -1).<\/p>\n<p>The <strong>$results<\/strong> variable contains a <strong>Results<\/strong> object (the ISearchResult Interface is <a target=\"_blank\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa386077(VS.85).aspx\">documented here<\/a>). This object consists of four properties, which are seen in <strong>Table 2<\/strong>.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EEDAC\">\n<thead>\n<tr>\n<td colspan=\"3\" class=\"tableHeader\">Table 2 SearchResult object members<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"stdHeader\">\n<td id=\"colEHDAC\">Name<\/td>\n<td id=\"colELDAC\">Type<\/td>\n<td id=\"colEPDAC\">Definition<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">ResultCode<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">OperationResultCode ResultCode () {get}<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">RootCategories<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">ICategoryCollection RootCategories () {get}<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">Updates<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IUpdateCollection Updates () {get}<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">Warnings<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Property<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IUpdateExceptionCollection Warnings () {get}<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>In today&rsquo;s script we are interested in the collection of software updates that is obtained by querying the <strong>Updates<\/strong> property. When we do this, all of the software updates are listed as seen here:<\/p>\n<p><img decoding=\"async\" height=\"424\" width=\"500\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0310\/hsg-3-10-9-1.jpg\" alt=\"Image of the listing of all software updates\" border=\"0\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>The line of code that displays all the software updates is seen here.<\/p>\n<pre class=\"codeSample\">$Results.Updates<\/pre>\n<p>Here is a bonus script. The <strong>DisplayTheSoftwareUpdateSettingsDialogBox.ps1<\/strong> script uses the <strong>Microsoft.Update.AutoUpdate<\/strong> COM object to show the settings dialog box. To do this, we use the <strong>New-Object<\/strong> cmdlet and specify the <strong>&ndash;ComObject<\/strong> parameter and supply the <strong>Microsoft.Update.AutoUpdate<\/strong> program ID. We put the <strong>New-Object<\/strong> command inside a pair of parentheses and call the <strong>ShowSettingsDialog<\/strong> method as seen here. The complete <strong>DisplayTheSoftwareUpdateSettingsDialogBox.ps1<\/strong> script is seen here (the VBScript version of this script can be seen in the <a target=\"_blank\" href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/sus\/client\/suclvb01.mspx\">Script Center Script Repository<\/a>):<\/p>\n<pre class=\"codeSample\">(New-Object -ComObject Microsoft.Update.AutoUpdate).ShowSettingsDialog()<\/pre>\n<p>When the script is run, it produces the dialog box seen here:<\/p>\n<p><img decoding=\"async\" height=\"379\" width=\"476\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0310\/hsg-3-10-9-2.jpg\" alt=\"Image of the dialog box that appears when the bonus script is run\" border=\"0\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Well, TC, that is about all there is to searching for specific types of software updates. And you even got a bonus script out of it. I hope this removes some of the mystery from the Windows Update process. Join us tomorrow when we will continue looking at managing Windows Update. Until then, peace.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I am curious about the updates that are available from Windows Update. The whole process seems so nebulous. It is like some kind of Impressionist painting that suggests things, but I never really get a feel for the updates that are coming down or the ones that are available. I like having [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[36,3,45,380],"class_list":["post-54223","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-client-side-management","tag-scripting-guy","tag-windows-powershell","tag-windows-update"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I am curious about the updates that are available from Windows Update. The whole process seems so nebulous. It is like some kind of Impressionist painting that suggests things, but I never really get a feel for the updates that are coming down or the ones that are available. I like having [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54223","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54223"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54223\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}