Russian Qt Forum
Ноябрь 25, 2024, 02:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: работа с процессами в mac os  (Прочитано 8104 раз)
virtual_root
Гость
« : Июль 18, 2012, 17:47 »

Добрый вечер! Ребята помогите, кто знает.
Работаю на макбуке в qt. Мне нужно получить список процессов запущенных в системе. Нашла документацию https://developer.apple.com/library/mac/#documentation/Carbon/Reference/Process_Manager/Reference/reference.html и стала разбираться. Решила воспользоваться функцией GetNextProcess, которая возвращает PSN следующего процесса. В документации написано, что можно передать константу kNoProcess и фун-я GetNextProcess вернет PSN первого процесса в списке процессов ProcessManager.
Затем можно в цикле передавать полученный PSN и фун-я будет возвращать следующий и так пока не дойдет до конца.
   Дальше мне нужно получить информацию о процессе. Я воспользовалась фун-ей GetProcessInformation которой передаю полученный PSN, но вот беда никакой информации не могу получить... приходят все нули... или я может как-то не правильно вывожу её(в qDebug) Непонимающий Подскажите, пожалуйста кто знает.

Выкладываю пример кода:
Код:
void MacAPIWindows::GetlistProcess(){

    ProcessSerialNumber psn = { 0, kNoProcess };
    qDebug()<< GetNextProcess(&psn);
    ProcessInfoRec info;
    qDebug()<<&psn;
    OSErr error = GetProcessInformation(&psn,&info);
    qDebug()<<info.processName;

}

Вот какой вывод в дебаге получаю:
Код:
0 
0x7fff5fbffa98
0x0

В .pro файле добавила фреймворк carbon:
Код:
macx {
 LIBS += -framework CoreFoundation -framework Carbon
 LIBS += -framework LDAP
 DEFINES += MAC_BOOK_PROVIDER
 DEFINES += LDAP_PROVIDER
}

Всё собирается и всё работает, только вот что-то получить то что нужно не могу никак...
« Последнее редактирование: Июль 18, 2012, 18:00 от virtual_root » Записан
mutineer
Гость
« Ответ #1 : Июль 18, 2012, 18:06 »

Код:
OSErr error = GetProcessInformation(&psn,&info);

error чему равно?

Ну и мне кажется что стоит обратить внимание на этот абзац в документации:
Цитировать
You need to specify values for the processInfoLength, processName, and processAppSpec fields of the process information structure. Specify the length of the process information structure in the processInfoLength field. If you do not want information returned in the processName and processAppSpec fields, specify NULL for these fields. Otherwise, allocate at least 32 bytes of storage for the string pointed to by the processName field and, in the processAppSpec field, specify a pointer to an FSSpec structure.
« Последнее редактирование: Июль 18, 2012, 18:14 от mutineer » Записан
virtual_root
Гость
« Ответ #2 : Июль 18, 2012, 18:16 »

error равен нулю. Просто ProcessName является указателем на маковский тип StringPtr а вот как его преобразовать не могу найти способа.. может у кого есть идеи ?
Записан
mutineer
Гость
« Ответ #3 : Июль 18, 2012, 18:18 »

Указывает он на 0 потому что ты неправильно инициализировала структуру, недочитав документацию.

Вот пример из доки:
Код:
ProcessInfoRec infoRec;
infoRec.processInfoLength = sizeof(ProcessInfoRec);
infoRec.processName = NULL;
infoRec.processAppSpec = NULL;
           
if (GetProcessInformation(&currentProcessPSN, &infoRec) == noErr)
...

Без задания этих трех значений информации о процессе ты не получишь. Если тебе нужен processName, то вместо нуля инициализируй его адресом участка памяти, в который функция запишет тебе имя процесса.

Написано же все там
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июль 18, 2012, 18:33 »

Код
C++ (Qt)
unsigned char pName[257];
ProcessInfoRec infoRec;
infoRec.processInfoLength = sizeof(ProcessInfoRec);
infoRec.processName = pName;
infoRec.processAppSpec = NULL;
 
if (GetProcessInformation(&currentProcessPSN, &infoRec) == noErr) {
 pName[pName[0] + 1] = 0;   // pascal string to C
 qDebug() << (char *) (pName + 1);
}
 
