Имя: Пароль:
IT
Админ
Как завершить дочерний процесс?
0 Jump
 
15.11.13
11:42
Ситуация такая -
Программа или скрипт А при работе в некоторый момент запускает консольную утилиту B (например wget), эта утилита работает как отдельный процесс.

1й вопрос - как эту утилиту B грохнуть из программы А?

2й и самый главный вопрос - можно ли как нибудь так извернуться, чтобы ежели кто внезапно прибъет программу А, то чтобы автоматом прибились все программы B, которые она стартанула.
1 Jump
 
15.11.13
12:05
Апнем?
2 Jump
 
15.11.13
12:58
Апнем!
3 User_Agronom
 
15.11.13
13:00
ps ax
а потом kill :)
4 Jump
 
15.11.13
13:02
(3)Извиняюсь что сразу не уточнил - под виндой надо.
5 Torquader
 
15.11.13
23:28
WScript.Shell - там есть запуск процесса, когда получаем указатель и можем проверить, а жив ли ещё процесс или "дать ему пинка".

http://msdn.microsoft.com/en-us/library/2f38xsxe(v=vs.84).aspx

Ну, в общем, всё что надо для работы (только на потоках ввода-вывода обычно "виснет", если пытаться читать то, что ещё не написали в консоль.
6 Мизантроп
 
15.11.13
23:41
//*******************************************
//PsList.JS
//Вывод  списка   процессов   Windows
//*******************************************
// Объявляем переменные
var PsWMI, PsProcesses1, PsProcess1, PsList1, Mess1;
var vbCritical=16;

//Создаем экземпляр объекта WshShell    
var WshShell = WScript.CreateObject("WScript.Shell");

//Включаем обработку исключительных ситуаций
try   {
//Соединяемся с WMI
PsWMI=GetObject("winMgmts:");
}

//Начинаем обработку возможных ошибок
catch (e) {  
if (e!=0) {
                Mess ="Ошибка\nКод ошибки: " + err.Number;        
                WshShell.Popup(Mess,0,"Запущенные прoцеccы",vbCritical);
                WScript.Quit();
}
}

//Создаем кoллeкцию всех работающих процеccoв
PsProcesses1=new Enumerator(PsWMI.ExecQuery("SELECT * FROM Win32_Process"));
PsList1="Зaпущенныe прoцеccы\n\n";

//Цикл для перебора коллекции
while (!PsProcesses1.atEnd()) {                                  
                PsProcess1=PsProcesses1.item ();
                PsList1+=PsProcess1.Name + "       " + PsProcess1.ProcessID + "\n";
                PsProcesses1.moveNext();              
}
//Выводим кoллeкцию процеccов и их идентификаторов
WScript.Echo(PsList1);                                    
//*************   Конец ********************
7 Мизантроп
 
15.11.13
23:42
то же на VB

'**********************************************
' PsList.VBS
'Вывод  списка   процессов   Windows
'**********************************************
' Включаем обработку исключительных ситуаций
On Error Resume Next
' Объявляем переменные
Dim PsWMI, PsProcesses, PsProcess, PsList, Mess

' Создаем экземпляр объекта WshShell    
set WshShell = WScript.CreateObject("WScript.Shell")

' Производим соединение с WMI
set PsWMI=GetObject("winmgmts:")

' Проверка на ошибку
If Err.Number <> 0 Then
                Mess ="Ошибка" &vbCrLf & "Код ошибки: " & err.Number
                 WshShell.Popup Mess,0,"Зaпущенныe процеccы",vbCritical
Else

' Производи SQL запрос для получения кoллeкции
set PsProcesses=PsWMI.ExecQuery("SELECT * FROM Win32_Process")
PsList="Зaпущeнные проoцeссы" & vbCrLf & vbCrLf

' Производи перебор
For Each PsProcess in PsProcesses
               PsList=PsList & PsProcess.Name & vbTab & PsProcess.ProcessID & vbCrLf
NEXT

'Выводим  список   прoцесcов  их идентификаторов
WScript.Echo PsList
End if
'*************Конец***************************************
8 Мизантроп
 
15.11.13
23:42
потом tasklist
9 Мизантроп
 
15.11.13
23:43
можно вывод tasklist.exe парсить
10 BigHarry
 
16.11.13
11:40
Поскольку процессы запускаются как независимые, а не дочерние, то для того, что бы их идентифицировать и привязать к запускателю "А" надо как-то шаманить с заголовком окна, ну а taskkill может убивать по названию заголовка окна. Для случаев, когда убили запускателя "А" и надо прибить всех его "дочек" потребуется отдельный процесс, который будет проверять наличие осиротелых "дочек"...
11 Torquader
 
16.11.13
13:33
(10) В Windows информация о "дочерности" процесса теряется после его запуска (если родитель не использует режим отладки). Если мы знаем, кого мы запустили, то мы должны получать Id или HANDLE процесса - иначе мы его не найдём.
12 N1kMZ
 
16.11.13
14:11
(11) А как тогда Process Explorer от Sysinternals определяет "дочерность"?
13 Torquader
 
16.11.13
14:14
(12) Также как и обычный Windows mstask - если процессы запущены в одной консоли, то пока один исполняется, остальные в цепочке запуска его ждут - но в этом случае нет никакого параллельного исполнения - понятно, что ожидающий завершения другого процесса процесс будет считаться родительским.
14 N1kMZ
 
16.11.13
14:17
(13) Не, ну я из тотал коммандер запустил excel. Process Explorer показывает, что excel является дочерним по отношению к тоталу. И работают они параллельно.
15 N1kMZ
 
16.11.13
14:40
(14) + Если посмотреть "свойства" excel в process explorer, то там сказано parent: TOTALCMD.EXE(72532)
16 Torquader
 
16.11.13
14:52
(15) Вообще написано, что если через Process Snapshort сделать снимок исполняемой системы, то потом можно посмотреть информацию о каждом процессе

lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0 );

