У нашего клиента есть серверы Windows 2003, на которых выполняются пакетные задания, активируемые планировщиком задач. Фактические программы, выполняющие эту работу, являются пользовательскими процессами .exe, и они объединяются в сценарии .cmd, чтобы планировщик задач запускал их вместе, когда наступает запланированный интервал. Строки в сценариях cmd могут использовать или не использовать команду Call для запуска отдельных программ .exe.
В этой настройке планировщик задач эффективно отслеживает cmd.exe, а при использовании Process Explorer можно заметить, что дочерние процессы .exe припаркованы под деревом процессов cmd.exe. Однако, когда планировщик задач убивает cmd.exe из-за превышения допустимого ограничения по времени, дочерние процессы .exe не могут быть убиты вместе со своими родительскими и стать осиротевшими. Эти процессы остаются остановленными на неопределенное время. Из-за состояния потоков процессов, показанных в Process Explorer, я подозреваю, что эти процессы заканчиваются ошибкой и выскакивают диалоговое окно отладчика .NET (это приложения .NET), которое нельзя увидеть, поскольку пользователь пакетного задания является отдельным пользователем учетная запись.
Первоначально, когда я исследовал это поведение на своей рабочей станции Windows XP, я заметил, что дочерние процессы .exe, запускаемые из моего тестового .cmd-скрипта, убиваются вместе с cmd.exe, когда планировщик задач решает, что время истекло. У меня не было возможности осиротить дочерние процессы.
Основываясь на догадках, я в конце концов перешел на машину с Windows 2003, чтобы проверить это. Точно так же дочерние процессы должны быть завершены, как и на моей рабочей станции. Моим вторым шагом было использовать другая учетная запись пользователя для запуска запланированной задачи. На этот раз cmd.exe завершается после того, как лимит времени превышен, но дочерние процессы остаются в рабочем состоянии, точно так же, как мой клиент наблюдал на своих производственных серверах.
Если я с упреждением войду в эту учетную запись пакетного пользователя (которая, как оказалось, была другой учетной записью администратора), чтобы потребовать сеанс рабочего стола, любые всплывающие окна с ошибками или информацией из моих тестовых программ .exe будут перенаправлены и отображены на этом рабочем столе, что позволит мне увидеть фактический вывод пользователя. Если я войду в систему только после того, как запланированная задача была вызвана, сеанс рабочего стола не будет «возвращать» окна существующих процессов; они остаются скрытыми навсегда.
У меня вопрос, какие условия мне здесь не хватает, из-за которых планировщик задач не уничтожает дочерние процессы в cmd.exe? Что особенного в использовании другой учетной записи, которая может вызвать такое поведение, но не при использовании моей текущей учетной записи администратора для запуска запланированной задачи?
Попробуйте использовать "Taskkill / T" в командной строке. (/ T = «… Завершает указанный процесс и все дочерние процессы, которые были им запущены…»)
Если у вас запущено несколько процессов (у нас часто работает 5 или более «powershell.exe»), добавьте столбец «Командная строка» на вкладку «Подробности» в диспетчере задач. Это должно прояснить, какой идентификатор процесса вы хотите убить.
Процессы в Windows независимы - завершение родительского процесса не приводит к автоматическому завершению дочернего процесса.
Если вы думаете, что это связано с появлением сообщения отладчика, пробовали ли вы обернуть код в try{}catch{}
заблокировать и записать ошибку?
В противном случае, возможно, вы могли бы заставить процессы записывать вывод WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent())
Я подозреваю, что дети каким-то образом повышают свой уровень привилегии до Администратора, и тогда их нельзя убить вместе с родителем.
Чтобы проверить это без изменения кода, вы можете написать другое запланированное задание, которое пытается убить другие процессы, используя Taskkill. Это запланированное задание следует запускать от имени администратора. Если это сработает, значит, это проблема безопасности.
Как насчет использования pskill утилита, входящая в состав пакета SysInternals. Эта программа может уничтожать процессы по имени. Я бы добавил запланированную задачу, которая будет запускаться через несколько минут после того, как вы ожидаете завершения процессов, которая запустит pskill для их завершения.
PSKill также может работать под учетными данными пользователя, которые вы вводите в командной строке.
Я не знаю, что это решит вашу проблему, но если это связано с всплывающими окнами (а это может быть - приложение находится в неисправном состоянии и приостановлено, пока несуществующий пользователь решает, что с этим делать) .
Взгляни на http://blogs.msdn.com/shawnfa/archive/2004/07/15/184490.aspxи посмотри, не сможешь ли ты избавиться от этих ящиков ...