ryan-jan / MSCatalog

PowerShell module for searching and downloading offline updates from https://www.catalog.update.microsoft.com
MIT License
58 stars 16 forks source link

Sorting for updates in Get-MSCatalogUpdate #6

Closed umaritimus closed 3 years ago

umaritimus commented 3 years ago

Recently, I've noticed that the when you search the catalog, the results don't necessarily come sorted in chronological order, e.g. for Cumulative Update for Windows Server 2019 for x64-based Systems, 2020-10 Cumulative Update (latest) doesn't come in until page 2. It makes it slightly inconvenient and necessitates -AllPages flag:

${Catalog} = Get-MSCatalogUpdate -Search 'Cumulative Update for Windows Server 2019 for x64-based Systems' -AllPages -Strict
${Catalog} = ${Catalog} | Where-Object {$_.Products -eq 'Windows Server 2019'} | Sort-Object -Property Title
${LastUpdate} = ${Catalog} | Select-Object -Last 1
${LastUpdateKB} = ${LastUpdate}.Title | Select-String -Pattern '^.*\((KB\d*)\).*' -AllMatches | ForEach-Object {$_.Matches.Groups[1].Value}
${LastUpdateGuid} = ${LastUpdate}.Guid
New-Item -Type Directory -Path "${Env:Temp}\${LastUpdateKB}" -Force | Out-Null
Save-MSCatalogUpdate -Guid ${LastUpdateGuid} -Destination "${Env:Temp}\${LastUpdateKB}"

Is there a better/faster/less-resource-consuming way of getting the latest cumulative update?

ryan-jan commented 3 years ago

Hi, thanks for taking the time to use this module, and thanks for your feedback! Unfortunately, the issue you describe is due to the way in which the catalog.update.microsoft.com site returns the updates from the search term. If you go to catalog.update.microsoft.com in a web browser and search for Cumulative Update for Windows Server 2019 for x64-based Systems you will see that you also do not get the latest update on the first page of results (only the latest preview) and you would need to sort the table by the Last Updated field in order to see the latest Cumulative Update for Windows Server 2019 for x64-based Systems update. With most search engines you could wrap your search string in quotes to tell the search engine to match the exact string, which would help in this scenario. However, for some reason, the catalog.update.microsoft.com search function does not behave in this way. If you try it in your browser you should see exactly the same results with or without quotes.

The Strict parameter of this module simply filters the results returned from catalog.update.microsoft.com in PowerShell to try and help with this short-coming of the catalog sites functionality. But, as you have found, this means you do need to also apply the AllPages parameter which is far from ideal as it can make multiple requests to the catalog and is time consuming.

In your particular scenario of downloading the latest update, it is actually very trivial to include the YYYY-MM in the search string dynamically, which should limit the search results sufficiently to be able to use the Strict parameter without the AllPages parameter. This should achieve what you are looking for and is actually how I have my automation set up in my day job. So, you could do the following to get the latest update for this month, assuming one has been released.

Get-MSCatalogUpdate "$((Get-Date).ToString('yyyy-MM')) Cumulative Update for Windows Server 2019 for x64-based Systems" -Strict

Title                                                                               Products            Classification   LastUpdated Size
-----                                                                               --------            --------------   ----------- ----
2020-10 Cumulative Update for Windows Server 2019 for x64-based Systems (KB4577668) Windows Server 2019 Security Updates 2020/10/12  368.3 MB

If one has not been released this will just return a warning saying WARNING: We did not find any results for xyz

Please let me know if this helps with you particular issue, and if so I will close this off.

ryan-jan commented 3 years ago

I have investigated this further and, while my previous comment is accurate and the workaround should help you, I have also worked out how to sort the results directly from the catalog site by any field in the table (e.g. Title, Products, LastUpdated etc.). Therefore, I have begun work on a pull request to implement a SortBy paramater for the Get-MSCatalogUpdates command. This will take me some time but will eventually enable greater flexibility in retrieving results from the catalog site without the need to include the AllPages switch, which as we have already mentioned is not great from a performance point of view. I will update this issue with progress.

umaritimus commented 3 years ago

That's very cool Ryan! I was pretty sure that the issue is on catalog side of things, rather than your code of pulling it. I just wanted to see if you know of any shortcuts... :)

The "$((Get-Date).ToString('yyyy-MM')) trick is nifty and works starting every patch tuesday - It's just really inelegant. I wish microsoft would expose a better API to their update catalog site, at least &product=&sortby=

Either way, big thanks for implementing this module. It saves a lot of manual grief.

ryan-jan commented 3 years ago

@umaritimus I have implemented a SortBy parameter and improved the Strict parameter in the branch feature/improve-sorting-and-strict-results. Would you be interested in testing this out and giving some feedback?

The two changes are:

umaritimus commented 3 years ago

Sure... Is it already in PSGallery?

ryan-jan commented 3 years ago

No, I was thinking you could just pull down the branch with git clone and import the MSCatalog.psd1 file in the MSCatalog directory for a quick test.

umaritimus commented 3 years ago

K, let me see what i can do - it might take me couple days - i need to prep a test machine, but i also found this - Quickly Install PowerShell Modules from GitHub 😃

umaritimus commented 3 years ago

Works marvelously!

Get-MSCatalogUpdate -Search 'Cumulative Update for Windows Server 2019 for x64-based Systems' -Strict -SortBy Title -Descending

results in

Title                                                                               Products            Classification   LastUpdated Size
-----                                                                               --------            --------------   ----------- ----
2020-10 Cumulative Update for Windows Server 2019 for x64-based Systems (KB4577668) Windows Server 2019 Security Updates 2020/10/12  368.3 MB
2020-09 Cumulative Update for Windows Server 2019 for x64-based Systems (KB4570333) Windows Server 2019 Security Updates 2020/09/07  349.8 MB
2020-08 Cumulative Update for Windows Server 2019 for x64-based Systems (KB4565349) Windows Server 2019 Security Updates 2020/08/10  338.1 MB
2020-07 Cumulative Update for Windows Server 2019 for x64-based Systems (KB4558998) Windows Server 2019 Security Updates 2020/07/13  334.8 MB
2020-06 Cumulative Update for Windows Server 2019 for x64-based Systems (KB4567513) Windows Server 2019 Updates          2020/06/15  332.6 MB
2020-06 Cumulative Update for Windows Server 2019 for x64-based Systems (KB4561608) Windows Server 2019 Security Updates 2020/06/08  332.6 MB
...
umaritimus commented 3 years ago

Sorry it took me a while to test it out - I have limited VMs at my disposal, so I had to blow away one of my testing machines, but this amusing concoction of InstallModuleFromGitHub does work rather well. 😃

Install-Module -Name InstallModuleFromGitHub
Install-ModuleFromGitHub -GitHubRepo ryan-jan/MSCatalog -Branch feature/improve-sorting-and-strict-results
Get-MSCatalogUpdate -Search 'Cumulative Update for Windows Server 2019 for x64-based Systems' -Strict

The speed improved significantly too without the AllPages flag - awesome work! Please merge!

ryan-jan commented 3 years ago

Glad it is working for you. It will take a little bit longer to merge as I need to update the Pester tests etc seeing as I changed quite a bit of the code base in the end. Once it is done I will update this issue before closing.

ryan-jan commented 3 years ago

Closing issue as these changes have now been merged with master and have been pushed to PowerShell gallery. Run Update-Module MSCatalog to pull the latest version from the gallery.

umaritimus commented 3 years ago

Excellent work!