Python从Windows进程/开始菜单/注册表/ProgramFiles目录,根据指定exe文件名称,找到该exe文件所在路径

Python从Windows进程/开始菜单/注册表/ProgramFiles目录,根据指定exe文件名称,找到该exe文件所在路径
这种莫名其妙的需求,来自于每次调用下载程序,要调用的下载程序exe文件不知道安装到哪里去了(甚至可能是绿色版的,就没安装过)

从Windows进程中查找应用程序安装路径

import subprocess
import locale
    
def getExeExecutablePath(exeName):
    """
    要获取的exe必须在运行,才能从进程中获取到
    匹配模式:包含并忽略大小写
    返回list
    """
    patharr = list()
    command = f'''wmic process where "name like '%{exeName}%'" get executablepath'''
    p = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,)
    stdout = p.communicate()[0].decode(locale.getpreferredencoding())
    arr = [i.strip() for i in stdout.split('\n') if i.strip() not in ['ExecutablePath','']]
    for i in arr:
        if i not in patharr:
            patharr.append(i)
    return patharr

getExeExecutablePath("chrome")

返回结果

['C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe']

locale.getpreferredencoding()获取一下系统编码,用于返回数据的解码,避免乱码。
subprocess.Popen是通过子进程的方式,实现类型命令行执行,加上stdout=subprocess.PIPE是为了拿到输出内容。

从Windows注册表已安装程序注册的卸载路径中查找应用程序安装路径

涉及到注册表操作,官网文档比较简单函数也不多,没找到直接能取出所有包含项目的方法,所以用了winreg.QueryInfoKey取项目数量,然后遍历逐项提取,才实现了遍历查找。

import winreg
def findExeFromRegUninstallPath(exeName):
    """
    从注册表卸载路径中获取exe文件路径
    匹配模式:包含并忽略大小写
    返回list
    """
    pathArr = list()
    # 取出卸载路径上层的key值
    regPath = r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
    key = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE, regPath)
    # 取出key包含项目数,并枚举每一项
    for i in range(winreg.QueryInfoKey(key)[0]):
        item = winreg.EnumKey(key,i) # 取出项目名
        if item[0]!='{': # 屏蔽非用户安装的系统项目
            # 取key值以取出对应DisplayIcon位置
            key1 = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE, regPath+'\\'+item) 
            try:
                # 取出图标命名中的路径部分
                exePath = winreg.QueryValueEx(key1, "DisplayIcon")[0].split(',')[0].strip().strip('"').strip()
                if exeName.lower() in exePath.lower():
                    pathArr.append(exePath)
            except FileNotFoundError as e:
                pass
            winreg.CloseKey(key1)
    winreg.CloseKey(key)
    return pathArr
findExeFromRegUninstallPath("Chrome")

返回结果

['C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe']

从Windows Start Menu查找应用程序安装路径

基本就是遍历查询,只有从lnk中取出指向路径,算是个比较罕见的操作。

import os
import sys
import win32com.client 

def findExeFromStartMenuLnk(exeName):
    """
    从Start Menu获取exe文件路径
    匹配模式:包含并忽略大小写
    返回list
    """
    pathArr = list()
    # 开始菜单文件夹
    path = r'C:\ProgramData\Microsoft\Windows\Start Menu\Programs'
    # 忽略下一系统自带原生程序文件夹名
    ignorePath = [
        'Accessibility',
        'Accessories',
        'System Tools',
        'Administrative Tools',
        'Windows Kits',
        'Debugging Tools for Windows (X64)',
        'Debugging Tools for Windows (X86)',
        'Windows PowerShell',
    ]
    shell = win32com.client.Dispatch("WScript.Shell")
    # 遍历文件夹,取出所有lnk图标
    for record in os.walk(path):
        dirname = record[0]
        if dirname.split('\\')[-1] in ignorePath:
            continue
        for filename in record[2]:
            filepath = os.path.join(dirname, filename)
            filepath = os.path.abspath(filepath)
            # 从lnk中取出指向路径
            if os.path.splitext(filepath)[1]=='.lnk':
                shortcut = shell.CreateShortCut(filepath)
                exePath = shortcut.Targetpath
                # 包含且不重复的,加入到返回列表
                if exeName.lower() in exePath.lower() and exePath not in pathArr:
                    pathArr.append(exePath)
    return pathArr

findExeFromStartMenuLnk('chrome')

返回结果

['C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe']

遍历常见安装路径(针对绿色安装的)

思路是所有磁盘根目录下,前3-5层目录中的exe文件,这个比较简单,参照Start Menu里面的遍历写法即可,因为目前还没有这种需求先不写了。
2021-07-15 早上有空顺便写了,实际写出来发现想的简单了,os.walk迭代器,遍历结果过于庞大,各种应用程序附带的零碎文件实在太多,考虑到效率需要限制文件夹挖掘深度。
【注意】这里我们假设,程序厂商或用户遵守常识,将程序放在了系统默认的"Program*File*"这样的目录下

def getExeFromProgramFilesDir(exeName, deepth=4):
    """
    从所有磁盘根目录下,文件夹名同时包含'program'和'file'的文件夹中,获取exe文件。
    考虑到效率问题,设置挖掘深度
    匹配模式:包含并忽略大小写
    返回list
    """
    pathArr = list()
    exeName = exeName.lower()
    # 找出所有磁盘驱动器
    driveArr = [f'{c}:\\' for c in string.ascii_uppercase if os.path.exists(f'{c}:')]
    # 遍历找出所有ProgramFilew文件夹
    programfileArr = list()
    for drive in driveArr:
        for d in os.listdir(drive):
            d = drive + d
            dlower = d.lower()
            if 'program' in dlower and 'file' in dlower and os.path.isdir(d):
                programfileArr.append(d)
    # 遍历ProgramFiles文件夹
    for pf in programfileArr:
        for root, dirs, files in os.walk(pf):
            if root[len(pf):].count('\\') == deepth:  # 限制遍历深度,1层表示当前文件夹;2表示当前及当前子文件夹;依此类推...
                del dirs[:]
            else:
                for i in files:
                    ilower = i.lower()
                    if ilower[-4:] == '.exe' and exeName in ilower:
                        pathArr.append(os.path.join(root, i))
    return pathArr

总结

来个大合集

def findExeFile(exeName, deepth=4):
    """
    按照'正在运行 > 注册表 > 开始菜单 > programfiles目录'的顺序,查找exe文件所在路径
    按照该顺序去重后返回结果
    匹配模式:包含并忽略大小写
    返回list
    """
    pathArr = getExeExecutablePath(exeName) + \
        findExeFromRegUninstallPath(exeName) + \
        findExeFromStartMenuLnk(exeName) + \
        getExeFromProgramFilesDir(exeName, deepth=deepth)
    distinctPathArr = list()
    for i in pathArr:
        if i not in distinctPathArr:
            distinctPathArr.append(i)
    return distinctPathArr
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值