http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx

Это называется "свинство" - в самой системе информация спрятана, что её не достанешь, а если сделать снимок - на те получите - то есть, оказывается, хранит.
17 Torquader
 
16.11.13
14:54
В общем, когда я в Windows 2000 это хотел сделать - такого не было, а потом Microsoft, видимо, понял, что линейная таблица - это не есть хороший способ хранения информации о процессах (ну или кто-то из них Linux увидел, где это всегда было).
18 N1kMZ
 
16.11.13
14:55
(16) Только вот новый процесс после убийства родителя может получить его PID.
19 Torquader
 
16.11.13
15:14
(18) Скорей всего, если PID занят, то второй раз его не дадут - но - нужно проверять.
20 Torquader
 
16.11.13
15:59
В общем - в ответе Microsoft сказано, что никто не отслеживает дерево процессов, а Id записывается в момент вызова функции CreateProcess - так что потом может оказаться, что "родителем" стал тот, кто получил Id.
Если на процесс есть открытые ссылки HANDLE, то объект процесса живёт и хранит его код выхода, а Id никакой смысловой информации не несёт - и система даже и не знает, помнит ли кто-то Id или нет.
При запуске процесса можно получить HANDLE на него - пока HANDLE не закрыт, информация о процессе будет доступна - и его всегда можно завершить вызовом TerminateProcess.
21 Torquader
 
16.11.13
16:01
Кстати, если мы передаём пароль в командной строке при запуске, то строку можно получить через запрос данных процесса до тех пор, пока объект процесса жив - так что про это нужно помнить.
22 Jump
 
16.11.13
17:05
(7)Спасибо, пробую.
(11)Ну я так и понял вроде, что нет такого штатного метода чтобы контролировать запущенный процесс.
Поэтому вроде один вариант, как в (7) перебирать все текущие процессы и искать нужный.
23 Jump
 
16.11.13
17:08
(21)Да каких то супер требований по безопасности нет, ну максимум узнав пароль можно получить доступ на чтение на удаленном хосте, но какой смысл - проще дождаться работы программы и посмотреть эти данные когда они скачаются локально.
Что касается долговременного доступа - пароли меняются регулярно, собственно одна из задач программы которая стартует процесс получить актуальный адрес и пароль, и скормить его wget'у.
24 Мизантроп
 
16.11.13
17:56
Jump, попробуй такой код. Он тебе должен отдавать ProcessID при запуске процесса. AppActivate еще может заголовок окна менять.

WshShell = Новый COMОбъект("WScript.Shell");
Процесс = WshShell.Exec ("lalala.exe");
Рез = WshShell.AppActivate(Процесс.ProcessID);
25 Jaap Vduul
 
16.11.13
17:59
(19)
ParentProcessId
Data type: uint32
Access type: Read-only


Unique identifier of the process that creates a process. Process identifier numbers are reused, so they only identify a process for the lifetime of that process. It is possible that the process identified by ParentProcessId is terminated, so ParentProcessId may not refer to a running process. It is also possible that ParentProcessId incorrectly refers to a process that reuses a process identifier. You can use the CreationDate property to determine whether the specified parent was created after the process represented by this Win32_Process instance was created.
26 Мизантроп
 
16.11.13
18:15
Set WshShell = CreateObject("WScript.Shell")
PID = WshShell.Exec("notepad.exe").ProcessID
WshShell.AppActivate(PID)
msgbox PID

рабочий код. Показывает PID запускаемого процесса
27 Torquader
 
16.11.13
23:43
(26) Ему это в (5) и предлагалось, только в не настолько разжеванном виде.