« Последнее редактирование: Июль 19, 2012, 10:13 от Igors » Записан
virtual_root
Гость
« Ответ #5 : Июль 19, 2012, 10:30 »

Спасибо ребята!
Записан
virtual_root
Гость
« Ответ #6 : Июль 19, 2012, 17:26 »

Ребят, помогите справиться с маковскими типами! Не могу никак преобразовать в стандартные типы данных...
Код
C++ (Qt)
   ProcessSerialNumber psn = { 0, kNoProcess };
   qDebug()<< GetNextProcess(&psn);
 
   unsigned char pName[257];
   unsigned int type;
   ProcessInfoRec infoRec;
   infoRec.processInfoLength = sizeof(ProcessInfoRec);
   infoRec.processName = pName;
   infoRec.processAppRef = NULL;  // возвращает путь к файлу, тип возращаемого знач. FSRefPtr
   infoRec.processType = type;   // возвращает тип приложения "APPL" или "appe" , тип возвращ. знач. UInt32
 
 
   if (GetProcessInformation(&psn, &infoRec) == noErr) {
     qDebug() << (char *) (pName + 1);
     qDebug()<<type;
 
   }
Не могу никак преобразовать тип FSRefPtr к QString или char*... Не получается ничего придумать и с UInt32, получаю какое-то большое число, через QString::number не преобразуется...
Подскажите кто знает, пожалуйста!
Попыталась написать функцию которая бы преобразовывала тип FSRefPtr к QString, но она не компилится... вероятно этот тип не строка...
вот пример кода функции, работает если заменить тип FSRefPtr на CFStringRef
Код
C++ (Qt)
QString MacAPIWindows::uniCFStrToQStr(const FSRefPtr cfString)
{
   QChar qchar;
   QString qString("");
   int lenCF=(int)CFStringGetLength(cfString);  // возвращает длину строки
   for (int i=0;i<lenCF;i++)
   {
       qchar=((ushort)CFStringGetCharacterAtIndex(cfString,(CFIndex)i));  // получает символ из строки
       qString=qString+qchar;
   }
   return qString;
}
 
Записан
mutineer
Гость
« Ответ #7 : Июль 19, 2012, 17:34 »

Не нашел в документации по ProcessInfoRec поля processAppRef
Записан
virtual_root
Гость
« Ответ #8 : Июль 19, 2012, 17:41 »

Цитировать
Note that the processName field specifies the name of the application, whereas the processAppSpec field specifies the location of the file.
Прошу прощения я перепутала, там поле processAppSpec, правда из самой структуры оно не доступно...странно..
А как быть с processType не подскажите ? Мне нужно вытащить из него одно из значений:
Цитировать
processType

    The file type of the application, generally 'APPL' for applications and 'appe' for background-only applications launched at startup.
Но когда я в обычный int преобразую. то там естественно цифры... Может я что-то не допоняла в документации?
Записан
mutineer
Гость
« Ответ #9 : Июль 19, 2012, 17:45 »

похоже что они предлагают воспринимать каждый байт UInt32 как символ. И тогда из них будут складываться значения 'APPL' или 'appe'. Других вариантов не вижу

Ну и пока ты ставишь processAppSpec(ну или processAppRef) в 0 перед вызовом функции, оно нулем оставаться и будет
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июль 19, 2012, 18:42 »

похоже что они предлагают воспринимать каждый байт UInt32 как символ. И тогда из них будут складываться значения 'APPL' или 'appe'. Других вариантов не вижу
Так и есть - это 4-х байтовая сигнатура (обычно читабельная). Напр тип файла, креатор и др - это все OSType (UInt32). С ним легко работать

Код
C++ (Qt)
UInt32 type = 'appl';
OSType type2 = 'TEXT';
 

