2

How can I get information from a process that it is UI(User Interface) process or non-ui?

With UI process I mean, Finder, Dock, System UI server, or any other mac application which has UI interface and it is used by Window Server.

I want to determine this information from ProcessID.

I am using mac os x.

RLT
  • 4,219
  • 4
  • 37
  • 91
  • 1
    I would recommend substituting your 'process' tag with a programming language, Given your mac centric question, Objective-C seems appropriate. Many power users only scan for questions on their specialties. Good luck. – shellter Sep 27 '11 at 22:12
  • Presumably there is a purpose to getting this. If you explained what you are actually trying to achieve (why do you need to know this, and why from the process ID?), you might get more useful answers. :) – Duncan Babbage Oct 04 '11 at 06:43

4 Answers4

2

There is no way to determine based purely on the PID number what a specific process is. The reason for this: Process IDs are assigned (somewhat) sequentially from PID=1 on startup, and startup can be different for different systems. The process ID will also be reassigned if, for example, Finder or Dock crashes and has to be restarted.

If you can run a terminal command with a specific pid that you have, though, do this:

ps -p <pid> -o ucomm=

You'll get the filename of the process, which you can check against a list of ones you know are UI processes. For example, here is the output of certain ps commands on my system for my current login session:

> ps -p 110 -o ucomm=
Dock

> ps -p 112 -o ucomm=
Finder

And the following command will give you a list of processes in order of process ID, with only the name:

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

EDIT: You may be able to do what you ask, though it is convoluted. This answer mentions:

The function CGWindowListCopyWindowInfo() from CGWindow.h will return an array of dictionaries, one for each window that matches the criteria you set, including ones in other applications. It only lets you filter by windows above a given window, windows below a given window and 'onscreen' windows, but the dictionary returned includes a process ID for the owning app which you can use to match up window to app.

If you can obtain all the CGWindows and their respective pids, then you will know the pids of all UI applications without needing to run ps at all.

Rahul has implemented the following code for this approach, which he requested I add to my answer:

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;
}
Community
  • 1
  • 1
  • In second approach, if window is close. Lets say VMWare Fussion, its entry will not be listed and thus it wont be covered in list. – RLT Sep 28 '11 at 15:59
  • Well, unfortunately this is the closest you're going to get to a solution I think. What exactly are you doing which requires knowing the `pid` of every UI process? Sending a SIGKILL or SIGTERM to all UI processes on the system would be a bad idea, but what else do you need to know the `pid`s for? Are you trying to write a window manager for OS X? –  Sep 29 '11 at 05:48
  • What I am trying to achieve here is, I have list of process, from which I have to sort out the UI processes. I want to inject in UI process to create some nice effects, in addition to what we already have on mac. And I dont want to inject in non UI processes. – RLT Oct 02 '11 at 12:06
  • I would create an event listener or similar to call `CGWindowListCopyWindowInfo` (you can't just do that on e.g. mouse clicks since Apple Software Update appears without a mouse click.. you may want to just have a check every 2 seconds or so). When you notice an extra window is opened, get its associated processID and inject the UI effects. That's about as good as you'll get without somehow owning Window Server. –  Oct 03 '11 at 22:30
1

Kind of resurrecting this one... But for macOS, to get the process ids of various elements of the UI, you can use lsappinfo since maybe Tiger? The manpage says April, 2013, but I think it was around at the time of this question being asked and probably earlier. The command should be run as the user who currently owns the loginwindow process.

lsappinfo info -only pid Dock
"pid"=545
0

Try the following.

#include <unistd.h>

  if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO))
    // Process associated with a terminal
  else
    // No terminal - probably UI process
Diomidis Spinellis
  • 18,734
  • 5
  • 61
  • 83
  • Above code will work if you are in process area. I believe question is about getting information about the process by some pid or something like that – RLT Sep 25 '11 at 16:47
  • 1
    Yes! Question is about getting information about the process by pid. – RLT Sep 26 '11 at 09:15
  • And I don't think it will work for the processes mentioned in the question; the Finder, for example, probably doesn't have its stdin, stdout, and stderr pointing to ttys. The OP is asking about processes with active GUIs, right? – Keith Thompson Sep 27 '11 at 16:20
  • This is interesting, but -- processes such as "global daemons" (without any UI, that are NOT run by terminal, but rather by launchd) -- will they be "associated with a terminal) – Motti Shneor Jun 23 '21 at 04:17
0

On the lines of darvidsOn, below is the answer to your question.

  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;
    }

Just compare the processid you have against the array items to get the desired result.

RLT
  • 4,219
  • 4
  • 37
  • 91
  • @darvidsOn: Sorry darvidsOn. I dont have edit rights to update your answer thus posting new one. – RLT Sep 28 '11 at 09:53
  • @machintosh: I request you to give the reputation reward to darvidsOn. – RLT Sep 28 '11 at 09:53
  • In second approach, if window is close. Lets say VMWare Fussion, its entry will not be listed and thus it wont be covered in list. – RLT Sep 28 '11 at 16:00