Страница: 1 | 2 |
Вопрос: Нетривиальная задачка по API
Добавлено: 28.10.05 11:58
Автор вопроса: Comanche
Дано:
Хэндл процесса - как результат выполнения ShellExecuteEx.
Нужно:
Получить ID процесса.
Доп. требования:
Должно работать под любой версией ОС, начиная с NT 4.0.
Мысли после часа в Гугле и часа в MSDN'е:
1. Функция GetProcessId, которая явно решает эту задачу, существует только в XP w/SP1, Win2003 Server и в Висте. В предыдущих виндах её нет!!!
2. Материалов на эту тему очень мало.
3. В некоторых форумах задачу называют просто нерешаемой.
4. Удалось найти два решения "через одно место":
http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_10073493.html
и
http://www.eggheadcafe.com/ng/microsoft.public.win32.programmer.tools/post20380834.asp
Оба не тянут ни на быстрое, ни на универсальное, ни на надёжное решение.
Есть ещё идеи?
Ответы
Всего ответов: 20
Номер ответа: 1
Автор ответа:
el-paso
Вопросов: 3
Ответов: 164
Профиль | | #1
Добавлено: 28.10.05 13:40
А почему бы не использовать CreateProcess вместо ShellExecuteEx?
В последнем аргументе CreateProcess можно выкопать искомый ID...
Хотя, конечно, всё зависит от конкретной задачи...
Номер ответа: 2
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #2
Добавлено: 28.10.05 14:21
ОК, можно скомбинировать CreateProcess с FindExecutable - но всё равно точного аналога "запуска по файловой ассоциации" не получится - ведь не всегда командная строка предполагается равной "<exe-шник><пробел><файл>". Чтобы получить такой аналог, надо определить верную командную строку для данного типа файла, а для этого надо лезть в реестр, в HKCR находить соответствующий раздел shell\open\command, дёргать оттуда ключ, парсить его значение... ещё то удовольствие.
Если непонятно, о чём я, то вот shell\open\command для MSI-файлов:
А мне нужна 100%-ная гарантия, что всё отработает корректно, как оно бывает при использовании ShellExecute/ShellExecuteEx.
Номер ответа: 3
Автор ответа:
LamerOnLine
ICQ: 334781088
Вопросов: 108
Ответов: 2822
Профиль | | #3
Добавлено: 28.10.05 17:41
А если не секрет - для чего это надо?
Задача в целом какая?
Номер ответа: 4
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #4
Добавлено: 28.10.05 18:32
Задача - манипулировать окнами, порождёнными процессом, запущенным через ShellExecuteEx. Нужно пройти по цепочке:
Всё просто, кроме самого первого звена, о котором и речь.
Номер ответа: 5
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #5
Добавлено: 28.10.05 18:33
Пардон, очепятка:
кроме второго звена, разумеется, - hProcess --> ProcessID.
Номер ответа: 6
Автор ответа:
Victor
ICQ: 345743490
Вопросов: 42
Ответов: 385
Web-сайт:
Профиль | | #6
Добавлено: 28.10.05 23:15
Можно вопрос. Что возвращает функция VB Shell? Не тот ли самый ID?
Номер ответа: 7
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #7
Добавлено: 28.10.05 23:42
Именно его и возвращает.
И что дальше?!
Номер ответа: 8
Автор ответа:
Victor
ICQ: 345743490
Вопросов: 42
Ответов: 385
Web-сайт:
Профиль | | #8
Добавлено: 29.10.05 00:03
Я понял. Использование функции ShellExecute обязательно. Просто сразу хочется предложить использовать функцию Shell. Она, правда, не все умеет.
Номер ответа: 9
Автор ответа:
Victor
ICQ: 345743490
Вопросов: 42
Ответов: 385
Web-сайт:
Профиль | | #9
Добавлено: 29.10.05 01:09
Нашел кое-что.
В MSDN Есть пример. TLIST называется.
Он делает то, что может помочь. А именно - получает полный список процессов вместе с их PID'ами. Дальше можно использовать функцию OpenProcess, которая дает хендл на процесс. Но я не уверен, что этот хендл совпадет с полученным из ShellExecuteEx. А если все нормально, то надо получить хендлы на каждый процесс, сравнить с имеющимся, и получить таким макаром PID.
Проблема в том, что там все сугубо на C, а я в нем плохо разбираюсь.
Вывалил файл: http://vt-dbnz.narod.ru/tlist.rar
(142KB)
Бяка в том, что это не слишком надежное решение, но ничего другого не видно.
Номер ответа: 10
Автор ответа:
GSerg
Вопросов: 0
Ответов: 1876
Профиль | | #10
Добавлено: 29.10.05 02:32
Не совпадёт.
Номер ответа: 11
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #11
Добавлено: 29.10.05 13:10
Конечно не совпадёт! ))
Более того, получение снэпшота системы - штука не быстрая...
На Релибе подсказали ссылку:
http://www.codeproject.com/win32/Remote.asp
Там эмуляция GetProcessId - в т.ч. и через недокументированные функции из NtDll.dll. Прикольно...
Номер ответа: 12
Автор ответа:
LamerOnLine
ICQ: 334781088
Вопросов: 108
Ответов: 2822
Профиль | | #12
Добавлено: 31.10.05 12:56
Ну можно пойти и с другого конца цепочки - GetWindowThreadProcessId
Номер ответа: 13
Автор ответа:
Comanche
Вопросов: 87
Ответов: 459
Профиль | | #13
Добавлено: 31.10.05 14:20
Это не поможет - я же не знаю ProcessId, а знаю только его хэндл! и проблема-то заключается именно в их увязке!
Номер ответа: 14
Автор ответа:
Victor
ICQ: 345743490
Вопросов: 42
Ответов: 385
Web-сайт:
Профиль | | #14
Добавлено: 02.11.05 01:27
Да. Здесь, похоже, будет легче написать парсилку содержимого реестра, с учетом всяких там dde. И изучать все тонкости.
Ну, можно, конечно, пойти тупо.
Делаем список окон до заветного вызова... и после него. Сравниваем, получаем ответ - какие окна появились. Оттуда можно даже PID вытащить.
Конечно, это не претендует на надежное решение, просто как вариант. Я знаю, что пока ShellExecute выполняется, могут появится окна, не имеющие к ней никакого отношения (мало ли, че там еще юзверь делает), которые тоже поймаются. Или могут быть такие, которые появляются далеко не сразу...
Номер ответа: 15
Автор ответа:
LamerOnLine
ICQ: 334781088
Вопросов: 108
Ответов: 2822
Профиль | | #15
Добавлено: 02.11.05 12:44
Тут можно фильтрануть процессы по имени экзешника и ID Parent процесса, но если юзер запускает два аналогичных процесса - уже проблемы