{"id":54203,"date":"2009-03-12T21:22:00","date_gmt":"2009-03-12T21:22:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/03\/12\/hey-scripting-guy-how-can-i-remove-a-microsoft-update\/"},"modified":"2009-03-12T21:22:00","modified_gmt":"2009-03-12T21:22:00","slug":"hey-scripting-guy-how-can-i-remove-a-microsoft-update","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-remove-a-microsoft-update\/","title":{"rendered":"Hey, Scripting Guy! How Can I Remove a Microsoft Update?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> <\/H2>\n<P>Hey, Scripting Guy! You are not going to believe this. We recently deployed a Microsoft Update, and it is not working well for us. I tested it, of course, but for some reason it is not playing well with our systems. I now need to determine what the problem is, but in the meantime, I want to remove the update from all our systems. How can I write a script that will remove the Microsoft Update?<BR><BR>&#8211; MC<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hi MC,<\/P>\n<P>I am listening to the <A href=\"http:\/\/en.wikipedia.org\/wiki\/Buena_Vista_Social_Club_%28album%29\" target=\"_blank\">Buena Vista Social Club<\/A> on my Zune. It does not matter how many times I listen to this album\u2014man, it is sweet. The <A href=\"http:\/\/www.pbs.org\/buenavista\/\" target=\"_blank\">documentary<\/A> is pretty good as well. It is cold and dreary outside, but the music warms my spirits like a day lying on the beach in late summer. <\/P>\n<P>Oh, you would like to know how to uninstall an update. This is going to be a different kind of article today. The reason is that the script I am going to show you does not work for me. There is really not too much funny for me to say about this, because I am rather annoyed to be perfectly frank (or Ed). I spent more than five hours on this script, and in the end I do not think I would have been able to figure out the problem, if it had not been for having access to our internal support case files. In the hopes that I will save you the same frustration, we will go through the script. It is possible the script will work if you use it to uninstall an update that was deployed from a Microsoft Windows Server Update Services (WSUS) server, but I do not have one stuck under my desk, so I cannot test it.<\/P>\n<TABLE id=\"EBD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\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 href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa387099.aspx\" target=\"_blank\">on MSDN<\/A>. There is also a good collection of VBScripts that use the Windows Update API in the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\" target=\"_blank\">Script Center Script Repository<\/A>. For information about manually configuring Windows Update on workstations, refer to <A href=\"http:\/\/www.microsoft.com\/windows\/downloads\/windowsupdate\/learn\/windowsvista.mspx\" target=\"_blank\">this page<\/A>. These scripts use Windows PowerShell. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\" target=\"_blank\">The Windows PowerShell getting started page<\/A> has basic information for learning about Windows PowerShell and about downloading Windows PowerShell.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>The <B>UninstallUpdate.ps1<\/B> script is seen here (a VBScript version of this script is in the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\" target=\"_blank\">Script Center Script Repository<\/A>):<\/P><PRE class=\"codeSample\">$UpdateCollection = New-Object -ComObject Microsoft.Update.UpdateColl\n$Searcher = New-Object -ComObject Microsoft.Update.Searcher<\/p>\n<p>$updateID = &#8220;71535ae5-039f-482c-b242-6c5046414edf&#8221;\n$Result = $Searcher.Search(&#8220;UpdateID=&#8217;$updateID'&#8221;)\n$Updates = $Result.updates\n$updates\n&#8220;update count &#8221;  + $Updates.Count\n$UpdateCollection.Add($Updates.Item(0))\n&#8220;Collection count &#8221; + $UpdateCollection.Count<\/p>\n<p>$Installer = New-Object -ComObject Microsoft.Update.Installer\n$Installer.Updates = $UpdateCollection\n$installer\n$Installer.UnInstall()<\/PRE>\n<P>First the nitty-gritty details. After writing the <B>UninstallUpdate.ps1<\/B> script, an error is returned when the script is run (the same is true of the VBScript version). The error that is returned is <B>HResult 0x80240028<\/B>. <B>HResults<\/B> can be looked up directly in the <A href=\"http:\/\/technet.microsoft.com\/en-us\/library\/cc720442.aspx\" target=\"_blank\">MSDN documentation<\/A>. The result string is <B>WU_E_UNINSTALL_NOT_ALLOWED<\/B>. The description for the <B>HResult<\/B> is this: \u201cThe update could not be uninstalled because the request did not originate from a WSUS server.\u201d The error message itself is seen here:<\/P><IMG border=\"0\" alt=\"Image of the error message\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0312\/hsg-3-12-9-1.jpg\" width=\"668\" height=\"199\"> \n<P>&nbsp;<\/P>\n<P>So is the resolved error description right or not? It might be true, or it might not be true. I installed the update via the Microsoft Update Service on the Web. Does this use WSUS? Maybe the error is one of those bogus errors? After several hours of frustrated experimentation, I can assure you it is not a bogus error. The error in fact means exactly what it says: It cannot uninstall the update because the update was not installed via a WSUS server. The computer is considered to be an unmanaged workstation, and therefore the <B>Uninstall<\/B> method will not work. There is actually code that is used to inspect the workstation before calling the <B>Uninstall<\/B> method. <\/P>\n<P>Remember the trick <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/mar09\/hey0311.mspx\" target=\"_blank\">yesterday<\/A> we used to gain more information about an error we were receiving? We looked in the System log of the Event Viewer. Well there are no errors in the Event Viewer related to this script. Bummer! Well, there is the <A href=\"http:\/\/support.microsoft.com\/kb\/902093\" target=\"_blank\">Windows Update log file<\/A>. Actually there may be two Windows Update log files; both found in the system root directory (C:\\Windows).The first is the <B>Windows Update.Log<\/B> (it has a space in the name) file which is seen here:<\/P><IMG border=\"0\" alt=\"Image of the Windows Update.Log\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0312\/hsg-3-12-9-2.jpg\" width=\"562\" height=\"163\"> \n<P>&nbsp;<\/P>\n<P>The contents of the <B>Windows Update.Log<\/B> file (with a space in the name) are sub-enthralling. The <B>Windows Update.Log<\/B> file you want to look at is the one <I>without<\/I> a space in the name: <B>WindowsUpdate.Log<\/B>. As seen in the next image, there is very detailed information related to each method call. In the log, the items that are listed as coming from COMAPI are related to actions arising from the script. You can see it performs a search, finds a single update, and then calls the <B>Uninstall<\/B> method. At this point, the exit code is the same one that we received from within the Windows PowerShell console. <\/P><IMG border=\"0\" alt=\"Image of the detailed information related to each method call\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0312\/hsg-3-12-9-3.jpg\" width=\"789\" height=\"553\"> \n<P>&nbsp;<\/P>\n<P>The <B>UninstallUpdate.ps1<\/B> script begins by creating a couple of objects. The <B>Microsoft.Update.UpdateColl<\/B> object and the <B>Microsoft.Update.Searcher<\/B> object were discussed in <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/mar09\/hey0311.mspx\" target=\"_blank\">yesterday\u2019s \u201cHey, Scripting Guy!\u201d article<\/A>.<\/P>\n<P>After the <B>UpdateColl<\/B> and the <B>Searcher<\/B> objects are created, we specify the <B>updateID<\/B> and use the <B>Searcher<\/B> object to locate that particular update. The <B>Result<\/B> object contains a collection of update objects that are added to the <B>UpdateColl<\/B> object. (Again, all this was discussed in yesterdays Hey Scripting Guy! article.) This section of the code is seen here:<\/P><PRE class=\"codeSample\">$UpdateCollection = New-Object -ComObject Microsoft.Update.UpdateColl\n$Searcher = New-Object -ComObject Microsoft.Update.Searcher<\/p>\n<p>$updateID = &#8220;71535ae5-039f-482c-b242-6c5046414edf&#8221;\n$Result = $Searcher.Search(&#8220;UpdateID=&#8217;$updateID'&#8221;)\n$Updates = $Result.updates\n$updates\n&#8220;update count &#8221;  + $Updates.Count\n$UpdateCollection.Add($Updates.Item(0))\n&#8220;Collection count &#8221; + $UpdateCollection.Count\n<\/PRE>\n<P>Now we need to create the <B>Installer<\/B> object, add the <B>UpdateCollection<\/B> to the <B>Updates<\/B> property and call the <B>Uninstall<\/B> method. This section of code is similar to the code we used in yesterdays article: <\/P><PRE class=\"codeSample\">$Installer = New-Object -ComObject Microsoft.Update.Installer\n$Installer.Updates = $UpdateCollection\n$installer\n$Installer.UnInstall()\n<\/PRE>\n<P>Well, MC, that is the way it goes sometimes when you are writing scripts. There are some things that should be easy, and then they end up taking a really long time. If you noticed, there is something like one line of difference between today&#8217;s script and yesterday&#8217;s script. I was hoping to get off easy today, but it did not work out like that. The good news is that tomorrow is Quick-Hits Friday! Woohoo! We love Quick-Hits Friday. Like a box of chocolates, you never know what you\u2019re gonna get. See you tomorrow. Take care. <\/P>\n<P>&nbsp;<\/P>\n<P><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! You are not going to believe this. We recently deployed a Microsoft Update, and it is not working well for us. I tested it, of course, but for some reason it is not playing well with our systems. I now need to determine what the problem is, but in the meantime, I [&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-54203","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! You are not going to believe this. We recently deployed a Microsoft Update, and it is not working well for us. I tested it, of course, but for some reason it is not playing well with our systems. I now need to determine what the problem is, but in the meantime, I [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54203","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=54203"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54203\/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=54203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}