目录
本文提供了一个专为 Windows 系统设计的强大 Python 脚本,能够通过多种智能途径快速准确地定位系统中安装的可执行文件(.exe)路径。该工具集成了四种不同的查找策略,确保在复杂的企业环境或个人电脑中都能可靠地找到目标程序。
核心功能特点
🔍 多维度智能搜索
采用四级递进式搜索策略,确保查找结果的准确性和完整性:
- 运行进程查询 - 通过 PowerShell 获取当前正在运行的指定进程路径
- 注册表分析 - 深度扫描系统卸载注册表项,获取软件安装信息
- 开始菜单检索 - 解析所有用户的开始菜单快捷方式,找到程序链接
- 程序目录扫描 - 在 Program Files 及相关目录中进行深度文件搜索
⚡ 高效智能的去重机制
- 自动去除重复路径,保持发现顺序
- 支持路径标准化和大小写不敏感匹配
- 实时验证路径有效性,确保返回结果都可直接使用
🛡️ 完善的错误处理
- 全面的异常捕获和处理机制
- 权限错误的优雅降级处理
- 支持模糊匹配和部分名称搜索
典型应用场景
软件开发与自动化
- 自动化软件部署和配置
- 开发环境中依赖程序的自动检测
- 持续集成/持续部署(CI/CD)流水线
系统管理与维护
- 企业环境中的软件资产清点
- 多版本程序管理
- 故障排查和系统恢复
终端用户便利
- 快速找到已安装但忘记位置的程序
- 创建自定义脚本和快捷方式
- 批量处理和组织应用程序
技术亮点
- 跨架构支持:同时处理 32 位和 64 位应用程序
- 多用户兼容:支持当前用户和所有用户的程序查找
- 智能过滤:自动跳过系统目录和无关项目,提高搜索效率
- 编码安全:正确处理系统区域设置和文件编码
附工具源码:
import win32com.client as win32
import re
import string
import subprocess
import locale
import winreg
import os
import win32com.client
def getExeExecutablePath(exe_name: str) -> list[str]:
"""
获取正在运行的指定可执行文件路径(支持模糊匹配)
Args:
exe_name:要查找的进程名(如"chrome.exe"),支持模糊匹配
Returns:
按发现顺序排列的进程路径列表(去重)
"""
safe_name = exe_name.strip().replace(""", '').replace(""", "")
if not safe_name:
return []
command = [
"powershell.exe",
"-Command",
f"Get-CimInstance Win32_Process | "
f"Where-Object {{ $_.Name -ilike '*{safe_name}*' }} | "
f"Select-Object -ExpandProperty ExecutablePath | "
f"Sort-Object -Unique"
]
try:
result = subprocess.run(
command,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
encoding=locale.getpreferredencoding(False),
creationflags=subprocess.CREATE_NO_WINDOW
)
except subprocess.CalledProcessError:
return []
except FileNotFoundError:
return []
# 处理输出结果
paths = []
seen = set()
for line in result.stdout.splitlines():
clean_path = line.strip()
if clean_path and os.path.exists(clean_path):
# 保持顺序的去重逻辑
if clean_path not in seen:
seen.add(clean_path)
paths.append(clean_path)
return paths
def findExeFromRegUninstallPath(exe_name: str) -> list[str]:
"""从注册表卸载项中查找包含指定exe的安装路径(已合并为单个函数)
Args:
exe_name: 目标exe文件名(如"chrome.exe"),不区分大小写
Returns:
按发现顺序排列的有效路径列表(自动去重)
"""
result = []
seen = set()
pattern = re.compile(re.escape(exe_name), re.IGNORECASE)
registry_paths = [
(winreg.HKEY_LOCAL_MACHINE, r"SOFTWAREMicrosoftWindowsCurrentVersionUninstall"),
(winreg.HKEY_LOCAL_MACHINE, r"SOFTWAREWOW6432NodeMicrosoftWindowsCurrentVersionUninstall"),
(winreg.HKEY_CURRENT_USER, r"SoftwareMicrosoftWindowsCurrentVersionUninstall")
]
for root, path in registry_paths:
try:
with winreg.OpenKey(root, path) as main_key:
for i in range(winreg.QueryInfoKey(main_key)[0]):
subkey_name = winreg.EnumKey(main_key, i)
# 跳过系统组件
if subkey_name.startswith(("{", "KB")) or "microsoft" in subkey_name.lower():
continue
try:
with winreg.OpenKey(main_key, subkey_name) as subkey:
# 检查多个可能的键值
for value_name in ["DisplayIcon", "InstallLocation", "UninstallString"]:
try:
raw_value = winreg.QueryValueEx(subkey, value_name)[0]
except FileNotFoundError:
continue
# 清理路径字符串
clean_path = re.split(r'[,#]', raw_value.split('"')[-1])[0].strip()
if not clean_path:
continue
# 处理目录路径的情况
if os.path.isdir(clean_path):
for root_dir, _, files in os.walk(clean_path):
for file in files:
if file.lower().endswith(".exe") and pattern.search(file):
full_path = os.path.join(root_dir, file)
if full_path not in seen:
seen.add(full_path)
result.append(full_path)
break
else:
if pattern.search(clean_path) and os.path.exists(clean_path):
if clean_path not in seen:
seen.add(clean_path)
result.append(clean_path)
except (OSError, PermissionError):
continue
except (FileNotFoundError, PermissionError):
continue
return result
def findExeFromStartMenuLnk(exe_name: str) -> list[str]:
"""
从系统开始菜单快捷方式中查找包含指定exe名称的路径
Args:
exe_name: 要查找的可执行文件名(如"notepad.exe")
Returns:
按路径出现顺序排列的匹配项列表,无重复项
"""
shell = win32com.client.Dispatch("WScript.Shell")
try:
# 动态获取所有用户的开始菜单路径
start_menu_path = shell.SpecialFolders("AllUsersPrograms")
except Exception:
# 回退到默认路径
start_menu_path = r"C:\ProgramData\Microsoft\Windows\Start Menu\Programs"
ignore_dirs = {
"Accessibility", "Accessories", "System Tools",
"Administrative Tools", "Windows Kits",
"Debugging Tools for Windows (X64)",
"Debugging Tools for Windows (X86)",
"Windows PowerShell"
}
exe_paths = []
seen = set() # 用于去重的集合
for root, dirs, files in os.walk(start_menu_path):
# 实时过滤子目录(原地修改dirs列表)
dirs[:] = [d for d in dirs if d not in ignore_dirs]
for filename in files:
# 先进行扩展名过滤提升效率
if not filename.lower().endswith(".lnk"):
continue
full_path = os.path.join(root, filename)
try:
# 获取快捷方式目标
shortcut = shell.CreateShortCut(full_path)
target_path = shortcut.TargetPath
except Exception:
continue # 跳过无效快捷方式
# 有效性检查
if not target_path or not os.path.exists(target_path):
continue
# 智能路径匹配(处理短路径和长路径)
normalized_path = os.path.normpath(target_path).lower()
search_key = exe_name.strip().lower()
# 同时匹配文件名和完整路径
if (search_key in normalized_path or
search_key == os.path.basename(normalized_path).lower()):
if target_path not in seen:
seen.add(target_path)
exe_paths.append(target_path)
return exe_paths
def getExeFromProgramFilesDir(exe_name: str, depth: int = 4) -> list[str]:
"""在系统Program Files类目录中查找指定exe文件
Args:
exe_name: 目标文件名或关键词(如"chrome"或"chrome.exe"),不区分大小写
depth: 最大搜索深度(0=仅ProgramFiles根目录),默认4层子目录
Returns:
按发现顺序排列的有效路径列表(自动去重)
"""
found_paths = []
seen_paths = set()
target = str(exe_name.strip().lower()).replace(".exe", '')
program_dirs = {
os.path.normcase(os.path.normpath(p))
for env_var in ["ProgramFiles", "ProgramFiles(x86)", "ProgramW6432"]
if (p := os.environ.get(env_var)) and os.path.exists(p)
}
for drive in (f"{d}:/" for d in string.ascii_uppercase if os.path.exists(f"{d}:/")):
try:
with os.scandir(drive) as entries:
program_dirs.update(
os.path.normcase(entry.path)
for entry in entries
if entry.is_dir()
and "program" in (name := entry.name.lower())
and any(k in name for k in {"file", "files"})
)
except OSError:
continue
for base_dir in program_dirs:
if not os.path.isdir(base_dir):
continue
try:
for root, dirs, files in os.walk(base_dir, topdown=True):
rel_path = os.path.relpath(root, base_dir)
current_depth = rel_path.count(os.sep) if rel_path != "." else 0
if current_depth > depth:
dirs.clear()
continue
for file in (f for f in files if f.lower().endswith(".exe")):
if target not in file.lower():
continue
full_path = os.path.normpath(os.path.join(root, file))
if (norm_path := os.path.normcase(full_path)) not in seen_paths:
seen_paths.add(norm_path)
found_paths.append(full_path)
except PermissionError:
continue
return found_paths
def findExeFile(exe_name: str, depth: int = 4) -> list[str]:
"""按照"正在运行->注册表->开始菜单->program files目录"的顺序,查找exe文件所在路径
Args:
exe_name: 目标文件名(含.exe或不含均可)
depth: 仅影响最后一级目录搜索深度
Returns:
去重后的路径列表(保持发现顺序)
"""
target = exe_name.lower().rstrip(".exe")
check_functions = [
lambda: getExeExecutablePath(target),
lambda: findExeFromRegUninstallPath(target),
lambda: findExeFromStartMenuLnk(target),
lambda: getExeFromProgramFilesDir(target, depth)
]
seen = set()
for func in check_functions:
if paths := [p for p in func() if (np := os.path.normpath(p)) not in seen and not seen.add(np)]:
return paths
return []
17万+

被折叠的 条评论
为什么被折叠?



