Получить имя процесса windows

Как получить список запущенных процессов?


Автор: Александр Федотов

Опубликовано: 23.10.2001
Исправлено: 13.03.2005
Версия текста: 1.1

Введение

Win32 предоставляет несколько способов перечисления запущенных процессов. К сожалению, нет единого способа, который бы работал на всех Win32-платформах. Программистам приходится комбинировать несколько методов в одной программе, чтобы она работала на всех версиях Windows.

Мы рассмотрим следующие методы:

  • С помощью библиотеки Process Status Helper (PSAPI)
  • С помощью ToolHelp32 API
  • С помощью недокументированной функции ZwQuerySystemInformation
  • Через счетчики производительности
  • С использованием интерфейсов Windows Management Instrumentation

Каждый метод мы будем иллюстрировать с помощью функции, имеющей следующий прототип:

Функция перечисления вызывает для каждого процесса указанную пользовательскую функцию, передавая ей информацию об очередном процессе. Пользователькая функция распоряжается этими данными в соответствии с логикой программы, например, в тестовом приложении для этой статьи, она добавляет очередной элемент в список. Некоторые из рассматриваемых нами методов позволяют перечислить процессы на других компьютеров, поэтому прототип функции содержит параметр pszMachineName, позволяющий задать имя компьютера. Значение NULL для этого параметра означает перечисление процессов на локальном компьютере.

Способ 1. Использование библиотеки Process Status Helper

Библиотека Process Status Helper, известная также под названием PSAPI, предоставляет набор функций, позволяющих получить информацию о процессах и драйверах устройств. Библиотека поставляется в составе Windows 2000/XP и доступна в качестве устанавливаемой компоненты для Windows NT 4.0.

Для перечисления процессов библиотека предоставляет функцию EnumProcesses , которая возвращает массив идентификаторов запущенных процессов. Ниже приведен текст функции EnumProcesses_PsApi , реализующей перечисление процессов с помощью PSAPI.

Обратите внимание, что мы связываемся с PSAPI.DLL динамически, загружая библиотеку с помощью LoadLibrary и получая адреса необходимых функций посредством GetProcAddress . Это позволит нам в дальнейшем включить эту функцию в программу, которая должна выполняться в том числе и на Windows 9x/Me, где PSAPI.DLL отстутствует. При реализации других способов перечисления процессов мы поступаем таким же образом.

Функция EnumProcesses не позволяет узнать, сколько места нужно для того, чтобы принять весь массив идентификаторов. Поэтому мы вызываем ее в цикле, увеличивая размер буфера, до тех пор, пока размер возвращенного массива не будет меньше размера буфера.

Поскольку мы хотим помимо идентификаторов процессов получить и имена процессов, мы должны проделать дополнительную работу. Для каждого процесса мы сначала получаем его описатель (handle) c помощью функции OpenProcess и затем используем функцию ЕnumProcessModules , которая возвращает список модулей, загруженных в адресное пространство процесса. Первым модулем в списке всегда является модуль, соответсвующий EXE-файлу программы. Наконец, мы вызываем функцию GetModuleFileNameEx (которая также является частью PSAPI), чтобы получить путь к EXE-файлу по описателю модуля. Мы используем имя EXE-файла без пути в качестве имени процесса.

Oбратите внимание на специальную обработку для двух процессов. Мы вынуждены обрабатывать отдельно процесс бездействия системы (Idle) с идентификатором 0, и системный процесс (System), который имеет идентификатор 2 на Windows NT 4 и 8 — на Windows 2000/XP, потому что OpenProcess не позволяет открыть описатель для этих процессов, возвращая код ошибки ERROR_ACCESS_DENIED.

Если вы запустите тестовое приложение, прилагающееся к этой статье, то обнаружите, что для одного из процессов в качестве имени возвращается «(name unavailable)». Запустив Task Manager нетрудно определить, что этим процессом является CSRSS.EXE. Оказывается, система устанавливает такой дескиптор безопасности этому процессу, который не позволяет открыть его с необходимыми нам правами доступа.

С одной стороны, мы могли бы поступить с этим процессом так же, как с процессами Idle и System, однако нет уверенности, что идентификатор этого процесса является постоянным. С другой стороны, проблему можно решить, включив (enable) привилегию SE_DEBUG_NAME. Когда включена эта привилегия, вызывающий поток может открывать процессы с любыми флагами доступа, независимо от того, какой дескриптор безопасности назначен процессу. Поскольку эта привилегия открывет возможности по преодолению системы безопасности Windows NT, ее имеют лишь администраторы компьютера, и мы не стали добавлять код для включения привилегии непосредственно в функцию EnumProcesses_PsApi . Если необходимо, то привилегия может быть включена перед вызовом EnumProcesses_PsApi , и тогда функция вернет имя и для процесса CSRSS.EXE.

