获取最顶层窗口的 pid 和详细信息

发布于 2024-08-17 14:43:23 字数 103 浏览 11 评论 0原文

有谁知道如何获取顶部活动窗口的 PID,然后如何使用 PID 获取窗口的属性?我的意思是进程名称、程序名称等属性。

我在 Linux (Ubuntu 9.10) 下使用 Qt。

Does anyone know how to get the PID of the top active window and then how to get the properties of the window using the PID? I mean properties like process name, program name, etc.

I'm using Qt under Linux (Ubuntu 9.10).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

冰火雁神 2024-08-24 14:43:23

Linux 中有一个名为 xprop 的命令,它是一个用于在 X 服务器中显示窗口属性的实用程序。在 Linux 中,xprop -root 为您提供根 Windows 属性以及其他活动程序。那么您可以使用以下命令获取活动窗口的 ID:

xprop -root | grep _NET_ACTIVE_WINDOW\(WINDOW\)

要获取活动窗口 ID(行首不带“_NET_ACTIVE_WINDOW(WINDOW): window id #”),请使用此命令:

xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'

现在您可以将此命令输出保存在用户定义的变量中:

myid=xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'

xprop 有一个属性 call -id。该参数允许用户在命令行上选择窗口 ID。我们应该在输出中查找 _NET_WM_PID(CARDINAL) ...因此我们使用此命令:

xprop -id $myid | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'

这将为您提供最顶层的活动窗口进程 ID。

更加狡猾,只需 1 个命令即可完成所有操作...:

 xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'

现在我可以使用 popen 函数通过我的 C++ 程序(在 Linux 中)运行这些命令,抓取 stdout 并打印或保存它。 popen 创建一个管道,以便我们可以读取正在调用的程序的输出。

(您还可以使用“/proc”文件系统并获取 PID 的更多详细信息(“/proc/YOUR_PID/status”))

#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;

inline std::string exec(char* cmd) {
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[128];
    std::string result = "";
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
                result += buffer;
    }
    pclose(pipe);
    return result;
}

int main()
{
    //we uses \\ instead of \ ( \ is a escape character ) in this string
 cout << exec("xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\\(WINDOW\\)/{print $NF}') | awk '/_NET_WM_PID\\(CARDINAL\\)/{print $NF}'").c_str(); 
 return 0;
}

there is a command in linux call xprop which is a utility for displaying window properties in an X server. In linux xprop -root gives you the root windows properties and also other active programs. then you can get the ID of the active window using this command:

xprop -root | grep _NET_ACTIVE_WINDOW\(WINDOW\)

to get just the active window ID ( without "_NET_ACTIVE_WINDOW(WINDOW): window id # " in the beginning of the line ) use this command:

xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'

now you can save this command output in a user defined variable:

myid=xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'

xprop have an attribute call -id. This argument allows the user to select window id on the command line. We should look for _NET_WM_PID(CARDINAL) in output ... so we use this command:

xprop -id $myid | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'

this gives you the topmost active window process ID.

to be more trickey and do all things in just 1 command ... :

 xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'

Now I can run these commands via my C++ program ( in linux ) using popen function, grab stdout and print or save it. popen creates a pipe so we can read the output of the program we are invoking.

( you can also use '/proc' file system and get more detail of a PID ('/proc/YOUR_PID/status') )

#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;

inline std::string exec(char* cmd) {
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[128];
    std::string result = "";
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
                result += buffer;
    }
    pclose(pipe);
    return result;
}

int main()
{
    //we uses \\ instead of \ ( \ is a escape character ) in this string
 cout << exec("xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\\(WINDOW\\)/{print $NF}') | awk '/_NET_WM_PID\\(CARDINAL\\)/{print $NF}'").c_str(); 
 return 0;
}
第七度阳光i 2024-08-24 14:43:23

X 的特点之一是它是网络透明的。顶部显示的实际窗口(具有焦点)很可能正在您自己的计算机以外的计算机上运行,​​在这种情况下,窗口内运行的进程的进程 ID 在您的计算机上将毫无意义。

你能详细说明一下你想做什么吗?我认为这里缺少一些细节。理想情况下,您应该在 X 级别而不是特定于机器的级别工作。

One of things about X is that it's network transparent. It's quite possible that the actual window being displayed at the top (which has focus) is running on a machine other than your own in which case, the process id of the process running inside the window will make no sense on your machine.

Can you elaborate a little on what you want to do? I think there are some missing details here. Ideally, you should work at the X level rather than at the machine specific one.

匿名的好友 2024-08-24 14:43:23

我参加聚会已经很晚了,但我也遇到了类似的问题,我认为这可以帮助其他有同样问题的人。
有一个命令行技巧可以做到这一点,您可以尝试 execvp'ing 它,或者执行它,将输出重定向到您的代码,

xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME WM_CLASS

给出窗口名称以及程序名称。
例如,对于这个选项卡,它给了我

_NET_WM_NAME(UTF8_STRING) = "linux - Getting pid and details for topmost window - Stack Overflow - Mozilla Firefox"

WM_CLASS(STRING) = "Navigator", "Firefox"

Am very very late to the party, but I had a similar problem, and I think this can help someone else who has the same problem.
There is a command line trick to do this, you can try execvp'ing it, or executing it redirecting the output to your code

xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME WM_CLASS

gives the window name, as well as the program name.
Eg, for this tab, it gives me

_NET_WM_NAME(UTF8_STRING) = "linux - Getting pid and details for topmost window - Stack Overflow - Mozilla Firefox"

