【问题标题】:How to Identify if the process in User Interface Process?如何识别用户界面进程中的进程?
【发布时间】:2011-09-25 13:11:20
【问题描述】:

如何从一个进程中获取它是 UI(用户界面)进程还是非 UI 进程的信息?

对于 UI 进程,我的意思是 Finder、Dock、System UI 服务器或任何其他具有 UI 界面并由 Window Server 使用的 mac 应用程序。

我想从 ProcessID 中确定此信息。

我正在使用 mac os x。

【问题讨论】:

  • 我已经更新了问题。谢谢
  • 我建议用编程语言替换您的“进程”标签,鉴于您以 Mac 为中心的问题,Objective-C 似乎是合适的。许多高级用户只扫描有关他们专业的问题。祝你好运。
  • 大概是有目的的得到这个。如果您解释了您实际尝试实现的目标(为什么需要知道这一点,以及为什么从进程 ID 中知道?),您可能会得到更有用的答案。 :)

标签: objective-c macos unix process macos-carbon


【解决方案1】:

没有办法完全根据 PID number 确定特定进程是什么。原因是:进程ID在启动时从PID=1开始(有点)按顺序分配,不同系统的启动可能不同。如果 Finder 或 Dock 崩溃并且必须重新启动,也会重新分配进程 ID。

如果您可以使用您拥有的特定 pid 运行终端命令,请执行以下操作:

ps -p <pid> -o ucomm=

您将获得进程的文件名,您可以对照您知道的 UI 进程列表检查该文件名。例如,这里是我系统上某些 ps 命令的输出,用于我当前的登录会话:

> ps -p 110 -o ucomm=
Dock

> ps -p 112 -o ucomm=
Finder

下面的命令会按照进程 ID 的顺序给你一个进程列表,只有名称:

> ps -ax -o pid=,ucomm=
   1 launchd
  10 kextd
  11 DirectoryService
     ...

编辑:你也许可以做你所要求的,尽管它很复杂。 This回答提到:

CGWindow.h 中的函数 CGWindowListCopyWindowInfo() 将返回一个字典数组,每个窗口对应于您设置的条件,包括其他应用程序中的条件。它只允许您按给定窗口上方的窗口、给定窗口下方的窗口和“屏幕”窗口进行过滤,但返回的字典包含所属应用程序的进程 ID,您可以使用该 ID 将窗口与应用程序匹配。

如果你能获得所有的CGWindows和它们各自的pids,那么你将知道所有UI应用程序的pids,而不需要运行ps

Rahul 为这种方法实现了以下代码,他要求我将其添加到我的答案中:

CFArrayRef UiProcesses()
{
    CFArrayRef  orderedwindows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
    CFIndex count = CFArrayGetCount (orderedwindows);
    CFMutableArrayRef uiProcess = CFArrayCreateMutable (kCFAllocatorDefault , count,  &kCFTypeArrayCallBacks);
    for (CFIndex i = 0; i < count; i++)
    {
        if (orderedwindows)
        {
            CFDictionaryRef windowsdescription = (CFDictionaryRef)CFArrayGetValueAtIndex(orderedwindows, i);
            CFNumberRef windowownerpid  = (CFNumberRef)CFDictionaryGetValue (windowsdescription, CFSTR("kCGWindowOwnerPID"));
            CFArrayAppendValue (uiProcess, windowownerpid);

        }
    }
    return uiProcess;
}

【讨论】:

  • 在第二种方法中,如果窗口关闭。比方说 VMWare Fusion,它的条目不会被列出,因此它不会被包含在列表中。
  • 好吧,不幸的是,这是我认为最接近解决方案的方法。你到底在做什么需要知道每个 UI 进程的pid?向系统上的所有 UI 进程发送 SIGKILL 或 SIGTERM 是个坏主意,但是您还需要知道 pids 的什么用途?您是否正在尝试为 OS X 编写窗口管理器?
  • 我在这里想要实现的是,我有流程列表,我必须从中整理出 UI 流程。除了我们在 mac 上已有的效果外,我还想在 UI 进程中注入一些漂亮的效果。而且我不想注入非 UI 进程。
  • 我会创建一个事件监听器或类似的调用CGWindowListCopyWindowInfo(你不能只在鼠标点击时这样做,因为苹果软件更新出现时没有鼠标点击......你可能只想拥有每 2 秒左右检查一次)。当您注意到打开了一个额外的窗口时,获取其关联的 processID 并注入 UI 效果。这与不以某种方式拥有 Window Server 的情况一样好。
【解决方案2】:

试试下面的。

#include <unistd.h>

  if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO))
    // Process associated with a terminal
  else
    // No terminal - probably UI process

【讨论】:

  • 如果您在流程区域中,上述代码将起作用。我相信问题是关于通过某个 pid 或类似的东西获取有关该过程的信息
  • 是的!问题是关于通过 pid 获取有关进程的信息。
  • 而且我认为它不适用于问题中提到的流程;例如,Finder 可能没有其 stdin、stdout 和 stderr 指向 ttys。 OP 正在询问具有活动 GUI 的进程,对吗?
  • 这很有趣,但是——诸如“全局守护进程”之类的进程(没有任何 UI,不是由终端运行,而是由 launchd 运行)——它们会“与终端相关联”吗?
【解决方案3】:

根据 darvidsOn 的说法,以下是您问题的答案。

  CFArrayRef UiProcesses()
    {
        CFArrayRef  orderedwindows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
        CFIndex count = CFArrayGetCount (orderedwindows);
        CFMutableArrayRef uiProcess = CFArrayCreateMutable (kCFAllocatorDefault , count,  &kCFTypeArrayCallBacks);
        for (CFIndex i = 0; i < count; i++)
        {
            if (orderedwindows)
            {
                CFDictionaryRef windowsdescription = (CFDictionaryRef)CFArrayGetValueAtIndex(orderedwindows, i);
                CFNumberRef windowownerpid  = (CFNumberRef)CFDictionaryGetValue (windowsdescription, CFSTR("kCGWindowOwnerPID"));
                CFArrayAppendValue (uiProcess, windowownerpid);

            }
        }
        return uiProcess;
    }

只需将您拥有的 processid 与数组项进行比较即可获得所需的结果。

【讨论】:

  • @darvidsOn:对不起,darvidsOn。我没有编辑权限来更新您的答案,因此发布了新答案。
  • @machintosh:我请求你将声望奖励给 darvidsOn。
  • 在第二种方法中,如果窗口关闭。比方说 VMWare Fusion,它的条目不会被列出,因此它不会被包含在列表中。
猜你喜欢
  • 2014-06-20
  • 2013-10-09
  • 2013-09-05
  • 1970-01-01
  • 2018-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
相关资源
最近更新 更多