Способ 2. Использование ToolHelp32 API

Корпорация Microsoft добавила набор функций под названием ToolHelp API в Windows 3.1, чтобы позволить сторонним разработчикам получить доступ к системной информации, которая ранее была доступна только программистам Microsoft. При создании Windows 95, эти функции перекочевали в новую систему под названием ToolHelp32 API. Операционная система Windows NT c cамого создания содержала средства для получения подобной информации под названием «данные производительности». Интерфейс для доступа к данным производительности был крайне запутанным и неудобным (справедливости ради надо отметить, что начиная с Windows NT 4.0, Microsoft предоставляет библиотеку Performance Data Helper, значительно облегчающую получение данных производительности; мы воспользуемся этой библиотекой при реализации соответствующего метода перечисления процессов). Говорят, команда Windows NT долгое время сопротивлялась включению ToolHelp32 API в систему, тем не менее, начиная с Windows 2000, ToolHelp32 API присутствует и в этой операционной системе.

Используя ToolHelp32 API, мы сначала создаем моментальный снимок (snapshot) списка процессов с помощью функции CreateToolhelp32Snapshot , а затем проходим по списку используя функции Process32First и Process32Next . Структура PROCESSENTRY32 , заполняемая этими функциями, содержит всю необходимую информацию. Ниже приведен код функции EnumProcesses_ToolHelp , реализующей перечисление процессов с помощью ToolHelp32.

Перед вызовом функций Process32First и Process32Next мы должны инициализировать поле dwSize структуры PROCESSENTRY32 таким образом, чтобы оно содержало размер структуры. Функции в свою очередь заносят в это поле количество байтов, записанных в структуру. Мы сравниваем это значение со смещением поля szExeFile в структуре, чтобы определить, было ли заполнено имя процесса.

Способ 3. Использование функции ZwQuerySystemInformation

Несмотря на наличие документированного способа получения списка процессов в Windows NT с помощью данных производительности, Windows NT Task Manager никогда не использовал этот интерфейс. Вместо этого он использовал недокументированную функцию ZwQuerySystemInformation , экспортируемую из NTDLL.DLL, которая позволяет получить доступ к самой разнообразной системной информации и списку процессов в том числе.

Функция ZwQuerySystemInformation имеет следующий прототип [2]:

SystemInformationClass задает тип получаемой информации, нас интересует SystemProcessesAndThreadsInformation (5)
SystemInformation указатель на буфер, принимающий запрошенную информацию
SystemInformationLength задает длину приемного буфера в байтах
ReturnLength указатель на переменную, в которую заносится количество байтов, записанных в выходной буфер

Формат информации о процессах и потоках описывается структурой SYSTEM_PROCESSES , которая содержит почти всю информацию, отображаемую Task Manager. Ниже привeден код функции EnumProcesses_NtApi , реализующей перечисление процессов с использованием функции ZwQuerySystemInformation .

При вызове ZwQuerySystemInformation трудно заранее определить, какой размер выходного буфера будет достаточным, поэтому мы начинам с буфера размером 32K и увеличиваем его по необходимости.

Структура SYSTEM_PROCESSES имеет переменный размер, поле NextEntryDelta указывает смещение к следующей струтктуре в массиве. Наличие этого поля позволяет нам игнорировать различия в размере фиксированной части структуры между Windows NT 4.0 и Windows 2000, где в состав структуры было добавлено поле IoCounters .

Способ 4. Использование cчетчиков производительности

Как уже отмечалось, операционная система Windows NT с самого создания содержала интерфейс для получения разнообразной информации о системе в виде счетчиков производительности. Этот интерфейс является, скажем, далеко не интуитивным. Для получения той или иной информации нужно прочитать из ключа реестра HKEY_PERFORMANCE_DATA значение со специально сформированным именем. В результате возвращается набор глубоко вложенных структур, многие из которых переменного размера, и разбор этих данных требует определенной усидчивости.

Ситуация изменилась в лучшую сторону с появлением в Windows NT 4.0 библиотеки Performance Data Helper (PDH), которая предоставляет более удобный интерфейс к данным производительности. Эта библиотека, однако, не входила в комплект поставки Windows NT 4.0, она распространялась в составе Microsoft Platform SDK. В Windows 2000 PDH.DLL присутствует по умолчанию.