WM_CLASS(STRING) = "Navigator", "Firefox"
一直在等你来 2024-08-24 14:43:23

窗口所有者的 PID 存储在 X 属性 _NET_WM_PID 中。请注意,这只是事实上的标准。

你必须先找到窗口的id,然后才能查询属性。我不知道 QT 为此提供任何抽象,因此您可能必须使用 xlib 或 xcb。

对于初学者来说,可以使用 xprop 工具。

The PID of a window owner is stored in the X property _NET_WM_PID. Note that this is only a de-facto standard.

You have to find the id of the window first, then you can query for the property. I don't know of any abstraction QT provides for this, so you will probably have to use xlib or xcb.

Play with the tool xprop for starters.

疯了 2024-08-24 14:43:23

xlib 的 XGetInputFocus 会告诉您哪个窗口具有焦点,这可能比最上面的窗口更有趣。比照。 Xfree86 的 XGetInputFocus 手册页

如果它确实是最顶层的窗口,而不是您所追求的带焦点的窗口,那么,我认为没有一个简单的调用可以做到这一点,因为 xlib 似乎没有提供任何查询全局的方法堆叠顺序,这是一种数据结构,可以告诉您哪些窗口位于哪些窗口的前面。

一旦您获得了正确的窗口 ID,xprop 就会在 _NET_WM_PID_ 下列出 pid - 尽管并非所有窗口都有这样的属性...

Postscript 更多想法;自从我考虑 xlib 以来已经很长时间了...

总结一下:

  1. X 不提供窗口 id 和 pid 之间的任何可靠关联,并且正如 Noufal 观察到的,窗口在 X 桌面上提供服务可能来自许多不同的机器,并且两个远程客户端可能碰巧使用相同的 PID,因为它对于每台机器来说都是唯一的。比照。 如何从进程 ID 获取 X11 窗口?< /a>

  2. X 似乎没有提供询问哪个窗口是最上面的窗口,或者一个窗口是否遮挡另一个窗口的界面。同样,具有特权访问权限......参见。 如何使用 xlib 识别顶级 X11 窗口?

  3. 常用的窗口管理器和 Qt 不会为您提供对 X 的特权访问

  4. 没有两种方法来查找最顶层窗口 就无法解决问题。

  5. 我们可以找到哪个窗口获得焦点,这可能就是我们想要的。但同样,没有 wid 到 pid 映射...

所以,抱歉,看起来这是无法完成的。

xlib's XGetInputFocus will tell you which window has focus, which is probably more interesting than which is topmost. Cf. Xfree86's XGetInputFocus manpage.

If it's really the topmost window, and not the window-with-focus you're after, well, I don't think there is a simple call to do that, because xlib doesn't seem to offer any way of querying the global stacking order, which is the data structure that tells you which windows are in front of which others.

Once you have the right window id, xprop will list the pid under _NET_WM_PID_ - though not all windows have such a property...

Postscript More thoughts; long time since I've thought about xlib...

To summarise:

  1. X does not offer any reliable association between window ids and pids, and as Noufal observes, the windows served on an X desktop may come from many different machines, and two remote clients might happen to use the same PID, since it is only unique per machine. Cf. How to get an X11 Window from a Process ID?

  2. X does not seem to offer an interface asking which is the topmost window, or whether one window occludes another. Likewise with privileged access... Cf. How to identify top-level X11 windows using xlib?

  3. Commonly available window managers and Qt don't give you privileged access to X

  4. Without both a way of finding the topmost window, and a reliable association of the window id to the matching pid, we can't solve the question.

  5. We can find which window has focus, and this is probably what we want. But again, without the wid to pid map ...

So, sorry, it looks like it can't be done.

向地狱狂奔 2024-08-24 14:43:23

我正在投票 Michel Kogan 的答案,并添加其简明摘要:

ps -o pid,comm,args $(xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}") -f _NET_WM_PID 0c " \$0\\n" _NET_WM_PID | awk "{print \$2}")

上面将显示当前活动的以下内容窗口:PID、命令名称(仅可执行文件名称)、命令及其所有参数。

I am voting up Michel Kogan’s answer, and adding this concise summary of it:

ps -o pid,comm,args $(xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}") -f _NET_WM_PID 0c " \$0\\n" _NET_WM_PID | awk "{print \$2}")

The above will show the following for the currently active window: PID, command name (only the executable name), command with all its arguments.

淡水深流 2024-08-24 14:43:23

我在终端上运行此命令:

sleep 5s; ps -Flwwp $(xdotool getwindowpid $(xdotool getwindowfocus))

运行它,将焦点更改到相关窗口,等待 5 秒钟,然后返回终端。瞧!

I run this command on a terminal:

sleep 5s; ps -Flwwp $(xdotool getwindowpid $(xdotool getwindowfocus))

Run it, change the focus to the relevant window, wait 5 seconds, then back to terminal. Voilà!

冷情 2024-08-24 14:43:23

安装 wmctrl(从存储库)。 wmctrl -lp 可能就是您想要的。如果您的程序需要它,您可以随时查看源代码。

Install wmctrl (from the repositories). wmctrl -lp could be what you want. You can always take a look at the source if you need it from your program.

塔塔猫 2024-08-24 14:43:23

将 xprop 的要点提取到 https://github.com/mondalaci/current-window-linux

可以工作,但有时会出现段错误 - 需要修复和清理。

Extracted the gist of xprop into https://github.com/mondalaci/current-window-linux

Works but sometimes segfaults - needs to be fixed and cleaned up.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文