Как перечислить все процессы Windows и их атрибуты (например, диспетчер задач) с помощью C # в WinForms

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

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

1. Используйте пространство имен Diagnostics

Для работы с процессами в вашем приложении вам необходимо импортировать System.Diagnostics Пространство имен в верхней части вашего класса:

using System.Diagnostics;

System.Diagnostics Пространство имен предоставляет классы, которые позволяют вам взаимодействовать с системными процессами, журналами событий и счетчиками производительности.

2. Составьте список и получите основную информацию обо всех процессах.

Если вы здесь, потому что вам нужно только знать, как получить список всех процессов в Windows, вам нужно будет обратить внимание только на следующий фрагмент:

// Create an array to store the processes
Process[] processList = Process.GetProcesses();
// Loop through the array to show information of every process in your console
foreach (Process process in processList)
{
Console.WriteLine(@"
{0} | ID: {1} | Status {2} | Memory (private working set in Bytes) {3}",
process.ProcessName, process.Id, process.Responding, process.PrivateMemorySize64);
}

GetProcesses Метод поможет вам, вернув массив, содержащий информацию обо всех процессах в Windows. Выполнение предыдущего кода в вашем проекте должно сгенерировать вывод, подобный следующему:

Memory Compression | ID: 2560 | Status True | Memory (private working set)876544
conhost | ID: 9060 | Status True | Memory (private working set)5054464
MSASCuiL | ID: 13196 | Status True | Memory (private working set)3203072
svchost | ID: 1964 | Status True | Memory (private working set)3485696
chrome | ID: 18740 | Status True | Memory (private working set)97230848
chrome | ID: 2044 | Status True | Memory (private working set)26988544
VBCSCompiler | ID: 6688 | Status True | Memory (private working set)103931904
AppVShNotify | ID: 4020 | Status True | Memory (private working set)1605632

Довольно легко, верно? У объекта процесса есть много свойств, которые вы можете отобразить вашему пользователю, если вам нужно, Узнайте больше о свойствах здесь в MSDN.

3. Создание приложения, похожего на диспетчер задач

В качестве первого шага вам нужно будет создать элемент List View в вашей форме, чтобы отобразить информацию о нем. Этот элемент списка необходимо настроить следующим образом:

  1. На панели свойств элемента (нижний правый угол) установите Посмотреть собственность на подробности из выпадающего меню.
  2. На той же панели выберите свойство Columns, и должно появиться новое окно, в этом окне вы создадите 6 обязательных столбцов, которые мы будем использовать для отображения соответственно той же информации, что и диспетчер задач:

Диспетчер задач Дизайн C #

Теперь вы будете готовы легко отобразить некоторую информацию в этом списке.

Если вы уже прочитали обо всех свойствах, которые объект внутри массива возвращает Process.GetProcesses метод, вы увидите, что по сравнению с информацией, которую вы видите в исходном диспетчере задач Windows, это не так уж полно. Список процессов не содержит всю информацию, которую нам нужно показать в нашем списке, поэтому нам нужно добавить ссылку на System.Management чтобы получить имя пользователя, связанное с процессом и описанием. Для этого вам нужно будет добавить ссылку с менеджером ссылок Visual Studio. Для этого выполните следующие действия:

  1. Щелкните правой кнопкой мыши на Project, Добавить ссылки

  2. Выберите Сборки (рамки) Вкладка и поиск System.Management и, наконец, добавьте ссылку и нажмите ОК.

Добавьте System.Management справочную визуальную студию вручную

Нам нужно добавить System.Management создавать запросы в WMI Classes, Узнайте больше о получении классов WMI в .NET в msdn здесь. После того, как ссылка была добавлена ​​в ваш проект, вы можете импортировать пространство имен System.Management в вашем проекте. Помимо импорта System.Dynamic тоже на вершине вашего класса:

using System.Management;
using System.Dynamic;

Наконец, мы можем начать с кода для отображения информации о процессах в вашем приложении.

Вам решать, когда и где вы хотите выполнить код, который мы сейчас объясним, он может быть выполнен либо нажатием кнопки, либо событием Form_Load формы. Перед тем, как начать с рендеринга, нам нужно решить первую проблему, а именно, что список процессов не содержит имени пользователя Windows, запустившего процесс, и описания процесса. Как мы уже говорили ранее, нам нужно запросить класс WMI, а именно Win32_Process, этот запрос будет искать процесс по одному идентификатору. Как вы, возможно, знаете, у каждого процесса в Windows есть идентификатор, чтобы его можно было легко идентифицировать, поэтому мы можем создать следующий метод, который ожидает в качестве первого аргумента идентификатор процесса, который вы хотите запросить, и он возвратит объект Expando с 2 свойства, которые нам нужны: описание и имя пользователя:

///
/// Returns an Expando object with the description and username of a process from the process ID.
///
///
///
public ExpandoObject GetProcessExtraInformation(int processId)
{
// Query the Win32_Process
string query = "Select * From Win32_Process Where ProcessID = " + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
// Create a dynamic object to store some properties on it
dynamic response = new ExpandoObject();
response.Description = "";
response.Username = "Unknown";
foreach (ManagementObject obj in processList)
{
// Retrieve username
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return Username
response.Username = argList[0];
// You can return the domain too like (PCDesktop-123123\Username using instead
//response.Username = argList[1] + "\\" + argList[0];
}
// Retrieve process description if exists
if (obj["ExecutablePath"] != null)
{
try
{
FileVersionInfo info = FileVersionInfo.GetVersionInfo(obj["ExecutablePath"].ToString());
response.Description = info.FileDescription;
}
catch{}
}
}
return response;
}

Функция довольно проста для понимания, и она будет выполняться с каждым процессом, предоставляемым GetProcesses.

Вторая проблема заключается в том, что вы не хотите отображать значение используемой памяти пользователю в байтах, поскольку ее совсем не легко прочитать, поэтому, если вы сделаете его читаемым с понятными представлениями в КБ, МБ или ГБ и т.д. они будут благодарны. Чтобы преобразовать байты, возвращенные из информации о процессе, в читаемое значение, вы можете использовать следующий метод:

///
/// Method that converts bytes to its human readable value
///
///
///
public string BytesToReadableValue(long number)
{
List suffixes = new List { " B", " KB", " MB", " GB", " TB", " PB" };
for (int i = 0; i < suffixes.Count; i++)
{
long temp = number / (int)Math.Pow(1024, i + 1);
if (temp == 0)
{
return (number / (int)Math.Pow(1024, i)) + suffixes[i];
}
}
return number.ToString();
}

Обратите внимание, что метод ожидает длинное значение и возвращает строку. В качестве последнего шага мы можем теперь начать отображать информацию в представлении списка.

Вам необходимо получить список процессов и сохранить его в переменной, кроме того, вам нужно создать элемент списка изображений, в котором будут храниться значки каждого процесса (в случае, если они есть). Затем нам нужно перебрать массив процессов с помощью оператора foreach, в каждом цикле GetProcessExtraInformation будет выполнен (с идентификатором процесса в качестве первого аргумента), чтобы получить необходимую информацию, которой у нас нет, из переменной процесса в цикле. Затем будет создан массив строк, в котором будут храниться (соответственно значения должны следовать в том же порядке, что и столбцы в элементе списка) информация о каждой строке в элементе списка (обратите внимание, что мы преобразуем байты в читаемое значение с помощью BytesToReadableValue метод). При желании вы можете добавить значки в список, добавив новый элемент в ранее созданный список изображений. В списке изображений необходимо указать идентификатор (ключ) для изображения, которое вы хотите добавить (в данном случае значок процесса), а в качестве второго аргумента - данные изображения значка, которые можно получить с помощью Icon.ExtractAssociatedIcon метод, который ожидает путь к исполняемому файлу процесса (который может быть получен через объект процесса), этот значок можно преобразовать в растровое изображение, как показано в примере, чтобы повысить качество, однако при желании вы можете удалить метод toBitmap.

Наконец, создайте новый ListViewItem для добавления со строкой в ​​качестве первого аргумента и укажите, какое изображение из списка изображений следует использовать для элемента, и добавьте его в представление списка:

///
/// This method renders all the processes of Windows on a ListView with some values and icons.
///
public void renderProcessesOnListView()
{
// Create an array to store the processes
Process[] processList = Process.GetProcesses();
// Create an Imagelist that will store the icons of every process
ImageList Imagelist = new ImageList();
// Loop through the array of processes to show information of every process in your console
foreach (Process process in processList)
{
// Define the status from a boolean to a simple string
string status = (process.Responding == true ? "Responding" : "Not responding");
// Retrieve the object of extra information of the process (to retrieve Username and Description)
dynamic extraProcessInfo = GetProcessExtraInformation(process.Id);
// Create an array of string that will store the information to display in our
string[] row = {
// 1 Process name
process.ProcessName,
// 2 Process ID
process.Id.ToString(),
// 3 Process status
status,
// 4 Username that started the process
extraProcessInfo.Username,
// 5 Memory usage
BytesToReadableValue(process.PrivateMemorySize64),
// 6 Description of the process
extraProcessInfo.Description
};
//
// As not every process has an icon then, prevent the app from crash
try
{
Imagelist.Images.Add(
// Add an unique Key as identifier for the icon (same as the ID of the process)
process.Id.ToString(),
// Add Icon to the List
Icon.ExtractAssociatedIcon(process.MainModule.FileName).ToBitmap()
);
}
catch { }
// Create a new Item to add into the list view that expects the row of information as first argument
ListViewItem item = new ListViewItem(row)
{
// Set the ImageIndex of the item as the same defined in the previous try-catch
ImageIndex = Imagelist.Images.IndexOfKey(process.Id.ToString())
};
// Add the Item
listView1.Items.Add(item);
}
// Set the imagelist of your list view the previous created list :)
listView1.LargeImageList = Imagelist;
listView1.SmallImageList = Imagelist;
}