Подробное рассмотрение данных производительности выходит за рамки данной статьи, отметим лишь, что система подсчета производительности в Windows NT определяет понятие объекта , для которого осуществляется подсчет производительности. Примерами объектов являются процессор и жесткий диск. Каждый объект может иметь один или более экземпляров , и для каждого объекта существует свой набор счетчиков производительности . Наша задача состоит в перечислении всех экземпляров объекта с именем «Process» и получении для каждого из них значения счетчика с именем «ID Process». Ниже приведен код функции EnumProcesses_PerfData , которая использует PDH для перечисления процессов.

Мы возвращаем имя экземпляра объекта в качестве имени процесса. Если вы запустите тестовую программу, то увидите, что имена экземпляров соответсвуют именам исполняемых файлов процессов без расширения.

Названия объектов и счетчиков производительности являются локализуемыми. Это значит, что, например, на русской версии Windows NT необходимо использовать «Процесс» и «Идентификатор процесса» вместо «Process» и «ID Process». Для получения локализованных имен объектов и формирования полного пути к интересующему нас счетчику производительности служит вспомогательная функция PerfFormatCounterPath , исходный код которой приведен ниже.

Мы используем функцию PdhLookupPerfNameByIndex , чтобы получить локализованные имена по их индексам. Для стандартных объектов и счетчиков производительности индексы являются постоянными и не зависят от версии операционной системы, поэтому вполне безопасно задать значения индексов непосредственно в коде.

Отметим, что из перечисленных выше методов, этот метод — первый, который позволяет перечислить процессы на другом компьютере. Все что нужно сделать — это указать имя компьютера в поле szMachineName структуры PDH_COUNTER_PATH_ELEMENTS .

Способ 5. Использование Windows Management Instrumentation

Windows Management Instrumentation (WMI) является реализацией Mircrosoft для так называемой технологии Web-Based Enterprise Management (WBEM). WBEM определяет унифицированную архитектуру, которая позволяет получать данные от различных источников, построенных с помощью различных технологий и платформ, и единообразно представлять эти данные. WBEM основана на схеме общей информационной модели (Common Information Model, CIM), которая является индустриальным стандартом, управляемым Distributed Management Task Force (DMTF). WMI поставляется в составе Windows 2000, но также может быть установлен на Windows 95/98/Me и Windows NT 4.0.

Сколько-либо подробное рассмотрение WMI выходит за рамки этой статьи. Ограничимся лишь кодом, который перечисляет процессы с использованием интерфейсов, предоставляемых WMI.

Поскольку WMI основана на технологии COM, это избавило нас от необходимости явно загружать требуемые библиотеки, как это мы делали в предыдущих примерах. Этот же факт требует инициализации библиотеки COM прежде чем будет вызвана функция перечисления процессов. В приложении, созданном с использованием MFC, это можно сделать с помощью функции AfxOleInit , в остальных случаях следует пользоваться функциями CoInitialize или CoInitializeEx .

Кроме того, использование WMI требует инициализации безопасности COM с помощью функции CoInitializeSecurity :

Заметим, что как и метод с использованием счетчиков производительности, этот метод позволяет перечислить процессы на другом компьютере, для чего нужно указать имя компьютера в вызове IWbemLocator::ConnectServer .

Перечисление процессов на другом компьютере в том виде, в котором оно представлено в последних двух примерах, будет работать только если текущий пользователь локального компьютера включен в группу администраторов удаленного компьютера. Приведенные выше примеры не позволяют изменить имя пользователя и пароль, с которыми производится подключение. Чтобы указать альтернативные имя пользователя и пароль, для PDH следует использовать функцию NetUseAdd или WNetAddConnection2 чтобы установить аутентифицированное соединение с ресурсом IPC$ на удаленном компьютере. Для WMI следует использовать стандартные средства COM. Подробное рассмотрение этих механизмов выходит за рамки данной статьи.

Заключение

Таким образом, мы рассмотрели пять различных способов получения списка процессов. Ни один из них не является универсальным, так как существует версия Windows, где этот метод не работает. Приведенная ниже таблица показывает применимость различных методов.

Windows 9x/Me Windows NT 4.0 Windows 2000/XP
Способ 1 Нет Да * Да
Способ 2 Да Нет Да
Способ 3 Нет Да Да
Способ 4 Нет Да * Да
Способ 5 Да * Да * Да
* Требует установки дополнительных компонент.

