Downloading updates from Microsoft Update Catalog RRS feed

  • Question

  • Hi all,

    i found the script below and it works fine for me. Only some updates are failing. For example KB4054534.

    This happens when there is more than one result on the download page and this script dont seems to handle this.

    Maybe a loop round about this line is missing:

    $DirectDownloadLink=[regex]::Match($IEDownloadWindow.document.documentElement.innerHTML, "(?s)(?<=url \= ')(.+?)(?=';)").value.trim() 

    But i am not sure about that :-(

    Due to the fact that i will never understand regex expressions i could need some help from any expert to complete this.

    You find the whole Script below. To get it generally working you have to goto https://www.catalog.update.microsoft.com once and install the activeX plugin manually.

    Thank you all



    function Get-UpdateFromCatalog { 
                Get the specified Windows update details. 
                For that it generates COM IE windows, and parses the source code of the generated web pages. 
                The 'Microsoft Update Catalog' ActiveX (http://www.catalog.update.microsoft.com/Search.aspx) must be already installed. 
                Script should not be called twice at the same server due it will cause issues identifying child IE opened sessions. 
                Script cannot handle more than 25 results (1 search page output) 
            .PARAMETER Name 
                (Mandatory) Name of the item to look for. It can be a product, KB title or number. 
                Multiple values can be provided 
            .PARAMETER DownloadFolder 
                If specified, the installers will be downloaded to '<specified folder>\<kb title>\<installer>' 
                PS> Get-UpdateFromCatalog -Name "3197867","KB3197876" -verbose | out-gridview 
                PS> Get-UpdateFromCatalog -Name "3197867","KB3197876" -DownloadFolder ".\DownloadedPatches" -verbose  
        param ( 
        ## Closes any previous IE popup 
        (New-Object -ComObject Shell.Application).Windows() | Where-Object {$_.LocationUrl -like "*catalog.update.microsoft.com/*DownloadDialog.aspx*"} | foreach-object { $_.Quit() } 
        ## Adds '*.update.microsoft.com to the list of Trusted sites to be able to allow popups from it and get the 'direct link' 
        New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\EscDomains\microsoft.com\*.update" -Name "https" -Value 2 -Type DWORD -Force | Out-null 
        New-ItemProperty -Path "HKCU:\Software\Microsoft\Internet Explorer\New Windows\Allow" -Name '*.update.microsoft.com' -Value "0" -Type Binary -Force | Out-Null 
        Foreach ($Item in $Name) { 
            $URL='http://www.catalog.update.microsoft.com/Search.aspx?q=' + $Item.replace(' ','%20') 
            #"Suche nach: " + $Item
            #write-verbose " * Get-UpdateFromCatalog: Search url: `n $URL" 
            $WebClient = New-Object System.Net.WebClient 
            $WebClient.Encoding = [System.Text.Encoding]::UTF8 
            do { 
                try {  
                    $Content = $null 
                    $Content = $WebClient.DownloadString($URL) 
                } catch {} 
            } while (-not ($Result)) 
            if ($Content -match '(?s)(?<=>We did not find any results for)(.+?)(?=<\/span>)') {  
                write-warning "No results were found. Try using another search criteria..." 
                return $Null 
            } ## 25 is the max amount of rows in a page 
            try { 
                $Temp=([regex]::Match($Content, '(?s)(?<=searchDuration">)(.+?)(?=<\/span>)')).value.trim().tostring().split(' ') | where { $_ } 
            } catch {} 
            if ($Results -gt 25) { write-warning "Your search returned $($Results) results, but no more than 25 will be handled by the script. Try using another search criteria..."} ## 25 is the max amount of rows in a page 
            $Items=[regex]::Matches($Content, '(?s)<tr id=(.|\n)*?<\/tr>') | foreach-object { $_.Groups[0].Value } 
            foreach ($Item in $Items) { 
                $UpdateID=([regex]::Match($item, '(?s)(?<=<input id=")(.+?)(?=")')).value.trim() 
                ####### Get Update additional information 
                $URL='http://www.catalog.update.microsoft.com/ScopedViewInline.aspx?updateid=' + $UpdateID 
                write-verbose " * Get-UpdateFromCatalog: Getting additional update information from: `n $URL" 
                $ie = New-Object -ComObject InternetExplorer.Application  
                $ie.Navigate2($URL, "0x1000") 
                $ie.Visible = $False 
                while( $ie.busy){Start-Sleep 1} 
                try { 
                    [array]$SupersedesBy=[regex]::Match($ie.document.documentElement.innerHTML, "(?s)(?<=supersededbyInfo\>)(.+?)(?=<SPAN id\=)").value.trim() | foreach-object { 
                        ([regex]::Matches($_, '(?s)(?<="\>)(.+?)(?=<\/DIV>)')).Groups[1].Value.trim() | foreach-object { 
                            ([regex]::Match($_, '(?s)(?<="\>)(.+?)(?=<)')).value.trim()  
                } catch {} 
                try { 
                    [array]$Supersedes=[regex]::Match($ie.document.documentElement.innerHTML, "(?s)(?<=supersedesInfo\>)(.+?)(?=<DIV id\=)").value.trim() | foreach-object { 
                        [regex]::Matches($_, '(?s)(?<="\>)(.+?)(?=<\/DIV>)') | foreach-object {  
                } catch {} 
                ####### Get Update direct download link 
                $URL='http://catalog.update.microsoft.com/?updateid=' + $UpdateID 
                write-verbose " * Get-UpdateFromCatalog: Getting direct download link from: `n $URL" 
                $ie = New-Object -ComObject InternetExplorer.Application  
                $ie.Navigate2($URL, "0x1000") 
                $ie.Visible = $False 
                while( $ie.busy){Start-Sleep 1}  
                $DownloadBTN = $ie.Document.getElementsByName("downloadButton") | Where-Object {$_.Type -eq 'button'}  
                $IEDownloadWindow = (New-Object -ComObject Shell.Application).Windows() | Where-Object {$_.LocationUrl -like "*catalog.update.microsoft.com/*DownloadDialog.aspx*"} 
                $IEDownloadWindow.Visible = $False 
                while( $IEDownloadWindow.busy){Start-Sleep 1}  
                $DirectDownloadLink=[regex]::Match($IEDownloadWindow.document.documentElement.innerHTML, "(?s)(?<=url \= ')(.+?)(?=';)").value.trim() 
                $Obj = New-Object -TypeName PSObject -Property (@{ 
                    'Title'=[regex]::Match($item, '(?s)(?<=<a id=)(.+?)(?=<\/a>)').value.split('>')[-1].trim() 
                    'Products'=[regex]::Match($item, '(?s)(?<=_C2_)(.+?)(?=<\/td>)').value.split('>')[-1].trim() 
                    'Classification'=[regex]::Match($item, '(?s)(?<=_C3_)(.+?)(?=<\/td>)').value.split('>')[-1].trim() 
                    'LastUpdated'=[regex]::Match($item, '(?s)(?<=_C4_)(.+?)(?=<\/td>)').value.split('>')[-1].trim() 
                    'Version'=[regex]::Match($item, '(?s)(?<=_C5_)(.+?)(?=<\/td>)').value.split('>')[-1].trim() 
                    'Size'=[regex]::Match($item, '(?s)(?<=size">)(.+?)(?=<\/span>)').value.trim() 
                    'CatalogURL'='http://catalog.update.microsoft.com/?updateid=' + $UpdateID 
                ## To have PS object sorted 
                $Report+=$Obj | select Title, Products, Classification, LastUpdated, Version, Size, CatalogURL, DirectDownloadLink, Supersedes, SupersedesBy 
        ##### Download section 
        if ($DownloadFolder) 

            #write-verbose " * Get-UpdateFromCatalog: Attemping to download files..." 
            if (-not (Test-Path $DownloadFolder)) { 
                #write-verbose " * Get-UpdateFromCatalog: Creating folder ""$($DownloadFolder)""..." 
                $DownloadFolderPath=New-Item $DownloadFolder -Type "Directory" -Confirm:$False -Force | foreach-object { $_.Fullname } 
            } else { $DownloadFolderPath=get-item $DownloadFolder | foreach-object { $_.Fullname } } 
            foreach ($Item in $Report) 
                    #"Found object for download..."
                    $SubFolder=New-Item "$($DownloadFolderPath)\$($Item.Title)" -Type "Directory" -Confirm:$False -Force | foreach-object { $_.Fullname }
                    $global:DLFile = $FileName
                    #write-verbose " * Get-UpdateFromCatalog: Downloading ""$Url"" to ""$FileName""..." 
                    try { (new-object System.Net.WebClient).DownloadFile($Url,$FileName)  
                    } catch { write-error "$(Get-Date -Format o) - Get-MBSAMissingUpdates: $_" }
                    if (Test-Path  ($FileName))
                        $TestFile = $FileName.IndexOf(".cab")
                        If ($TestFile -gt 0) 
                        $Subfolder1 = """$SubFolder"""
                        $FileName1 = """$FileName"""
                        Start-Process  -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList "e -y -o$Subfolder1 $FileName1" -Wait
                        Remove-Item -Path $FileName
        #return $Report 

    • Moved by Bill_Stewart Friday, March 15, 2019 6:22 PM This is not "fix/debug/rewrite my script for me" forum
    Saturday, January 19, 2019 6:21 AM

All replies