You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python自动执行系统已安装应用:随机或前3个启动方案

当然可以实现!下面我会一步步帮你改造代码,实现随机选取或选取前3个应用自动执行的功能,同时也会解决原代码里的一些潜在问题。

首先得提一句:你原来用的wmi.Win32_Product()其实不太推荐——这个WMI类会触发Windows Installer的一致性检查,不仅运行慢,还可能意外触发MSI修复操作。更可靠的方式是从系统注册表读取已安装应用信息,我会在代码里兼顾两种方式,但优先推荐注册表方案。

完整实现代码

import wmi
import random
import subprocess
import winreg
import os

def get_installed_apps_via_registry():
    """从注册表获取已安装应用(推荐方式)"""
    installed_apps = []
    # 检查32位和64位系统的注册表路径,以及HKLM/HKCU
    hives = [(winreg.HKEY_LOCAL_MACHINE, "HKLM"), (winreg.HKEY_CURRENT_USER, "HKCU")]
    uninstall_paths = [
        r"Software\Microsoft\Windows\CurrentVersion\Uninstall",
        r"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
    ]
    
    for hive, hive_name in hives:
        for path in uninstall_paths:
            try:
                root_key = winreg.OpenKey(hive, path)
                subkey_count = winreg.QueryInfoKey(root_key)[0]
                
                for i in range(subkey_count):
                    try:
                        subkey_name = winreg.EnumKey(root_key, i)
                        subkey = winreg.OpenKey(root_key, subkey_name)
                        
                        # 获取应用名称(必填项)
                        display_name = winreg.QueryValueEx(subkey, "DisplayName")[0]
                        # 获取版本和厂商(可选)
                        version = winreg.QueryValueEx(subkey, "DisplayVersion")[0] if "DisplayVersion" in [val[0] for val in winreg.EnumValue(subkey)] else "未知版本"
                        vendor = winreg.QueryValueEx(subkey, "Publisher")[0] if "Publisher" in [val[0] for val in winreg.EnumValue(subkey)] else "未知厂商"
                        
                        installed_apps.append({
                            "name": display_name,
                            "version": version,
                            "vendor": vendor,
                            "subkey": f"{hive_name}\\{path}\\{subkey_name}"
                        })
                    except (FileNotFoundError, OSError):
                        # 跳过没有DisplayName的项
                        continue
                    finally:
                        winreg.CloseKey(subkey)
            except FileNotFoundError:
                continue
            finally:
                winreg.CloseKey(root_key)
    return installed_apps

def get_installed_apps_via_wmi():
    """用WMI Win32_Product获取应用(不推荐,仅兼容原代码)"""
    w = wmi.WMI()
    installed_apps = []
    for p in w.Win32_Product():
        installed_apps.append({
            "name": p.Caption,
            "version": p.Version,
            "vendor": p.Vendor,
            "install_location": p.InstallLocation
        })
    return installed_apps

def get_app_executable_path(app_info):
    """根据应用信息查找可执行文件路径"""
    # 如果是注册表获取的应用,优先从DisplayIcon或InstallLocation找
    if "subkey" in app_info:
        hive_str, subkey_path = app_info["subkey"].split("\\", 1)
        hive = winreg.HKEY_LOCAL_MACHINE if hive_str == "HKLM" else winreg.HKEY_CURRENT_USER
        
        try:
            subkey = winreg.OpenKey(hive, subkey_path)
            # 尝试读取DisplayIcon(通常包含exe路径,格式可能是"path.exe,0")
            try:
                display_icon = winreg.QueryValueEx(subkey, "DisplayIcon")[0]
                if "," in display_icon:
                    exe_path = display_icon.split(",")[0].strip('"')
                else:
                    exe_path = display_icon.strip('"')
                if os.path.exists(exe_path):
                    return exe_path
            except FileNotFoundError:
                pass
            
            # 尝试从InstallLocation查找exe文件
            try:
                install_location = winreg.QueryValueEx(subkey, "InstallLocation")[0]
                if install_location and os.path.exists(install_location):
                    # 遍历目录找包含应用名的exe(简单匹配)
                    for root, _, files in os.walk(install_location):
                        for file in files:
                            if file.endswith(".exe") and app_info["name"].lower() in file.lower():
                                return os.path.join(root, file)
                        # 只遍历一级目录,避免过慢
                        break
            except FileNotFoundError:
                pass
        finally:
            winreg.CloseKey(subkey)
    # 如果是WMI获取的应用,从InstallLocation查找
    elif "install_location" in app_info and app_info["install_location"]:
        install_location = app_info["install_location"]
        if os.path.exists(install_location):
            for root, _, files in os.walk(install_location):
                for file in files:
                    if file.endswith(".exe") and app_info["name"].lower() in file.lower():
                        return os.path.join(root, file)
                break
    return None

def execute_selected_apps(selected_apps):
    """执行选中的应用"""
    for app in selected_apps:
        exe_path = get_app_executable_path(app)
        if exe_path:
            print(f"✅ 正在启动 {app['name']}...")
            # 用subprocess.Popen后台启动应用,不会阻塞脚本
            subprocess.Popen(exe_path)
        else:
            print(f"❌ 无法找到 {app['name']} 的可执行文件路径")

if __name__ == "__main__":
    # 选择获取应用的方式:推荐用注册表方式
    # installed_apps = get_installed_apps_via_wmi()
    installed_apps = get_installed_apps_via_registry()
    
    if not installed_apps:
        print("未找到已安装的应用")
        exit()
    
    # --- 选取逻辑二选一 ---
    # 1. 选取前3个应用
    selected_apps = installed_apps[:3] if len(installed_apps) >=3 else installed_apps
    
    # 2. 随机选取3个应用(如果总数不足3则全选)
    # selected_apps = random.sample(installed_apps, min(3, len(installed_apps)))
    
    print(f"已选中 {len(selected_apps)} 个应用:")
    for idx, app in enumerate(selected_apps, 1):
        print(f"{idx}. {app['name']} - {app['version']} ({app['vendor']})")
    
    # 执行选中的应用
    execute_selected_apps(selected_apps)

关键说明

  • 应用列表获取:优先用get_installed_apps_via_registry(),避免Win32_Product的副作用;如果需要兼容原代码,再用WMI方式。
  • 选取逻辑:代码里提供了两种方式,注释掉不需要的即可——前3个直接切片,随机选用random.sample保证不重复。
  • 执行应用:通过get_app_executable_path函数从注册表的DisplayIcon或安装目录查找可执行文件,解决了Win32_Product没有直接exe路径的问题。
  • 启动方式:用subprocess.Popen后台启动应用,脚本不会被阻塞,可以继续执行其他操作。

内容的提问来源于stack exchange,提问作者JJJ

火山引擎 最新活动