Используя эту таблицу и приведенные выше функции, несложно написать функцию перечисления процессов, которая будет работать на всех версиях Windows. Например, если мы хотим использовать PSAPI при работе на Windows NT/2000/XP и ToolHelp32 API — на Windows 9x/Me, то функция будет выглядеть следующим образом:

Как получить подробные сведения о процессах в Windows 7

В статье «Анализ использования памяти с помощью Монитора ресурсов Windows 7» я рассказывал, как использовать Монитор ресурсов (Resource Monitor) для анализа распределения памяти в Windows 7. При этом я упомянул, что графа «Образ» (Image) в таблице «Процессы» (Processes) на вкладке «Память» (Memory) позволяет идентифицировать процессы приложений по имени исполняемого файла. Например, процесс «notepad.exe» со всей очевидностью принадлежит Блокноту (Notepad).

Однако далеко не все процессы можно так легко опознать, и я получил уже немало вопросов от читателей по этому поводу. С идентификацией менее очевидных процессов поможет Диспетчер задач (Task Manager), и в этой статье я расскажу, как его использовать.

Запуск Диспетчера задач

Запустить Диспетчер задач в Windows 7 можно несколькими способами. Во-первых, можно нажать на панели задач правой кнопкой мыши и выбрать опцию «Запустить диспетчер задач» (Start Task Manager). Во-вторых, можно воспользоваться клавишной комбинацией [Ctrl]+[Shift]+[Esc]. И наконец в-третьих, можно запустить исполняемый файл Диспетчера задач из строки поиска меню «Пуск» (Start) — для этого введите taskmgr и нажмите [Enter]. В открывшемся окне выберите вкладку «Процессы» (Processes).

На вкладке «Процессы» есть графа «Описание» (Description, рис. A), в которой приводятся подробные сведения о каждом процессе.

Добавление столбцов на вкладке «Процессы»

Чтобы получить более подробные сведения о процессах Windows 7, воспользуйтесь командой «Выбрать столбцы» (Select Columns) в меню «Вид» (View). Появится диалоговое окно «Выбор столбцов страницы процессов» (Select Process Page Columns), показанное на рис. B. Отсюда можно добавить на вкладку «Процессы» дополнительные колонки — например, столбец «Путь к образу» (Image Path Name), в котором указывается полный путь к файлу, инициировавшему запущенный процесс Windows 7, или графу «Командная строка» (Command Line), где приводится полная команда для запуска процесса со всеми параметрами и переключателями.

Помимо этих столбцов, на вкладку «Процессы» можно добавить и многие другие. Всего в окне «Выбор столбцов страницы процессов» доступно более 30 опций, описание которых не входит в задачи данной статьи. Узнать о назначении всех колонок можно из справочной статьи «Что означают столбцы памяти Диспетчера задач?» на сайте Microsoft.

Опция «Открыть место хранения файла»

Помимо добавления на вкладку столбцов «Путь к образу» и «Командная строка», можно нажать на процессе правой кнопкой мыши и выбрать опцию «Открыть место хранения файла» (Open File Location). При этом откроется папка со всеми файлами, относящимися к данному процессу. К примеру, для процесса «hqtray.exe» на моем компьютере открывается папка «VMware Player» (рис. C).

Еще один источник информации о процессе Windows 7 — окно свойств, которое можно вызвать, нажав на процессе правой кнопкой мыши и выбрав опцию «Свойства» (Properties). Полезные сведения содержатся на вкладке «Подробно» (Details, рис. D).

Если вас интересует процесс «Svchost.exe», можно воспользоваться утилитой командной строки Tasklist, чтобы узнать о нем поподробнее. «Svchost.exe» — общее имя процесса для всех служб, запускаемых из динамически подключаемых библиотек (DLL). Чтобы узнать, каким службам принадлежит этот процесс, откройте командную строку (Command Prompt) и выполните следующую команду:

Вы получите список всех запущенных процессов, в котором приводятся сведения о службах для каждого процесса «Svchost.exe» (рис. E).

Узнав имена служб, запомните идентификатор (PID) процесса «Svchost.exe». Теперь откройте вкладку «Службы» (Services) в Диспетчере задач и отсортируйте список по столбцу «ИД процесса» (PID). Найдите нужный идентификатор и посмотрите описание, чтобы понять назначение службы Windows 7 (рис. F).

Сведения, к сожалению, весьма скудные, но хотя бы позволяют понять, какая именно служба запустила процесс «Svchost.exe».

А что думаете вы?

А вам приходилось использовать Диспетчер задач для поиска информации о запущенных процессах Windows 7? Поделитесь своим опытом в комментариях!

Читайте также:  Как получить windows 10 ltsc
Оцените статью