有趣的问题。
与往常一样,有多种方法可以获取这些应用程序的列表,每种方法都有其特定的优点和缺点。
使用窗口列表获取启动器中表示的进程列表
由于只有带有(映射)窗口的应用程序才会显示在启动器中,因此请使用:
wmctrl -lp
(wmctrl
默认情况下未安装),我们可以获得打开的窗口的列表以及该窗口所属的进程ID。输出格式为:
0x05204641 0 12618 jacob-System-Product-Name verhaal (~) - gedit
对我们而言,最重要的信息在哪里:
- 第一个字符串(
0x05204641
); 这是窗口-id
- 第三个字符串(
12618
); 这是窗口所属的进程ID(pid),并且
- 最后一节(
verhaal (~) - gedit
); 这是窗口名称。
有了pid后,我们可以通过以下命令查找相应的进程名称:
ps -p <pid> -o comm=
我们可以编写上述步骤的脚本,并列出现有窗口的输出,如下所示(使用python
):
{'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'thunderbird', 'soffice.bin'}
并发症
这似乎很简单。但是,一如既往,现实有点复杂。我们需要注意一些例外情况和复杂情况:
- 一些窗口将属于pid 0,这将在尝试获取其属性时引发错误。的视窗
Idle
(python
IDE),或者tkinter
是这样的窗口。
- 某些窗口不是“真实”窗口,也不是诸如临时窗口(从其他窗口调用并属于其他窗口的窗口)之类的窗口,例如台式机本身。这些窗口在的输出中被列为窗口
wmctrl
,但在Dash中不会单独出现。
- 在某些情况下,应用程序的名称与进程名称完全不同,例如,
LibreOffice
在所有模块的进程名称均为的情况下soffice.bin
。同时,运行命令 soffice.bin
将不起作用。如果你需要识别模块(Calc
,Writer
等)分开,你需要得到更多的信息,从该窗口的名称,例如。
- 另一个示例是的名称
gnome-terminal
,显示在流程列表中,如的输出所示ps -e ww
。在14.04中,gnome-terminal
显示为gnome-terminal
,但是在15.04 / 15.10中显示:/usr/lib/gnome-terminal/gnome-terminal-server
。
我们至少需要解决的问题
要解决以上最重要的问题,您需要:
添加一个检查窗口是否为“真实”或“正常”窗口,并使用
xprop -id <window_id>
如果输出包含以下行:
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
该窗口在Unity Launcher的意义上是有效的窗口
- 要修复
gnome-terminal
in 的流程名称15.x
(假设您希望显示的流程名称为gnome-terminal
),我们需要添加一个例外,gnome-terminal
如果流程名称显示为,则将其重命名为
/usr/lib/gnome-terminal/gnome-terminal-server
脚本
#!/usr/bin/env python3
import subprocess
import sys
try:
listed = sys.argv[1]
except IndexError:
listed = []
get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()
def check_wtype(w_id):
# check the type of window; only list "NORMAL" windows
return "_NET_WM_WINDOW_TYPE_NORMAL" in get(["xprop", "-id", w_id])
def get_process(w_id):
# get the name of the process, owning the window
proc = get(["ps", "-p", w_id, "-o", "comm="])
proc = "gnome-terminal" if "gnome-terminal" in proc else proc
return proc
wlist = [l.split() for l in subprocess.check_output(["wmctrl", "-lp"])\
.decode("utf-8").splitlines()]
validprocs = set([get_process(w[2]) for w in wlist if check_wtype(w[0]) == True])
if listed == "-list":
for p in validprocs:
print(p)
else:
print(validprocs)
如何使用
该脚本需要wmctrl
:
sudo apt-get install wmctrl
将上面的脚本复制到一个空文件中,另存为 get_running.py
通过以下命令运行它:
python3 /path/to/get_running.py
它将输出如下:
{'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'thunderbird', 'soffice.bin'}
或者,使用参数运行-list
:
thunderbird
nautilus
gnome-terminal
firefox
gedit
GuitarPro.exe
soffice.bin
笔记
从您的问题来看,尚不完全清楚找到列表的目的是什么。如果需要使用应用程序的名称(如界面中显示的名称)(“可读”名称),则可以采用完全不同的方法:
- 所有全局安装的应用程序都在中有一个
.desktop
文件/usr/share/applications
。在大多数情况下,我们可以从文件中得出应用程序的进程名称和接口名称.desktop
。使用此信息,我们可以相对容易地创建一个正在运行的GUI应用程序列表,以它们的“可读”名称表示。
此外,在这种情况下,然而,现实中也比较复杂那么理论,为解释在这里。