You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Python读取Windows更新文件元数据获取目标Windows版本

如何通过Python读取Windows更新文件元数据获取目标Windows版本

哥们,我之前折腾过一模一样的需求——靠文件名判断Win10/Win11更新太不靠谱了,毕竟微软的文件命名有时候真的让人头大。试了好几种方法,终于找到了几个靠谱的路子,分不同文件类型给你讲讲,亲测有效:

处理 .msu 文件

其实MSU本质就是个换了后缀的ZIP压缩包,里面藏着关键的元数据XML文件。用Python自带的zipfile就能解压,再解析XML就能拿到目标系统版本:

import zipfile
import xml.etree.ElementTree as ET

def get_win_version_from_msu(msu_path):
    with zipfile.ZipFile(msu_path, 'r') as zip_ref:
        # 找出包里的XML文件,一般叫Update.xml或者类似的
        xml_files = [f for f in zip_ref.namelist() if f.endswith('.xml')]
        if not xml_files:
            return "找不到元数据XML文件"
        
        with zip_ref.open(xml_files[0]) as xml_file:
            tree = ET.parse(xml_file)
            root = tree.getroot()
            # Windows更新XML有固定命名空间,必须带上
            ns = {'wu': 'http://schemas.microsoft.com/msus/2002/12/Update'}
            target_os = root.find('.//wu:TargetOperatingSystem', ns)
            
            if target_os:
                version_str = target_os.find('wu:Version', ns).text
                major, minor, build = map(int, version_str.split('.'))
                # Win10的build从10240开始,Win11是22000及以上
                if build >= 22000:
                    return f"Windows 11 (版本号: {version_str})"
                elif build >= 10240:
                    return f"Windows 10 (版本号: {version_str})"
                else:
                    return f"未知Windows版本 (版本号: {version_str})"
            return "未找到目标系统版本信息"

处理 .msi 和 .msp 文件

这俩属于Windows安装包格式,得用Windows Installer的COM接口来读元数据,需要先装pywin32库(pip install pywin32):

import win32com.client

def get_win_version_from_msi_msp(file_path):
    installer = win32com.client.Dispatch("WindowsInstaller.Installer")
    try:
        # 以只读模式打开安装包数据库
        db = installer.OpenDatabase(file_path, 0)
        
        # 先查VersionNT属性,这是Windows Installer标记的最低支持系统版本
        view = db.OpenView("SELECT Value FROM Property WHERE Property='VersionNT'")
        view.Execute()
        record = view.Fetch()
        
        if record:
            version_nt = record.StringData(1)
            # VersionNT的数值对应:603=Win10,1001=Win11
            if version_nt == '603':
                return "Windows 10"
            elif version_nt == '1001':
                return "Windows 11"
        
        # 如果VersionNT查不到,就看ProductVersion里的build号
        view = db.OpenView("SELECT Value FROM Property WHERE Property='ProductVersion'")
        view.Execute()
        record = view.Fetch()
        
        if record:
            product_ver = record.StringData(1)
            if '22000' in product_ver or '22621' in product_ver:
                return f"Windows 11 (产品版本: {product_ver})"
            elif any(build in product_ver for build in ['1904', '1836', '1776']):
                return f"Windows 10 (产品版本: {product_ver})"
        
        return "未找到有效版本信息"
    except Exception as e:
        return f"读取失败: {str(e)}"
    finally:
        # 记得释放资源,避免内存泄漏
        try:
            view.Close()
        except:
            pass

处理 .cab 文件

CAB是最麻烦的,因为里面可能装着各种内容——有时候是MSI,有时候是驱动,有时候是纯更新文件。给你两种方案:

方案1:用Windows自带的DISM命令

DISM是Windows内置的部署工具,能直接读取CAB里的映像信息:

import subprocess
import re

def get_win_version_from_cab_dism(cab_path):
    try:
        # 调用DISM命令获取映像信息
        result = subprocess.run(
            ['dism', '/Get-WimInfo', '/WimFile:' + cab_path, '/Index:1'],
            capture_output=True,
            text=True,
            check=True
        )
        # 从输出里提取版本号
        version_match = re.search(r'Version\s*:\s*(\d+\.\d+\.\d+\.\d+)', result.stdout)
        if version_match:
            full_ver = version_match.group(1)
            build = int(full_ver.split('.')[2])
            if build >= 22000:
                return f"Windows 11 (版本号: {full_ver})"
            elif build >= 10240:
                return f"Windows 10 (版本号: {full_ver})"
        return "DISM未识别到有效版本信息"
    except subprocess.CalledProcessError as e:
        return f"DISM命令执行失败: {e.stderr}"

方案2:解压CAB处理内部文件

如果DISM报错(比如CAB不是WIM格式),就解压CAB找里面的MSI/XML文件,用前面的方法处理。可以用pycabinet库(pip install pycabinet):

import pycabinet
import xml.etree.ElementTree as ET

def get_win_version_from_cab_extract(cab_path):
    try:
        with pycabinet.Cabinet(cab_path) as cab:
            for entry in cab:
                # 遇到MSI/MSP就用之前的方法处理
                if entry.name.endswith(('.msi', '.msp')):
                    with open('temp_installer.msi', 'wb') as f:
                        f.write(entry.read())
                    ver = get_win_version_from_msi_msp('temp_installer.msi')
                    if ver != "未找到有效版本信息":
                        return ver
                # 遇到XML就用MSU的解析逻辑
                elif entry.name.endswith('.xml'):
                    xml_content = entry.read()
                    tree = ET.fromstring(xml_content)
                    ns = {'wu': 'http://schemas.microsoft.com/msus/2002/12/Update'}
                    target_os = tree.find('.//wu:TargetOperatingSystem', ns)
                    if target_os:
                        version_str = target_os.find('wu:Version', ns).text
                        build = int(version_str.split('.')[2])
                        if build >=22000:
                            return f"Windows 11 (版本号: {version_str})"
                        elif build>=10240:
                            return f"Windows 10 (版本号: {version_str})"
        return "未找到有效版本信息"
    except Exception as e:
        return f"解压处理失败: {str(e)}"

最后提醒几句

  • Win10的build号范围是10240~21999,Win11是22000及以上,这个判断标准是微软官方的,不会错
  • 处理XML的时候一定要注意命名空间,不然会找不到元素
  • COM对象用完记得释放,不然容易留内存泄漏的坑

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 09:49:29