Why does search for installed updates using win32com.client.Dispatch() not match Control Panel

86 Views Asked by At

I'm on Windows Server 2019 Standard, 1809, 17763.4499 Using Python v3.11.4:d2340ef

Based on the code found here I've written the following script to find out what updates have been installed.

The issue is; the reported updates don't match what I see manually in Control Panel.

Why is that? Do I need to alter the search parameters?

Results Summary

Found by script...
(In Control Panel)     KB5012170  2022-08 Security Update for Windows Server 201...
(In Control Panel)     KB5027222  2023-06 Cumulative Update for Windows Server 2...
(In Control Panel)     KB4589208  2021-01 Update for Windows Server 2019 for x64...
(In Control Panel)     KB5012170  2022-08 Security Update for Windows Server 201...
(NOT In Control Panel) MSXML 6.0 RTM Security Update  (925673)
(NOT In Control Panel) KB5027536       2023-06 Cumulative Update for .NET Framework 3...
(NOT In Control Panel) MSXML 6.0 RTM Security Update  (925673)
(NOT In Control Panel) KB4589208       2021-01 Update for Windows Server 2019 for x64...
(NOT In Control Panel) PowerShell v7.3.4 (x64)
(NOT In Control Panel) KB890830        Windows Malicious Software Removal Tool x64 - ...
(NOT In Control Panel) KB5027536       2023-06 Cumulative Update for .NET Framework 3...
(NOT In Control Panel) PowerShell v7.3.4 (x64)
(NOT In Control Panel) KB890830        Windows Malicious Software Removal Tool x64 - ...
(NOT In Control Panel) KB890830        Windows Malicious Software Removal Tool x64 - ...

In Control Panel, not found by script...
KB5027124
KB4486153
KB5005112
KB4535680
KB4598480

Control Panel | Programs and Features | Updates Control Panel Programs Updates

CODE

import win32com.client
import win32con
import win32api
import pywintypes
import re

def get_software_updates(update_seeker, installed, verbose = False):
    verbose   = True if verbose else False
    installed = 1 if installed else 0
    # Search installed/not installed Software Windows Updates
    # search_string = "IsInstalled=%d and Type='Software'" % installed
    search_string = f"IsInstalled={installed}"
    search_update = update_seeker.Search(search_string)
    _ = win32com.client.Dispatch("Microsoft.Update.UpdateColl")

    result = {}
    # compiles the regex pattern for finding Windows Update codes
    updates_pattern = re.compile(r'KB+\d+')
    for update in search_update.Updates:
        update_str = str(update)

        # extracts Windows Update code using regex
        update_code = updates_pattern.findall(update_str)
        
        for category in update.Categories:
            category_name = category.Name
            try:
                result[category_name]
            except KeyError: 
                result[category_name] = []
            result[category_name].append((update_code, update_str))
            if verbose: print(f"[*] Name: {update_str} - url: https://support.microsoft.com/en-us/kb/{''.join(update_code).strip('KB')} - Category: {category_name}")
            
    return result

def enum_winupdates():
    installed = {}
    available = {}
    wua = win32com.client.Dispatch("Microsoft.Update.Session")
    update_seeker = wua.CreateUpdateSearcher()
    print("[+] Enumerating installed Windows or Drivers' Updates (if any)...", end = "")
    installed = get_software_updates(update_seeker, installed=True)
    print("OK")
        
    return installed, available

if __name__ == "__main__":
    installed, available = enum_winupdates()
    print("\ninstalled -----,--------------")
    data = []
    for k,v in installed.items():
        # print(f"\n{k}:")
        for i in v:
            print("  ({0:<10} {1}".format(''.join(i[0])+")", i[1]))
            data.append([''.join(i[0]), i[1]])    
0

There are 0 best solutions below