Explorer.exe в качестве родительского процесса в Windows

Я убиваю некоторые задачи в cmd, используя следующую команду:

taskkill /f /im software* /t

Он выполняет свою работу и убивает все задачи с этим IMAGENAME; но, глядя на то, что это дало мне, я увидел кое-что интересное. Смотри ниже:

SUCCESS: The process with PID 14712 (child process of PID 9068) has been terminated.
SUCCESS: The process with PID 12184 (child process of PID 9068) has been terminated.
SUCCESS: The process with PID 16344 (child process of PID 9068) has been terminated.
SUCCESS: The process with PID 6816 (child process of PID 9068) has been terminated.
SUCCESS: The process with PID 10656 (child process of PID 9068) has been terminated.
SUCCESS: The process with PID 14912 (child process of PID 9068) has been terminated.
SUCCESS: The process with PID 11908 (child process of PID 9068) has been terminated.
SUCCESS: The process with PID 9068 (child process of PID 10060) has been terminated.

Итак, как и ожидалось, все процессы привязаны к одной централизованной задаче PID = 9068. Но тогда этот процесс также является дочерним процессом для PID = 10060, который является PID для explorer.exe. У этого задания нет GUI. Поэтому я удивлен, увидев, что это дочерний процесс explorer.

Итак, вот вопрос: какие процессы будут под explorer.exe в окна?

Обновлять:

Вопрос: Если я хочу избежать уничтожения (с помощью taskkill) любого процесса, который является непосредственно дочерним процессом explorer.exe, как я могу подойти к этому?

Это то, что у меня есть до сих пор. Для начала нам нужно получить pid для explorer.exe:

TASKLIST /NH /FI  "IMAGENAME eq explorer.exe"

Затем я думаю о написании функции, которая убивает pid, проверяет его родительский процесс, если родительский pid равен explorer.exe, он завершает процесс, если нет, то убивает процесс. Все это должно происходить в одной и той же функции, чтобы избежать работы с динамическими pid, упомянутыми в комментариях.

Я могу найти родительский процесс для каждого pid, используя следующее:

wmic process get processid,parentprocessid,executablepath|find "process id goes here")

Я благодарен за помощь в написании функции.

К вашему сведению, у taskkill есть два способа закрыть процесс. С /F он пытается открыть дескриптор процесса с доступом PROCESS_TERMINATE и вызывает TerminateProcess. Без /F он перечисляет окна процесса и отправляет WM_CLOSE, с которым процесс может справиться при своем нарушении. Для консольного приложения, если оно является владельцем консоли, taskkill отправляет WM_CLOSE в окно консоли, которое, в свою очередь, инструктирует сервер сеанса (csrss.exe) отправлять CTRL_CLOSE_EVENT всем процессам, подключенным к консоли. У них есть 5 секунд, чтобы изящно выйти, прежде чем они будут принудительно завершены.

Eryk Sun 13.12.2019 23:32

@ErykSun - Немного отступить. Просто избегайте закрытия прямых дочерних процессов explorer.exe. Я подумываю написать UDF, который принимает pid, проверяет, находится ли он под explorer.exe (используя это, чтобы найти родительский wmic process get processid,parentprocessid,executablepath|find "process id goes here"), затем if "pid of parent" = "pid of explorer.exe" завершает работу, а если нет, это убивает процесс. Я не знаю, как сделать это рекурсивным. так, например, в этом случае сам 9068 не будет закрыт, но его дочерние процессы будут. Не уверен, возможно ли это. это?

M-- 14.12.2019 22:14

Должно ли это быть реализовано с помощью только пакетных сценариев (cmd.exe) и утилит командной строки, таких как wmic.exe, tasklist.exe. а taskkill.exe? Если нет, я бы предложил использовать Python или PowerShell. Я не поклонник PowerShell, но у него есть то преимущество, что он уже установлен в большинстве систем Windows.

Eryk Sun 14.12.2019 22:39

Основная проблема с попыткой убить дерево процессов в Windows заключается в том, что ОС его не поддерживает. Идентификатор родительского процесса устанавливается при создании процесса, но он статичен, поэтому дочерние ветви в дереве могут быть осиротевшими, а PID завершенных процессов в дереве могут даже повторно использоваться новыми процессами. (Последнее можно проверить, проверив отметки времени создания. Идентификатор родительского процесса, который ссылается на процесс, который был создан после дочернего процесса, очевидно, не является настоящим родительским элементом.)

Eryk Sun 14.12.2019 22:49

Вам нужен процесс оболочки для сеанса. Заменять проводник не принято, но при запуске процесс, который хочет запускаться в качестве оболочки рабочего стола для сеанса, регистрируется в диспетчере окон через SetShellWindowEx. В C / C++ вы можете получить его окно рабочего стола верхнего уровня через GetShellWindow. Затем получите его PID через GetWindowThreadProcessId. Оболочка может порождать несколько экземпляров самой себя, как это делает Explorer для файловых браузеров, поэтому вам нужно будет сохранить путь к ее образу из OpenProcess и QueryFullProcessImageNameW и проверить, является ли родитель оболочкой, сравнив пути к изображениям.