Код
C++ (Qt)
 
   if (GetProcessInformation(&psn, &infoRec) == noErr) {
     qDebug() << (char *) (pName + 1);
 
Халтурить не надо, ребятка. Кто будет ноль-терминатор ставить, папа Карло? А потом начинается хлопание крыльями - ах, в debug работает а в release валится и.т.п.

Записан
virtual_root
Гость
« Ответ #11 : Июль 20, 2012, 12:36 »

Спасибо Igors. Сделала следующее, чтобы извлекать значение:
Код
C++ (Qt)
union Type{
   UInt32 pType2;
   char bytes[4];
};
 
 
void MacAPIWindows::GetlistProcess(){
 
   unsigned char pName[257];
   char pPath[257];
 
 
   ProcessSerialNumber psn = { 0, kNoProcess };
   ProcessInfoRec infoRec;
   infoRec.processInfoLength = sizeof(ProcessInfoRec);
   infoRec.processAppRef = NULL;
   infoRec.processName = pName;
   infoRec.processLocation = pPath;
   OSErr error;
 
   do {
       error = GetNextProcess(&psn);
       if (GetProcessInformation(&psn, &infoRec) == noErr && IsProcessVisible(&psn)) {
         pName[pName[0] + 1] = 0;
         qDebug() << (char *) (pName + 1);
         qDebug() << pPath<<"!";
       }
 
 
       Type type; type.pType2 = infoRec.processType;
       qDebug()<<type.bytes[3]<<type.bytes[2]<<type.bytes[1]<<type.bytes[0];
    } while(error != procNotFound);
 
 
}
 
 
 
Получаю список процессов,их название, путь правда не приходит. Не могу понять как нужно инициализировать поле infoRec.processLocation, чтобы путь получить. Как поняла, что нужно не NULL инициализировать поле infoRec.processAppRef, в документации написано что нужен адрес структуры файла куда сохраниться этот путь, но что это за адрес? Как нужно правильно инициализировать это поле, подскажите, пожалуйста.
 мне кажется что как-то через процессы можно получить и заголовки их окон, если их окна не скрыты и имеются, но что-то никак не могу додуматься как так выкрутиться.
Интересно, что в мониторинге системы можно выбрать просмотр только оконных процессов,может как-то можно и через API это определить. оконный процесс или нет и взять заголовок его окна. Кто может помочь, направьте, пожалуйста в нужном направлении Подмигивающий
« Последнее редактирование: Июль 20, 2012, 12:52 от virtual_root » Записан
mutineer
Гость
« Ответ #12 : Июль 20, 2012, 12:55 »

Цитировать
processLocation - The beginning address of the application partition.

infoRec.processLocation = pPath; - Эта строчка не нужна
processLocation надо брать не из pPath, а из infoRec.processLocation

Прочитай уже документацию, на которую сама же и привела ссылку
Записан
virtual_root
Гость
« Ответ #13 : Июль 20, 2012, 13:17 »


Цитировать
infoRec.processLocation = pPath; - Эта строчка не нужна
processLocation надо брать не из pPath, а из infoRec.processLocation
Я до этого пробовала ничем не инициализировать и просто выводила infoRec.processLocation, но путь просто не выводился, пустой. Поэтому я решила так попробовать.
У меня получилось отловить только оконные процессы, через поле processMode. В документации приведен набор флагов этого поля, но что-то при сравнении с любым из флагов у меня условие не работало, тогда я посмотрела что содержит в себе это поле, естественно увидела число так как это UInt32, и стала сравнивать с числом. Может может всё-таки как-то с флагами сравнивать, чтоб как-то более понятно было и наглядно.
И у меня всё ещё остаётся один вопрос, как можно мне получить заголовок окна активного процесса?

Код
C++ (Qt)
   do {
       error = GetNextProcess(&psn);
       if (GetProcessInformation(&psn, &infoRec) == noErr && infoRec.processMode == 4832) {
         pName[pName[0] + 1] = 0;
         qDebug() << (char *) (pName + 1);
         qDebug() << (char *) infoRec.processLocation<<"!";
       }
 
 
       Type type; type.pType2 = infoRec.processType;
       qDebug()<<type.bytes[3]<<type.bytes[2]<<type.bytes[1]<<type.bytes[0];
 
    } while(error != procNotFound);
Записан
mutineer
Гость
« Ответ #14 : Июль 20, 2012, 13:45 »

А как именно ты сравнивала с флагами?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.175 секунд. Запросов: 23.