Обратите внимание, что вам нужно установить значение свойств LargeImageList и SmallImageList в качестве ImageList, который мы создали для иконок. Чтобы сделать эту работу, вам нужно всего лишь выполнить renderProcessesOnListView функция, когда вам нужно отобразить услуги в вашем списке.

4. Последний пример

Если вы уже прочитали, как все работает, вы можете просто следовать всему примеру и реализовать его самостоятельно в своем проекте:

Важный

Не забывайте, что вам нужно добавить ссылку на System.Management в ваш проект, как показано в шаге № 3. С другой стороны, вам нужно создать элемент представления списка, идентифицированный как listView1, со свойством View, установленным в Details, и соответственно с 6 элементами в свойстве Columns.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
// Required namespaces
using System.Diagnostics;
using System.Management;
using System.Dynamic;
namespace Sandbox
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Once the form loads, render the items on the list
renderProcessesOnListView();
}
///
/// This method renders all the processes of Windows on a ListView with some values and icons.
///
public void renderProcessesOnListView()
{
// Create an array to store the processes
Process[] processList = Process.GetProcesses();
// Create an Imagelist that will store the icons of every process
ImageList Imagelist = new ImageList();
// Loop through the array of processes to show information of every process in your console
foreach (Process process in processList)
{
// Define the status from a boolean to a simple string
string status = (process.Responding == true ? "Responding" : "Not responding");
// Retrieve the object of extra information of the process (to retrieve Username and Description)
dynamic extraProcessInfo = GetProcessExtraInformation(process.Id);
// Create an array of string that will store the information to display in our
string[] row = {
// 1 Process name
process.ProcessName,
// 2 Process ID
process.Id.ToString(),
// 3 Process status
status,
// 4 Username that started the process
extraProcessInfo.Username,
// 5 Memory usage
BytesToReadableValue(process.PrivateMemorySize64),
// 6 Description of the process
extraProcessInfo.Description
};
//
// As not every process has an icon then, prevent the app from crash
try
{
Imagelist.Images.Add(
// Add an unique Key as identifier for the icon (same as the ID of the process)
process.Id.ToString(),
// Add Icon to the List
Icon.ExtractAssociatedIcon(process.MainModule.FileName).ToBitmap()
);
}
catch { }
// Create a new Item to add into the list view that expects the row of information as first argument
ListViewItem item = new ListViewItem(row)
{
// Set the ImageIndex of the item as the same defined in the previous try-catch
ImageIndex = Imagelist.Images.IndexOfKey(process.Id.ToString())
};
// Add the Item
listView1.Items.Add(item);
}
// Set the imagelist of your list view the previous created list :)
listView1.LargeImageList = Imagelist;
listView1.SmallImageList = Imagelist;
}
///
/// Method that converts bytes to its human readable value
///
///
///
public string BytesToReadableValue(long number)
{
List suffixes = new List { " B", " KB", " MB", " GB", " TB", " PB" };
for (int i = 0; i < suffixes.Count; i++)
{
long temp = number / (int)Math.Pow(1024, i + 1);
if (temp == 0)
{
return (number / (int)Math.Pow(1024, i)) + suffixes[i];
}
}
return number.ToString();
}
///
/// Returns an Expando object with the description and username of a process from the process ID.
///
///
///
public ExpandoObject GetProcessExtraInformation(int processId)
{
// Query the Win32_Process
string query = "Select * From Win32_Process Where ProcessID = " + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
// Create a dynamic object to store some properties on it
dynamic response = new ExpandoObject();
response.Description = "";
response.Username = "Unknown";
foreach (ManagementObject obj in processList)
{
// Retrieve username
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return Username
response.Username = argList[0];
// You can return the domain too like (PCDesktop-123123\Username using instead
//response.Username = argList[1] + "\\" + argList[0];
}
// Retrieve process description if exists
if (obj["ExecutablePath"] != null)
{
try
{
FileVersionInfo info = FileVersionInfo.GetVersionInfo(obj["ExecutablePath"].ToString());
response.Description = info.FileDescription;
}
catch{}
}
}
return response;
}
}
}

Как показано на изображении статьи, появится окно со списком всех процессов в Windows, а рядом с названием процесса и другими свойствами появится значок.

Ссылка на основную публикацию
Adblock
detector