Eryk Sun 14.12.2019 23:06

@ErykSun powershell и cmd в порядке.

M-- 14.12.2019 23:21

не понимаю смысла вопроса, но формально сделать это очень легко. позвоните в NtQuerySystemInformation(SystemProcessInformation.. и проверьте SYSTEM_PROCESS_INFORMATION::InheritedFromUniqueProcessId перед тем, как решить убить процесс или нет

RbMm 15.12.2019 09:54

Но при перечислении процессов для поиска дочерних элементов цели необходимо проверить временную метку создания, чтобы подтвердить, что цель старше из-за повторного использования PID. Современная Windows пытается избежать повторного использования PID, но нет никаких гарантий. Просмотрите дерево, используя список записей (pid, timestamp), начиная с цели. Вставьте пластинку с конца. Откройте ручку. Проверьте отметку времени. Попробуйте завершить / прекратить процесс. Подождите на ручке и закройте ее. Если ожидание прошло успешно, сделайте снимок запущенных процессов. Добавить потомков цели в список, исключая слишком старые процессы. Повторение.

Eryk Sun 15.12.2019 16:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
2 098
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Родительский процесс не имеет ничего общего с тем, является ли дочерний процесс графическим, консольным или служебным приложением. Если Explorer является родительским, это означает только то, что Explorer вызвал CreateProcess или что другой процесс, названный CreateProcess или CreateProcessAsUser, заменил дескриптор для Explorer как дочерний PROC_THREAD_ATTRIBUTE_PARENT_PROCESS.

Например, если пользователь дважды щелкнет значок сценария .py в проводнике, оболочка найдет ассоциацию файлов (например, с использованием внутренней реализации интерфейса IQueryAssociations) и выполнит соответствующую программу со сценарием в качестве аргумента с помощью команды как "C:\Windows\py.exe" "path\to\script.py". Если он выполняется напрямую, Explorer вызывает CreateProcess с этой командной строкой в ​​качестве аргумента. Если он «запускается от имени администратора», Explorer отправляет запрос в службу информации о приложении, которая создает процесс с повышенными правами через CreateProcessAsUser, при этом Explorer устанавливается в качестве родительского с помощью вышеупомянутого атрибута создания процесса.

Ответ принят как подходящий

Следующий сценарий .bat может помочь понять родительские / дочерние процессы и их поведение ...

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
echo "%~1%~2%~3" | findstr /I "\? /h \-h">NUL 2>&1
if %errorlevel% EQU 0 goto :usage 

set "_explorerName=explorer.exe"
set "_NameToKill=%~1"
set "_Terminate=%~2"
set "_KillForce=%~3"

if NOT defined _NameToKill if not [%1]==[] (
  rem debugging 
  set "_NameToKill=CMD.EXE"
  rem debugging: start a child process
  start "" /MIN notepad.exe
)

for /F "tokens=1,2 delims=," %%G in ('
    TASKLIST /NH /FI "IMAGENAME eq %_explorerName%"  /FO CSV
') do (
  set "_explorerPID=%%~H"
)
ECHO checking '%_NameToKill%*' as child of %_explorerName% ^(PID=%_explorerPID%^)  
for /F "skip=1 tokens=1-3" %%G in ('
    wmic process WHERE "Name like '%_NameToKill%%%' and ParentProcessId=%_explorerPID%" get Name^,ParentProcessId^,ProcessId^,Status
') do (
  if NOT "%%H"= = "" (
    echo %%G
    for /F "skip=1 tokens=1-3" %%g in ('
        2^>NUL wmic process WHERE "ParentProcessId=%%I" get Name^,ParentProcessId^,ProcessId^,Status
    ') do (
      if NOT "%%h"= = "" (
        echo    ProcessId=%%i, ParentProcessId=%%h, %%g child of %%G ^(%%I^)
        if defined _Terminate (
          if /I "%%~g"= = "conhost.exe" (
            rem debugging
            taskkill /PID %%i /T
          ) else (
            taskkill /PID %%i %_Terminate% %_KillForce%
          )
          echo(
        )
      )
    )
    echo    ParentProcessId=%%H, ProcessId=%%I, %%G child of %_explorerName% ^(%_explorerPID%^)
    if defined _Terminate (
      taskkill /PID %%I /T
      echo(- 
    )
  )
)
if [%1]==[] goto :usage
:endlocal
ENDLOCAL
goto :eof

:usage
  echo USAGE:
  echo %~nx0 -? ^| /? ^| /h ^| -h           this help message
  echo %~nx0                             list all childs of %_explorerName%
  echo %~nx0 ^<processName^> [/T] [/F]     list all childs of a process
  echo %~nx0 ""            [/T] [/F]     a particular test case for cmd.exe
  echo(
  echo Optional parameters /T and /F ^(or -T and -F^): see taskkill /? 
goto :endlocal

Другие вопросы по теме