Windows软件自动扫描与分类工具 - 技术文档

Windows软件自动扫描与分类工具 - 技术文档

项目概述

项目目标

开发一个能够全面扫描Windows系统中所有已安装软件,并基于国际标准进行自动分类的工具,解决软件资产管理中的识别和分类难题。

核心功能

  • 全面扫描: 检测系统级和用户级的所有软件
  • 智能分类: 基于国际标准的12大类50+小类分类体系
  • 详细报告: 生成CSV结果和Markdown分析报告
  • 易于集成: 模块化设计,便于嵌入其他项目

技术栈

  • 编程语言: Python 3.6+
  • 系统访问: Windows注册表API
  • 数据处理: CSV文件操作
  • 报告生成: Markdown文档生成

技术原理

软件扫描原理

1. 注册表扫描机制

Windows系统中,已安装软件的信息主要存储在以下注册表位置:

位置 描述 权限要求
HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall 系统级32位软件 管理员权限
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall 系统级64位软件 管理员权限
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall 用户级软件 普通用户权限
2. 软件信息提取

从注册表中提取的关键信息包括:

  • DisplayName: 软件名称
  • DisplayVersion: 版本号
  • Publisher: 发布者
  • InstallDate: 安装日期
  • InstallLocation: 安装位置
  • UninstallString: 卸载命令
3. 去重策略

采用基于软件名称的智能去重:

python 复制代码
normalized_name = software_info['DisplayName'].strip().lower()
if normalized_name not in seen_names:
    seen_names.add(normalized_name)
    software_list.append(software_info)

自动分类原理

1. 分类体系设计

基于ISO/IEC TR 12182软件分类标准,设计了12个大类:

  1. 系统软件: 操作系统组件、驱动程序、系统工具等
  2. 应用开发软件: IDE、编程语言、开发工具等
  3. 办公与生产力软件: 办公套件、文档处理等
  4. 打印与成像软件: 打印机管理、扫描软件等
  5. 移动与嵌入式软件: 移动设备工具、嵌入式系统等
  6. 通信与协作软件: 即时通讯、视频会议等
  7. 个人效率软件: 云存储、压缩软件等
  8. 媒体与娱乐软件: 视频播放、音频播放等
  9. 网络与安全软件: 浏览器、VPN、安全软件等
  10. 人工智能与自动化软件: AI助手、自动化工具等
  11. 业务与金融软件: 金融软件、ERP、CRM等
  12. 专业领域软件: 工程设计、科学计算等
2. 分类算法

采用多层级匹配策略:

python 复制代码
def classify_software(name, publisher):
    # 1. 特殊软件完全匹配
    # 2. 特殊软件包含匹配  
    # 3. VS组件特殊处理
    # 4. 厂商特定软件处理
    # 5. 关键词匹配分类
    # 6. 发布者匹配分类
    # 7. 默认分类
3. 关键词匹配机制

为每个分类设计了专属的关键词库:

python 复制代码
taxonomy = {
    '系统软件': {
        '操作系统组件': ['microsoft .net', 'visual c++', 'runtime', 'framework', 'windows']
    },
    # 其他分类...
}

代码结构设计

核心模块

1. 扫描模块 (get_all_installed_software())

负责从注册表中扫描并提取软件信息:

python 复制代码
def get_all_installed_software():
    """获取系统中所有已安装的软件"""
    software_list = []
    scan_locations = [
        (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKLM (32-bit)"),
        (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", "HKLM (64-bit)"),
        (winreg.HKEY_CURRENT_USER, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKCU (User)")
    ]
    
    for hive, reg_path, description in scan_locations:
        # 扫描逻辑...
    
    return software_list
2. 分类模块 (classify_software_comprehensive())

实现软件的自动分类功能:

python 复制代码
def classify_software_comprehensive(name, publisher, taxonomy, special_cases):
    """全面的软件分类函数"""
    # 分类逻辑...
    return major_category, minor_category
3. 报告生成模块 (generate_detailed_report())

生成详细的分析报告:

python 复制代码
def generate_detailed_report(software_list, classified_list):
    """生成详细的分类报告"""
    # 报告生成逻辑...
    return report_file
4. 主控制模块 (main())

协调各个模块的执行:

python 复制代码
def main():
    """主函数 - 全面软件扫描和分类"""
    # 步骤1: 全面扫描软件
    # 步骤2: 加载分类体系  
    # 步骤3: 对所有软件进行分类
    # 步骤4: 保存结果和生成报告

配置文件设计

1. 分类体系配置
python 复制代码
def create_comprehensive_taxonomy():
    """创建全面的软件分类体系"""
    taxonomy = {
        # 12个大类的详细配置...
    }
    return taxonomy
2. 特殊软件处理规则
python 复制代码
def get_enhanced_special_cases():
    """获取增强版特殊软件处理规则"""
    return {
        'typora': ('办公与生产力软件', '文档处理'),
        '豆包': ('人工智能与自动化软件', 'AI助手'),
        # 其他特殊软件...
    }

集成指南

嵌入到其他项目的方法

1. 作为独立模块调用
python 复制代码
from Comprehensive_Software_Scanner_Fixed import get_all_installed_software, classify_software_comprehensive

# 获取软件列表
software_list = get_all_installed_software()

# 加载分类体系
taxonomy = create_comprehensive_taxonomy()
special_cases = get_enhanced_special_cases()

# 分类处理
classified_results = []
for software in software_list:
    major, minor = classify_software_comprehensive(
        software['DisplayName'],
        software['Publisher'],
        taxonomy,
        special_cases
    )
    classified_results.append({
        'name': software['DisplayName'],
        'category': major,
        'subcategory': minor,
        'version': software['DisplayVersion'],
        'publisher': software['Publisher']
    })
2. 作为命令行工具集成
bash 复制代码
# 在其他项目中调用
python -c "from Comprehensive_Software_Scanner_Fixed import main; main()"
3. 结果数据格式

CSV结果文件格式:

csv 复制代码
Major_Category,Minor_Category,DisplayName,DisplayVersion,Publisher,InstallLocation,InstallDate,UninstallString,ScanSource
系统软件,操作系统组件,Microsoft .NET Runtime,9.0.10,Microsoft Corporation,,20251106,MsiExec.exe /X{05987870-6EDD-4352-ADEA-4A8694040F3E},HKLM (64-bit)

与文档扫描项目集成

1. 软件-文档关联分析
python 复制代码
def analyze_software_document_relationship(software_list, document_list):
    """分析软件与文档的关联关系"""
    relationships = []
    
    for software in software_list:
        software_name = software['DisplayName'].lower()
        
        for document in document_list:
            document_name = document['name'].lower()
            document_content = document['content'].lower()
            
            # 检查软件名称是否在文档中出现
            if software_name in document_content or any(keyword in document_content 
                                                     for keyword in get_software_keywords(software_name)):
                relationships.append({
                    'software': software['DisplayName'],
                    'document': document['name'],
                    'relationship_type': 'content_reference'
                })
    
    return relationships
2. 文档分类建议
python 复制代码
def suggest_document_category_based_on_software(document_content, classified_software):
    """基于相关软件为文档建议分类"""
    category_scores = {}
    
    for software in classified_software:
        software_name = software['DisplayName'].lower()
        if software_name in document_content.lower():
            category = software['Major_Category']
            category_scores[category] = category_scores.get(category, 0) + 1
    
    if category_scores:
        return max(category_scores.items(), key=lambda x: x[1])[0]
    return "未分类"
3. 综合资产管理
python 复制代码
def integrate_with_asset_management(software_results, document_results):
    """与资产管理系统集成"""
    asset_inventory = {
        'software_assets': software_results,
        'document_assets': document_results,
        'relationships': analyze_software_document_relationship(software_results, document_results),
        'scan_timestamp': datetime.now().isoformat()
    }
    
    return asset_inventory

使用指南

环境要求

1. 系统要求
  • 操作系统: Windows 10/11
  • Python版本: Python 3.6或更高版本
  • 权限要求: 建议管理员权限
2. 依赖安装
bash 复制代码
# 检查Python版本
python --version

# 无需额外依赖,使用Python标准库

运行方式

1. 基本运行
bash 复制代码
# 普通用户权限运行
python Comprehensive_Software_Scanner_Fixed.py

# 管理员权限运行(推荐)
# 在命令提示符中右键选择"以管理员身份运行"
python Comprehensive_Software_Scanner_Fixed.py
2. 命令行参数扩展(可选)
python 复制代码
import argparse

def parse_arguments():
    parser = argparse.ArgumentParser(description='Windows软件扫描与分类工具')
    parser.add_argument('--output-dir', default='.', help='输出目录')
    parser.add_argument('--report-only', action='store_true', help='只生成报告,不保存CSV')
    parser.add_argument('--verbose', action='store_true', help='详细输出模式')
    return parser.parse_args()

def main():
    args = parse_arguments()
    # 根据参数执行不同操作...
3. 自动化脚本集成
python 复制代码
# 创建自动化脚本 run_scan.bat
@echo off
echo 开始软件扫描...
python "%~dp0Comprehensive_Software_Scanner_Fixed.py"
echo 扫描完成!
pause

输出结果

1. CSV结果文件

文件名格式:Comprehensive_Software_Classification_YYYYMMDD_HHMMSS.csv

包含字段:

  • Major_Category: 大类
  • Minor_Category: 小类
  • DisplayName: 软件名称
  • DisplayVersion: 版本号
  • Publisher: 发布者
  • InstallLocation: 安装位置
  • InstallDate: 安装日期
  • UninstallString: 卸载命令
  • ScanSource: 扫描来源
2. Markdown报告文件

文件名格式:Comprehensive_Software_Report_YYYYMMDD_HHMMSS.md

报告内容包括:

  • 扫描统计信息
  • 分类质量分析
  • 详细软件列表
  • 可视化表格

经验总结

技术挑战与解决方案

1. 注册表访问权限问题

挑战 : 普通用户无法访问系统级注册表
解决方案:

  • 添加权限检查和提示
  • 提供管理员权限运行建议
  • 优雅处理访问被拒绝错误
2. 软件分类准确性

挑战 : 软件名称多样化,分类规则复杂
解决方案:

  • 建立多层级分类策略
  • 维护特殊软件处理规则库
  • 持续优化关键词匹配算法
3. 性能优化

挑战 : 注册表扫描可能耗时较长
解决方案:

  • 添加进度显示
  • 优化循环和条件判断
  • 减少不必要的注册表访问

最佳实践

1. 代码设计原则
  • 模块化设计: 功能分离,便于维护
  • 错误处理: 全面的异常处理机制
  • 用户友好: 清晰的进度显示和提示信息
  • 可扩展性: 易于添加新的分类规则
2. 分类体系维护
  • 定期更新: 根据新软件更新分类规则
  • 用户反馈: 收集实际使用中的分类错误
  • 标准跟踪: 关注ISO标准的更新变化
3. 部署建议
  • 权限配置: 确保工具具有足够的访问权限
  • 定期扫描: 建立定期扫描机制
  • 结果备份: 妥善保存扫描结果
  • 版本控制: 对工具本身进行版本管理

性能优化建议

1. 扫描性能优化
python 复制代码
# 批量读取注册表项
def batch_read_registry_keys(key, batch_size=100):
    subkey_count = winreg.QueryInfoKey(key)[0]
    for i in range(0, subkey_count, batch_size):
        batch = []
        for j in range(i, min(i + batch_size, subkey_count)):
            try:
                subkey_name = winreg.EnumKey(key, j)
                batch.append(subkey_name)
            except:
                continue
        yield batch
2. 分类算法优化
python 复制代码
# 使用字典加速关键词匹配
def build_keyword_index(taxonomy):
    keyword_index = {}
    for major, minors in taxonomy.items():
        for minor, keywords in minors.items():
            for keyword in keywords:
                keyword_index[keyword.lower()] = (major, minor)
    return keyword_index

# 使用索引快速匹配
def fast_classify(name, publisher, keyword_index):
    name_lower = name.lower()
    for keyword, category in keyword_index.items():
        if keyword in name_lower:
            return category
    return ('其他软件', '未分类软件')

扩展功能建议

1. 图形界面开发

使用PyQt或Tkinter开发可视化界面:

python 复制代码
import tkinter as tk
from tkinter import ttk, messagebox

class SoftwareScannerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("Windows软件扫描工具")
        # GUI设计...
    
    def start_scan(self):
        # 启动扫描...

2. 网络功能集成

添加网络查询功能,获取软件的详细信息:

python 复制代码
def get_software_info_from_network(software_name):
    """从网络获取软件详细信息"""
    import requests
    try:
        response = requests.get(f"https://api.example.com/software/search?q={software_name}")
        if response.status_code == 200:
            return response.json()
    except:
        pass
    return None

3. 数据库存储

将结果存储到数据库中,支持查询和统计:

python 复制代码
import sqlite3

def save_to_database(software_list, db_path='software_inventory.db'):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    
    # 创建表结构
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS software (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT,
            version TEXT,
            publisher TEXT,
            category TEXT,
            subcategory TEXT,
            install_date TEXT,
            install_location TEXT,
            scan_source TEXT,
            scan_timestamp TEXT
        )
    ''')
    
    # 插入数据
    for software in software_list:
        cursor.execute('''
            INSERT INTO software (name, version, publisher, category, subcategory, 
                                 install_date, install_location, scan_source, scan_timestamp)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
        ''', (
            software['DisplayName'],
            software['DisplayVersion'],
            software['Publisher'],
            software['Major_Category'],
            software['Minor_Category'],
            software['InstallDate'],
            software['InstallLocation'],
            software['ScanSource'],
            datetime.now().isoformat()
        ))
    
    conn.commit()
    conn.close()

4. 实时监控功能

添加软件安装监控功能:

python 复制代码
def monitor_software_changes():
    """监控软件安装和卸载变化"""
    import time
    previous_list = set()
    
    while True:
        current_list = set(get_installed_software_names())
        
        # 检测新增软件
        new_software = current_list - previous_list
        if new_software:
            print(f"发现新安装软件: {new_software}")
        
        # 检测卸载软件
        removed_software = previous_list - current_list
        if removed_software:
            print(f"发现卸载软件: {removed_software}")
        
        previous_list = current_list
        time.sleep(3600)  # 每小时检查一次

总结

项目成果

  1. 全面扫描: 实现了系统级和用户级软件的全面扫描
  2. 智能分类: 建立了基于国际标准的12大类分类体系
  3. 高覆盖率: 分类覆盖率达到98%以上
  4. 易于集成: 模块化设计,便于嵌入其他项目
  5. 详细报告: 生成专业的分析报告

技术价值

  • 标准化: 基于国际标准的分类体系
  • 自动化: 全自动化的扫描和分类流程
  • 可扩展: 易于添加新功能和优化算法
  • 实用性: 解决了实际的软件资产管理需求

应用场景

  • 企业IT资产管理: 全面了解企业软件资产状况
  • 软件合规审计: 检查软件许可合规性
  • 安全风险评估: 识别潜在的安全风险软件
  • IT服务管理: 支持IT服务台的日常运维工作
  • 文档管理系统: 与文档管理系统集成,建立软件-文档关联

这个工具为Windows系统的软件资产管理提供了完整的解决方案,具有很强的实用价值和扩展性。通过持续优化和功能扩展,可以更好地满足不同场景下的软件管理需求。

实现代码:

python 复制代码
import os
import sys
import csv
import re
import winreg
from datetime import datetime

def get_all_installed_software():
    """
    获取系统中所有已安装的软件,包括:
    1. 系统级32位软件 (HKLM 32-bit)
    2. 系统级64位软件 (HKLM 64-bit)  
    3. 用户级软件 (HKCU)
    """
    
    software_list = []
    software_names = set()  # 用于去重
    
    print("正在扫描已安装软件...")
    print("=" * 60)
    
    # 1. 扫描系统级注册表位置 - 正确的路径格式
    scan_locations = [
        # (注册表 hive, 路径, 描述)
        (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKLM (32-bit)"),
        (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", "HKLM (64-bit)"),
        (winreg.HKEY_CURRENT_USER, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKCU (User)")
    ]
    
    # 扫描注册表
    for hive, reg_path, description in scan_locations:
        print(f"正在扫描 {description}...")
        
        try:
            # 打开注册表项
            key = winreg.OpenKey(hive, reg_path)
            
            # 获取子项数量
            subkey_count = winreg.QueryInfoKey(key)[0]
            print(f"  发现 {subkey_count} 个子项,正在处理...")
            
            # 遍历所有子项
            found_count = 0
            for j in range(subkey_count):
                try:
                    subkey_name = winreg.EnumKey(key, j)
                    
                    # 完整路径
                    subkey_full_path = f"{reg_path}\\{subkey_name}"
                    
                    with winreg.OpenKey(hive, subkey_full_path) as subkey:
                        software_info = {}
                        
                        # 获取基本信息 - 软件名称
                        try:
                            software_info['DisplayName'] = winreg.QueryValueEx(subkey, "DisplayName")[0]
                        except FileNotFoundError:
                            continue
                        except Exception as e:
                            continue
                        
                        # 跳过没有名称的条目或系统内部条目(GUID)
                        if not software_info['DisplayName'] or software_info['DisplayName'].startswith("{"):
                            continue
                        
                        # 去重检查(忽略大小写)
                        normalized_name = software_info['DisplayName'].strip().lower()
                        if normalized_name in software_names:
                            continue
                        software_names.add(normalized_name)
                        
                        # 获取其他信息
                        try:
                            software_info['DisplayVersion'] = winreg.QueryValueEx(subkey, "DisplayVersion")[0]
                        except FileNotFoundError:
                            software_info['DisplayVersion'] = "未知"
                        except Exception:
                            software_info['DisplayVersion'] = "获取失败"
                        
                        try:
                            software_info['Publisher'] = winreg.QueryValueEx(subkey, "Publisher")[0]
                        except FileNotFoundError:
                            software_info['Publisher'] = "未知"
                        except Exception:
                            software_info['Publisher'] = "获取失败"
                        
                        try:
                            software_info['InstallDate'] = winreg.QueryValueEx(subkey, "InstallDate")[0]
                        except FileNotFoundError:
                            software_info['InstallDate'] = "未知"
                        except Exception:
                            software_info['InstallDate'] = "获取失败"
                        
                        try:
                            software_info['InstallLocation'] = winreg.QueryValueEx(subkey, "InstallLocation")[0]
                        except FileNotFoundError:
                            software_info['InstallLocation'] = "未知"
                        except Exception:
                            software_info['InstallLocation'] = "获取失败"
                        
                        try:
                            software_info['UninstallString'] = winreg.QueryValueEx(subkey, "UninstallString")[0]
                        except FileNotFoundError:
                            software_info['UninstallString'] = "未知"
                        except Exception:
                            software_info['UninstallString'] = "获取失败"
                        
                        # 添加扫描来源信息
                        software_info['ScanSource'] = description
                        
                        software_list.append(software_info)
                        found_count += 1
                        
                        # 显示进度
                        if (j + 1) % 50 == 0 or j + 1 == subkey_count:
                            print(f"  处理进度: {j + 1}/{subkey_count} 个子项,发现 {found_count} 个软件")
                            
                except WindowsError as e:
                    # 权限不足等错误,跳过
                    if e.winerror == 5:  # 访问被拒绝
                        print(f"  警告: 访问子项 {subkey_name} 时权限不足")
                    continue
                except Exception as e:
                    # 其他错误,跳过
                    continue
            
            winreg.CloseKey(key)
            print(f"  成功扫描 {description}: 发现 {found_count} 个软件")
            
        except WindowsError as e:
            if e.winerror == 5:  # 访问被拒绝
                print(f"  错误: 访问 {description} 时权限不足,请以管理员权限运行")
            elif e.winerror == 2:  # 文件未找到
                print(f"  错误: {description} 路径不存在")
            else:
                print(f"  错误: 扫描 {description} 时出错 - {e}")
            continue
        except Exception as e:
            print(f"  错误: 扫描 {description} 时发生异常 - {e}")
            continue
    
    print("=" * 60)
    print(f"扫描完成!总共发现 {len(software_list)} 个软件")
    
    return software_list

def create_comprehensive_taxonomy():
    """创建全面的软件分类体系"""
    
    taxonomy = {
        # 1. 系统软件
        '系统软件': {
            '操作系统组件': ['microsoft .net', 'microsoft visual c++', 'runtime', 'framework',
                           'windows', 'system', 'verifier', 'icecap', 'kits configuration',
                           'directx', 'visual studio', 'redistributable', 'common files',
                           'universal crt', 'vcpp_', 'vba', 'sdk', 'windows sdk', 'microsoft edge webview2'],
            '设备驱动程序': ['driver', 'printer driver', 'device driver', 'epson driver'],
            '系统工具': ['diagnostics', 'verifier', 'system tools', 'configuration', 'setup',
                       'diagnosticshub_collection', 'application verifier', 'microsoft update health tools'],
            '性能分析工具': ['wpt', 'performance', 'profiler', 'analyzer'],
            '更新工具': ['microsoft update', 'update health', 'windows update', 'update tools', 'software updater']
        },
        
        # 2. 应用开发软件
        '应用开发软件': {
            '集成开发环境': ['pycharm', 'intellij', 'visual studio', 'eclipse', 'idea', 'ide',
                           'visual studio code'],
            '编程语言与运行时': ['python', 'node.js', 'java', 'c++', 'c#', 'javascript', 'typescript',
                              'anaconda', 'python launcher', 'jdk', 'jre'],
            '开发工具与框架': ['git', 'github', 'docker', 'maven', 'gradle', 'npm', 'yarn',
                            'graphviz', 'heroku', 'cursor', 'ai gist', 'development',
                            'msi development tools', 'github protocol handler'],
            '数据库工具': ['mysql', 'sql server', 'oracle', 'postgresql', 'mongodb', 'navicat',
                         'database', 'sql', 'dbms', 'sqlite'],
            'Web开发框架': ['asp.net', 'asp.net core', 'web framework'],
            'WebAssembly开发工具': ['emscripten', 'webassembly'],
            '跨平台开发工具': ['mono', 'xamarin', 'cross-platform'],
            '调试工具': ['debugger', 'jit debugger', 'script debugging'],
            'VS组件': ['visual studio component', 'vs component', 'vs immersive activate helper',
                     'vs_devenx64vmsi', 'vs_minshell', 'vs_community', 'vs_coreeditorfonts',
                     'vs_filehandler', 'vs_filetracker', 'vs_tipsmsi', 'vs_vswebprotocolselector'],
            '智能提示工具': ['intellisense', 'winrt intellisense']
        },
        
        # 3. 办公与生产力软件
        '办公与生产力软件': {
            '办公套件': ['office', 'microsoft office', 'excel', 'word', 'powerpoint', 'onenote',
                       'outlook', 'wps', 'libreoffice', 'openoffice'],
            '文档处理': ['pdf', 'adobe digital editions', 'pdf24', 'pandoc', 'document', 'typora',
                       'markdown', '稻壳阅读器', 'document reader', 'wkhtmltox', 'notepad++'],
            '协作工具': ['腾讯会议', '钉钉', '飞书', 'teams', 'slack', 'conference', 'meeting'],
            '项目管理': ['project', 'trello', 'asana', 'jira', 'project management'],
            '笔记软件': ['evernote', 'onenote', 'notion', 'bear', 'simplenote']
        },
        
        # 4. 打印与成像软件
        '打印与成像软件': {
            '打印机管理': ['epson', 'printer', 'print', 'epsonnet print', 'myepson portal',
                        'epson event manager', 'epson printer connection checker'],
            '扫描软件': ['scan', 'epson scan', 'epson scansmart', 'epson scan ocr',
                      'epson scan pdf extensions'],
            '图像软件': ['epson photo+', 'epson manuals', 'epson connect printer setup', 'image viewer']
        },
        
        # 5. 移动与嵌入式软件
        '移动与嵌入式软件': {
            '移动设备工具': ['hisuite', 'honor', 'itunes', 'kies', 'smart switch', 'mobile', 'phone',
                           '荣耀', '华为', 'diagnoseanalysis', '荣耀超级工作台', '荣耀yoyo助理',
                           '荣耀电脑管家', 'osd'],
            '嵌入式软件': ['embedded', 'iot', 'internet of things', 'winrt intellisense iot'],
            '移动应用开发': ['winappdeploy', 'winrt intellisense mobile']
        },
        
        # 6. 通信与协作软件
        '通信与协作软件': {
            '即时通讯': ['qq', 'wechat', 'telegram', '微信', 'chat', 'messenger', '腾讯qq', 'telegram desktop'],
            '视频会议': ['腾讯会议', 'zoom', 'teams', 'video conference', 'meeting'],
            '电子邮件': ['outlook', 'thunderbird', 'email', 'mail'],
            '企业协作': ['钉钉', '飞书', 'slack', 'discord', 'teams', 'collaboration', '企业微信',
                       '南网elink']
        },
        
        # 7. 个人效率软件
        '个人效率软件': {
            '云存储': ['onedrive', '阿里云盘', '百度网盘', 'dropbox', 'google drive', 'cloud', 'storage'],
            '压缩软件': ['winrar', '7-zip', 'winzip', '7zip', 'compression', 'archive', 'zip', 'rar'],
            '思维导图': ['xmind', 'mindmanager', 'mindmap', 'mind mapping'],
            '文件管理': ['onecommander', 'total commander', 'file explorer', 'directory', 'file manager',
                       'listary'],
            '截图工具': ['pixpin', 'snip', 'screenshot', 'capture', 'image capture'],
            '翻译软件': ['有道翻译', '翻译', 'translate', 'translation'],
            '输入法': ['输入法', 'input method', 'ime', '微信输入法'],
            '桌面增强': ['launcher', 'desktop enhancement', 'utilities'],
            '下载工具': ['download', 'download manager', '迅雷', 'idm']
        },
        
        # 8. 媒体与娱乐软件
        '媒体与娱乐软件': {
            '视频播放': ['potplayer', 'vlc', 'media player', 'video', 'player', 'bilibili',
                       'vlc media player', '哔哩哔哩'],
            '音频播放': ['网易云音乐', 'music', 'audio', 'player', 'spotify', 'itunes'],
            '图像处理': ['photoshop', 'gimp', 'image', 'photo', 'graphics', 'pixpin'],
            '视频编辑': ['premiere', 'after effects', 'video editor', 'final cut'],
            '音频编辑': ['audacity', 'audio editor', 'sound editor']
        },
        
        # 9. 网络与安全软件
        '网络与安全软件': {
            '浏览器': ['chrome', 'edge', 'firefox', 'browser', 'webview', 'opera', 'safari', '夸克'],
            '网络工具': ['clash', 'vpn', 'network', 'proxy', 'router', '飞梭vpn', 'clash verge'],
            '安全软件': ['antivirus', 'security', 'firewall', 'malware', 'virus', 'protection'],
            '远程访问': ['todesk', 'teamviewer', 'anydesk', 'remote', 'control', 'remote service']
        },
        
        # 10. 人工智能与自动化软件
        '人工智能与自动化软件': {
            'AI助手': ['豆包', 'copilot', 'ai assistant', 'artificial intelligence', 'chatgpt'],
            'AI开发工具': ['ima.copilot', 'ai tools', 'machine learning', 'deep learning'],
            '自动化工具': ['影刀', 'automation', 'robot', 'auto', 'rpa']
        },
        
        # 11. 业务与金融软件
        '业务与金融软件': {
            '金融软件': ['华宝证券', '金长江', '证券', '银行', 'finance', 'financial',
                       'trading', 'investment', 'stock', '智投版', '网上交易'],
            '企业资源计划': ['erp', 'sap', 'oracle erp', 'enterprise resource'],
            '客户关系管理': ['crm', 'salesforce', 'customer relationship']
        },
        
        # 12. 专业领域软件
        '专业领域软件': {
            '工程设计': ['autocad', 'catia', 'solidworks', 'engineering', 'cad'],
            '科学计算': ['matlab', 'mathematica', 'maple', 'scientific computing'],
            '教育软件': ['evercraft', 'educational', 'learning', 'education', 'study'],
            '医疗软件': ['medical', 'healthcare', 'hospital', 'clinic']
        }
    }
    
    return taxonomy

def get_enhanced_special_cases():
    """获取增强版特殊软件处理规则"""
    
    return {
        'typora': ('办公与生产力软件', '文档处理'),
        'node.js': ('应用开发软件', '编程语言与运行时'),
        '稻壳阅读器': ('办公与生产力软件', '文档处理'),
        '豆包': ('人工智能与自动化软件', 'AI助手'),
        '影刀': ('人工智能与自动化软件', '自动化工具'),
        'ima.copilot': ('人工智能与自动化软件', 'AI开发工具'),
        '夸克': ('网络与安全软件', '浏览器'),
        'bilibili': ('媒体与娱乐软件', '视频播放'),
        '哔哩哔哩': ('媒体与娱乐软件', '视频播放'),
        '网易云音乐': ('媒体与娱乐软件', '音频播放'),
        '微信': ('通信与协作软件', '即时通讯'),
        '微信输入法': ('个人效率软件', '输入法'),
        '腾讯会议': ('通信与协作软件', '视频会议'),
        '钉钉': ('通信与协作软件', '企业协作'),
        '飞书': ('通信与协作软件', '企业协作'),
        '南网elink': ('通信与协作软件', '企业协作'),
        'evercraft lite': ('专业领域软件', '教育软件'),
        'listary': ('个人效率软件', '文件管理'),
        'wkhtmltox': ('办公与生产力软件', '文档处理'),
        'vlc media player': ('媒体与娱乐软件', '视频播放'),
        'microsoft visual studio code': ('应用开发软件', '集成开发环境'),
        'microsoft update health tools': ('系统软件', '更新工具'),
        'vs immersive activate helper': ('应用开发软件', 'VS组件'),
        'epson software updater': ('打印与成像软件', '更新工具'),
        'java': ('应用开发软件', '编程语言与运行时'),
        'jdk': ('应用开发软件', '编程语言与运行时'),
        'jre': ('应用开发软件', '编程语言与运行时'),
        'notepad++': ('办公与生产力软件', '文档处理'),
        'ai gist': ('应用开发软件', '开发工具与框架'),
        'github': ('应用开发软件', '开发工具与框架'),
        'pixpin': ('媒体与娱乐软件', '图像处理'),
        'telegram desktop': ('通信与协作软件', '即时通讯'),
        'trae cn': ('其他软件', '用户应用'),
        'wps office': ('办公与生产力软件', '办公套件'),
        'xmind': ('个人效率软件', '思维导图'),
        '网易有道翻译': ('个人效率软件', '翻译软件'),
        '阿里云盘': ('个人效率软件', '云存储'),
        'clash verge': ('网络与安全软件', '网络工具')
    }

def classify_software_comprehensive(name, publisher, taxonomy, special_cases):
    """
    全面的软件分类函数,确保高覆盖率
    """
    
    if not name:
        return '其他软件', '未知软件'
    
    name_lower = str(name).lower().strip()
    publisher_lower = str(publisher).lower().strip() if publisher else ""
    
    # 1. 首先检查完全匹配的特殊处理规则
    for special_name, category in special_cases.items():
        if special_name.lower() == name_lower:
            return category
    
    # 2. 检查包含匹配的特殊处理规则
    for special_name, category in special_cases.items():
        if special_name.lower() in name_lower:
            return category
    
    # 3. 处理VS相关组件(包括以vs_开头的软件)
    if name_lower.startswith('vs_') or 'visual studio' in name_lower:
        if 'devenx64vmsi' in name_lower:
            return '应用开发软件', 'VS开发环境组件'
        elif 'community' in name_lower:
            return '应用开发软件', 'VS社区版组件'
        elif 'coreeditorfonts' in name_lower:
            return '应用开发软件', '编辑器字体组件'
        elif 'devenvsharedmsi' in name_lower:
            return '应用开发软件', 'VS开发环境组件'
        elif 'filehandler' in name_lower:
            return '应用开发软件', '文件处理组件'
        elif 'filetracker' in name_lower:
            return '应用开发软件', '文件跟踪服务'
        elif 'minshell' in name_lower:
            return '应用开发软件', 'VS精简版组件'
        elif 'tipsmsi' in name_lower:
            return '应用开发软件', 'VS提示组件'
        elif 'vswebprotocolselector' in name_lower:
            return '应用开发软件', 'Web协议选择器'
        elif 'immersive activate helper' in name_lower:
            return '应用开发软件', 'VS组件'
        else:
            return '应用开发软件', 'VS组件'
    
    # 4. 处理Epson相关软件
    if 'epson' in name_lower or '爱普生' in name_lower:
        if 'scan' in name_lower:
            return '打印与成像软件', '扫描软件'
        elif 'print' in name_lower or 'printer' in name_lower:
            return '打印与成像软件', '打印机管理'
        elif 'update' in name_lower:
            return '打印与成像软件', '更新工具'
        else:
            return '打印与成像软件', '图像软件'
    
    # 5. 处理Java相关软件
    if 'java' in name_lower or 'jdk' in name_lower or 'jre' in name_lower:
        if 'development kit' in name_lower or 'jdk' in name_lower:
            return '应用开发软件', '编程语言与运行时'
        elif 'runtime' in name_lower or 'jre' in name_lower:
            return '应用开发软件', '编程语言与运行时'
        elif 'auto updater' in name_lower:
            return '应用开发软件', '更新工具'
        else:
            return '应用开发软件', '编程语言与运行时'
    
    # 6. 关键词匹配(更宽松的匹配策略)
    for major_category, minor_categories in taxonomy.items():
        for minor_category, keywords in minor_categories.items():
            # 检查软件名称或发布者中是否包含关键词
            if any(keyword in name_lower or keyword in publisher_lower for keyword in keywords):
                return major_category, minor_category
    
    # 7. 基于发布者的分类
    if 'microsoft' in publisher_lower:
        if 'update' in name_lower:
            return '系统软件', '更新工具'
        elif 'visual c++' in name_lower or '.net' in name_lower or 'runtime' in name_lower:
            return '系统软件', '操作系统组件'
        else:
            return '系统软件', '系统工具'
    
    # 8. 最后的默认分类
    return '其他软件', '用户应用'

def generate_detailed_report(software_list, classified_list):
    """生成详细的分类报告"""
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    report_file = f"Comprehensive_Software_Report_{timestamp}.md"
    
    # 统计
    total_scanned = len(software_list)
    total_classified = len(classified_list)
    
    if total_classified == 0:
        with open(report_file, 'w', encoding='utf-8') as f:
            f.write("# 软件扫描报告\n")
            f.write(f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
            f.write(f"**扫描结果**: 未发现任何软件\n")
            f.write(f"**可能原因**: 权限不足或系统配置问题\n")
        return report_file
    
    # 分类统计
    major_counts = {}
    minor_counts = {}
    source_counts = {}
    
    for software in classified_list:
        major = software['Major_Category']
        minor = software['Minor_Category']
        source = software['ScanSource']
        
        major_counts[major] = major_counts.get(major, 0) + 1
        minor_key = f"{major} > {minor}"
        minor_counts[minor_key] = minor_counts.get(minor_key, 0) + 1
        source_counts[source] = source_counts.get(source, 0) + 1
    
    # 生成报告内容
    report = []
    report.append("# 全面软件分类报告")
    report.append(f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    report.append(f"**扫描软件总数**: {total_scanned}个")
    report.append(f"**分类软件总数**: {total_classified}个")
    report.append("")
    
    # 扫描来源统计
    report.append("## 扫描来源统计")
    report.append("| 扫描位置 | 软件数量 | 占比 |")
    report.append("|----------|----------|------|")
    for source, count in sorted(source_counts.items()):
        percentage = (count / total_scanned) * 100
        report.append(f"| {source} | {count}个 | {percentage:.1f}% |")
    report.append("")
    
    # 大类统计
    report.append("## 大类分类统计")
    report.append("| 大类 | 数量 | 占比 |")
    report.append("|------|------|------|")
    for major, count in sorted(major_counts.items(), key=lambda x: x[1], reverse=True):
        percentage = (count / total_classified) * 100
        report.append(f"| {major} | {count}个 | {percentage:.1f}% |")
    report.append("")
    
    # 小类统计(前30名)
    report.append("## 小类分类统计(前30名)")
    report.append("| 小类 | 数量 | 占比 |")
    report.append("|------|------|------|")
    
    sorted_minors = sorted(minor_counts.items(), key=lambda x: x[1], reverse=True)[:30]
    for minor, count in sorted_minors:
        percentage = (count / total_classified) * 100
        report.append(f"| {minor} | {count}个 | {percentage:.1f}% |")
    report.append("")
    
    # 分类质量分析
    unclassified_count = major_counts.get('其他软件', 0)
    coverage_rate = ((total_classified - unclassified_count) / total_classified) * 100
    
    report.append("## 分类质量分析")
    report.append(f"- **分类覆盖率**: {coverage_rate:.1f}%")
    report.append(f"- **成功分类**: {total_classified - unclassified_count}个")
    report.append(f"- **未分类**: {unclassified_count}个")
    report.append(f"- **大类数量**: {len(major_counts)}个")
    report.append(f"- **小类数量**: {len(minor_counts)}个")
    report.append("")
    
    # 软件列表(按分类排序,限制显示前100个)
    report.append("## 软件列表(前100个)")
    report.append("| 大类 | 小类 | 软件名称 | 版本 | 发布者 | 扫描来源 |")
    report.append("|------|------|----------|------|--------|----------|")
    
    displayed_count = 0
    for software in sorted(classified_list, key=lambda x: (x['Major_Category'], x['Minor_Category'], x['DisplayName'])):
        if displayed_count >= 100:
            report.append(f"| ... | ... | ... | ... | ... | ... |")
            report.append(f"| 说明 | 共{total_classified}个软件,此处显示前100个 | | | | |")
            break
        
        report.append(f"| {software['Major_Category']} | {software['Minor_Category']} | {software['DisplayName']} | {software['DisplayVersion']} | {software['Publisher']} | {software['ScanSource']} |")
        displayed_count += 1
    
    # 保存报告
    with open(report_file, 'w', encoding='utf-8') as f:
        f.write('\n'.join(report))
    
    return report_file

def main():
    """主函数 - 全面软件扫描和分类"""
    
    print("=" * 80)
    print("          Windows全面软件扫描与分类工具")
    print("=" * 80)
    print("扫描策略:")
    print("✓ 扫描系统级32位软件 (HKLM)")
    print("✓ 扫描系统级64位软件 (HKLM WOW6432Node)") 
    print("✓ 扫描用户级软件 (HKCU)")
    print("✓ 宽松的分类策略,确保高覆盖率")
    print("✓ 详细的分类报告")
    print("=" * 80)
    print()
    
    try:
        # 步骤1: 全面扫描软件
        print("步骤1/3: 正在全面扫描已安装软件...")
        software_list = get_all_installed_software()
        print()
        
        if not software_list:
            print("警告: 未发现任何软件!")
            print("可能原因:")
            print("1. 权限不足 - 请以管理员权限运行")
            print("2. 系统配置问题")
            print("3. 注册表访问限制")
            return None, None
        
        # 步骤2: 加载分类体系
        print("步骤2/3: 正在加载分类体系...")
        taxonomy = create_comprehensive_taxonomy()
        special_cases = get_enhanced_special_cases()
        print(f"✓ 加载了 {len(taxonomy)} 个大类,{sum(len(minors) for minors in taxonomy.values())} 个小类")
        print(f"✓ 加载了 {len(special_cases)} 个特殊处理规则")
        print()
        
        # 步骤3: 对所有软件进行分类
        print("步骤3/3: 正在对软件进行分类...")
        classified_list = []
        
        total_software = len(software_list)
        for i, software in enumerate(software_list, 1):
            major, minor = classify_software_comprehensive(
                software['DisplayName'],
                software['Publisher'],
                taxonomy,
                special_cases
            )
            
            classified_software = software.copy()
            classified_software['Major_Category'] = major
            classified_software['Minor_Category'] = minor
            classified_list.append(classified_software)
            
            # 显示进度
            progress = (i / total_software) * 100
            print(f"\r进度: {progress:.1f}% - {software['DisplayName']} → {major} > {minor}", end='')
        
        print("\n分类完成!")
        print()
        
        # 保存详细结果到CSV
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        csv_file = f"Comprehensive_Software_Classification_{timestamp}.csv"
        
        with open(csv_file, 'w', newline='', encoding='utf-8-sig') as f:
            fieldnames = ['Major_Category', 'Minor_Category', 'DisplayName', 'DisplayVersion', 
                         'Publisher', 'InstallLocation', 'InstallDate', 'UninstallString', 'ScanSource']
            writer = csv.DictWriter(f, fieldnames=fieldnames)
            
            writer.writeheader()
            for software in classified_list:
                # 确保所有字段都存在
                row = {field: software.get(field, '') for field in fieldnames}
                writer.writerow(row)
        
        print(f"✓ 详细分类结果已保存到: {csv_file}")
        
        # 生成详细报告
        report_file = generate_detailed_report(software_list, classified_list)
        print(f"✓ 详细分类报告已生成: {report_file}")
        
        print()
        print("=" * 80)
        print("扫描和分类总结:")
        print("=" * 80)
        
        # 统计总结
        major_counts = {}
        for software in classified_list:
            major = software['Major_Category']
            major_counts[major] = major_counts.get(major, 0) + 1
        
        print(f"📊 扫描统计:")
        print(f"   - 总共扫描软件: {len(classified_list)}个")
        
        # 按来源统计
        source_counts = {}
        for software in classified_list:
            source = software['ScanSource']
            source_counts[source] = source_counts.get(source, 0) + 1
        
        for source, count in source_counts.items():
            print(f"   - {source}: {count}个")
        
        print(f"\n📋 分类统计:")
        for major, count in sorted(major_counts.items(), key=lambda x: x[1], reverse=True):
            percentage = (count / len(classified_list)) * 100
            print(f"   - {major}: {count}个 ({percentage:.1f}%)")
        
        unclassified_count = major_counts.get('其他软件', 0)
        coverage_rate = ((len(classified_list) - unclassified_count) / len(classified_list)) * 100
        print(f"\n✅ 分类质量:")
        print(f"   - 分类覆盖率: {coverage_rate:.1f}%")
        print(f"   - 成功分类: {len(classified_list) - unclassified_count}个")
        print(f"   - 未分类: {unclassified_count}个")
        
        print("=" * 80)
        
        return csv_file, report_file
        
    except Exception as e:
        print(f"\n程序运行出错: {e}")
        import traceback
        traceback.print_exc()
        return None, None

if __name__ == "__main__":
    # 检查是否在Windows系统上运行
    if sys.platform != 'win32':
        print("❌ 本脚本只能在Windows系统上运行,因为需要访问Windows注册表")
        sys.exit(1)
    
    # 检查是否以管理员权限运行
    try:
        if not os.environ.get('PROCESSOR_ARCHITEW6432', ''):
            import ctypes
            if ctypes.windll.shell32.IsUserAnAdmin() == 0:
                print("⚠️ 警告: 建议以管理员权限运行,以获取完整的软件列表")
                print("         非管理员权限可能无法访问某些系统级软件信息")
                print()
    except:
        pass
    
    main()
相关推荐
吴声子夜歌1 小时前
Java数据结构与算法——基本数学问题
java·开发语言·windows
这儿有一堆花5 小时前
用原生脚本编写无害恶作剧
windows
因我你好久不见5 小时前
Windows部署springboot jar支持开机自启动
windows·spring boot·jar
夜流冰5 小时前
Excel - MS Support for Excel: 2 Collaborate
数据库·windows·excel
林瞅瞅6 小时前
PowerShell 启动卡顿?内存飙升?原来是 800MB 的历史记录在作祟!
windows
Shepherd06196 小时前
【Windows Server 实战】WAC 反向代理配置
windows
云小逸6 小时前
【windows系统编程】第一章 Windows 系统核心架构与基础概念
windows·架构
怣疯knight8 小时前
Docker Desktop 4.55.0版本安装成功教程
windows·docker
liulilittle9 小时前
VEthernet 框架实现 tun2socks 的技术原理
网络·windows·c#·信息与通信·通信
zhangfeng11339 小时前
spss 性别类似的二分类变量 多分类变量 做线性回归分析
分类·数据挖掘·线性回归