Изучение процессов

35

Помимо полного списка всех выполняющихся на конкретной машине процессов, статический метод Process.GetProcessById() позволяет получать информацию и по конкретному объекту Process за счет указания ассоциируемого с ним идентификатора (PID). В случае запроса несуществующего PID генерируется исключение ArgumentException.

Набор потоков представляется в виде строго типизованной коллекции ProcessThreadCollection, в которой содержится определенное количество отдельных объектов ProcessThread. Свойство Threads в System.Diagnostics.Process предоставляет доступ к классу ProcessThreadCollection, некоторые наиболее интересные члены которого перечислены ниже:

CurrentPriority

Позволяет получить информацию о текущем приоритете потока

Id

Позволяет получить уникальный идентификатор потока

IdealProcessor

Позволяет указать предпочитаемый процессор для выполнения данного потока

PriorityLevel

Позволяет получить или задать уровень приоритета потока

ProcessorAffinity

Позволяет указать процессоры, на которых может выполняться соответствующий поток

StartAddress

Позволяет узнать, по какому адресу в памяти операционная система вызывала функцию, приведшую к запуску данного потока

StartTime

Позволяет узнать, когда операционная система запустила поток

ThreadState

Позволяет узнать текущее состояние данного потока

TotalProcessorTime

Позволяет узнать, сколько всего времени данный поток использовал процессор

WaitReason

Позволяет узнать причину, по которой поток находится в состоянии ожидания

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

Теперь давайте посмотрим, как реализовать проход по загруженным модулям, которые обслуживаются в рамках конкретного процесса. При обсуждении процессов модуль — это общий термин, используемый для описания заданной сборки *.dll (или *.ехе), которая обслуживается в определенном процессе. При получении доступа к ProcessModuleCollection через свойство Process.Modules можно извлечь список всех модулей, которые обслуживаются внутри процесса: .NET, СОМ и традиционных основанных на С библиотек.

И, наконец, последними членами класса System.Diagnostics.Process, которые осталось рассмотреть, являются методы Start() и Kill(). Эти методы позволяют, соответственно, программно запускать и завершать процесс. Метод Start() может принимать тип System.Diagnostics.ProcessStartInfо и предоставлять дополнительные фрагменты информации относительно запуска определенного процесса.

Давайте рассмотрим пример глобального изучения процессов:

using System;
using System.Linq;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("*** ПРОЦЕССЫ ***\n");
            string comm = Command();
            UseMyCommand(comm);
            // Используем рекурсию для вызова новых команд
            if (comm != "X")
                  Main();
        }

        static string Command()
        {
            Console.WriteLine("Какую информацию нужно получить? \n"+
                " 1 - Список всех процессов\n 2 - Выбрать процесс по PID\n"+
                " 3 - Информация о потоках\n 4 - Информация о подключаемых модулях\n"+
                " 5 - Запуск процесса\n 6 - Останов процесса\n X - выход\n");
            Console.Write("Введите команду: ");
            string comm = Console.ReadLine();
            return comm;
        }

        static void UseMyCommand(string str)
        {
            switch (str)
            {
                case "X":
                    break;
                case "1":
                    AllInfoProcess();
                    break;
                case "2":
                    ProcInMyPid();
                    break;
                case "3":
                    Threads();
                    break;
                case "4":
                    InfoByModuleProc();
                    break;
                case "5":
                    StartProcess();
                    break;
                case "6":
                    StopProcess();
                    break;
                default:
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Команда не распознана!");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    break;
            }
            Console.WriteLine();
        }

        static void AllInfoProcess()
        {
            var myProcess = from proc in Process.GetProcesses(".") 
                            orderby proc.Id select proc;
            Console.WriteLine("\n*** Текущие процессы ***\n");
            foreach (var p in myProcess)
                Console.WriteLine("-> PID: {0}\tName: {1}",p.Id,p.ProcessName);
        }

        static void ProcInMyPid()
        {
            Console.Write("Введите PID-идентификатор: ");
            string pid = Console.ReadLine();
            Process myProc = null;
            try
            {
                int i = int.Parse(pid);
                myProc = Process.GetProcessById(i);
                Console.WriteLine("\n-> PID: {0}\tName: {1}\n",myProc.Id,myProc.ProcessName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        static void Threads()
        {
            Console.Write("Введите PID-идентификатор: ");
            string pid = Console.ReadLine();
            Process myProc = null;
            try
            {
                int i = int.Parse(pid);
                myProc = Process.GetProcessById(i);
                // Получаем коллекцию потоков процесса
                ProcessThreadCollection threads = myProc.Threads;
                Console.WriteLine("Потоки процесса {0}:\n", myProc.ProcessName);
                foreach (ProcessThread pt in threads)
                    Console.WriteLine("-> Thread ID: {0}\tВремя: {1}\tПриоритет: {2}"
                        , pt.Id, pt.StartTime.ToShortTimeString(), pt.PriorityLevel);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.WriteLine();
            }
        }

        static void InfoByModuleProc()
        {
            Console.Write("Введите PID-идентификатор: ");
            string pid = Console.ReadLine();
            Process myProc = null;
            try
            {
                int i = int.Parse(pid);
                myProc = Process.GetProcessById(i);
                Console.WriteLine("Подключаемые модули процесса {0}:\n", myProc.ProcessName);
                // Получаем коллекцию модулей
                ProcessModuleCollection mods = myProc.Modules;
                foreach (ProcessModule pm in mods)
                    Console.WriteLine("-> Имя модуля: "+pm.ModuleName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.WriteLine();
            }
        }

        static void StartProcess()
        {
            Process myProc = null;
            // Запустить сайт professorweb.ru на машине пользователя
            try
            {
                // Будет работать только для пользавателей у которых установлен браузер Google Chrome
                // Чтобы запустить IE, нужно запустить процесс IExplore.exe
                myProc = Process.Start("chrome.exe", "www.professorweb.ru");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        static void StopProcess()
        {
            Console.Write("Введите PID-идентификатор процесса, который нужно остановить: ");
            string pid = Console.ReadLine();
            Process myProc = null;
            try
            {
                int i = int.Parse(pid);
                myProc = Process.GetProcessById(i);
                myProc.Kill();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

Данное приложение является многофункциональным и позволяет просмотреть все текущие процессы на машине пользователя, найти процесс по PID-идентификатору, получить информацию о потоках и подключаемых модулях процесса, а также запустить или остановить процесс (в качестве примера запуска процесса приведен запуск браузера Google Chrome и передача ему URL professorweb.ru).

Использование процессов Windows
Пройди тесты
Лучший чат для C# программистов