Cómo obtener los procesos en ejecución y sus datos básicos (nombre de proceso, ruta del ejecutable, id, etc.) mediante Visual Studio .Net C# (C Sharp) y WMI (Windows Management Instrumentation). Incluimos descarga del código fuente completo y gratuito de la aplicación de ejemplo. Para el desarrollo de esta aplicación se usa .NET 6 y Visual Studio .Net Community 2022.
- Crear clase InvProceso.cs en Visual Studio .Net CSharp.
- Crear clase Inventario.cs en Visual Studio .Net CSharp.
- Formulario para probar las clases anteriores y obtener los procesos y sus datos con WMI y C#.
- Aplicación ProyectoA – Obtener Procesos WMI en funcionamiento.
- Descarga del código fuente en C# de Visual Studio .Net Community 2022 de la aplicación completa.
Crear clase InvProceso.cs en Visual Studio .Net CSharp
En primer lugar, para almacenar la información de cada proceso del equipo, crearemos una clase llamada InvProceso.cs. Para ello, pulsaremos con el botón derecho del ratón sobre la solución y elegiremos «Agregar» – «Clase…»:

Introduciremos el nombre de la clase (en nuestro caso InvProceso.cs) y pulsaremos «Aceptar»:

Añadiremos el siguiente código fuente C# a la clase creada:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
namespace ProyectoA_Procesos_WMI { public class InvProceso { public string Name { get; set; } public string ProcessId { get; set; } public long PageFileUsage { get; set; } public long ThreadCount { get; set; } public long WorkingSetSize { get; set; } public string ExecutablePath { get; set; } public string CommandLine { get; set; } public InvProceso() { Name = string.Empty; ProcessId = string.Empty; PageFileUsage = 0; ThreadCount = 0; WorkingSetSize = 0; ExecutablePath = string.Empty; CommandLine = string.Empty; } } } |
Crear clase Inventario.cs en Visual Studio .Net CSharp
De la misma forma, crearemos la clase en la que añadiremos todos los métodos de nuestra aplicación C#. Entre ellos, el método para obtener los procesos del equipo, usando la clase InvProceso.cs anterior para almacenar una lista de clases (lista de procesos). De esta forma, obtendremos todos los datos de todos los procesos del equipo (en una lista de miembros de la clase InvProceso.cs).
El código fuente de la clase Inventario.cs será:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
using System.Management; namespace ProyectoA_Procesos_WMI { class Inventario { public List<InvProceso>? LProcesos { get; set; } //Obtener lista de procesos en ejecución en el equipo public List<InvProceso> ObtenerProcesos() { List<InvProceso> elementos = new List<InvProceso>(); try { ManagementObjectSearcher objBusquedaWMI = new ManagementObjectSearcher("Select ProcessId, Name, PageFileUsage, ThreadCount, WorkingSetSize, ExecutablePath, CommandLine FROM Win32_Process"); foreach (ManagementObject propiedad in objBusquedaWMI.Get().Cast<ManagementObject>()) { InvProceso elemActual = new InvProceso(); try { elemActual.ProcessId = Convert.ToString(propiedad["ProcessId"]); } catch { elemActual.ProcessId = ""; } try { elemActual.Name = Convert.ToString(propiedad["Name"]); } catch { elemActual.Name = ""; } try { if (!long.TryParse(Convert.ToString(propiedad["PageFileUsage"]), out long tamaño)) tamaño = 0; elemActual.PageFileUsage = tamaño; } catch { elemActual.PageFileUsage = 0; } try { if (!long.TryParse(Convert.ToString(propiedad["ThreadCount"]), out long tamaño)) tamaño = 0; elemActual.ThreadCount = tamaño; } catch { elemActual.ThreadCount = 0; } try { if (!long.TryParse(Convert.ToString(propiedad["WorkingSetSize"]), out long tamaño)) tamaño = 0; elemActual.WorkingSetSize = tamaño; } catch { elemActual.WorkingSetSize = 0; } try { elemActual.ExecutablePath = Convert.ToString(propiedad["ExecutablePath"]); } catch { elemActual.ExecutablePath = ""; } try { elemActual.CommandLine = Convert.ToString(propiedad["CommandLine"]); } catch { elemActual.CommandLine = ""; } elementos.Add(elemActual); } LProcesos = elementos; } catch (Exception error) { LProcesos = null; string texto = $"Error al obtener procesos del equipo con WMI. Error: {error.Message}"; MessageBox.Show(texto, "Error al obtener procesos...", MessageBoxButtons.OK, MessageBoxIcon.Error); } return elementos; } } } |
Si algún método da error, como ManagementObjectSearcher, podremos instalarlo directamente desde el código, pasando el ratón por encima del error y pulsando en la bombilla. Mostrará un menú emergente donde indicará «Instalar paquete «System.Management» – «Buscar e instalar la última versión»:

Lo que hará Visual Studio .Net será instalar el paquete necesario por nosotros y agregará el using:
1 |
using System.Management; |
Y agregará la referencia a este paquete (System.Management) para nuestro proyecto:

Todo esto, evidentemente, podemos hacerlo nosotros mismos de forma manual, pero ya hemos comprobado que de forma automática se instala correctamente y es más rápido.
Formulario para probar las clases anteriores y obtener los procesos y sus datos con WMI y C#
Crearemos un formulario con un Button y un TextBox (con propiedad Multiline = True):

En el evento Click del Button añadiremos el siguiente código para obtener los procesos en ejecución en ek equipo y sus datos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
private void btObtenerProcesos_Click(object sender, EventArgs e) { string texto = ""; //Obtenemos la lista de procesos en ejecución del equipo Inventario inventario = new Inventario(); var lsProcesos = inventario.ObtenerProcesos(); if (lsProcesos != null) { //Recorremos todos los elementos de la lista de tipo InvProceso foreach (InvProceso proceso in lsProcesos) { //Guardamos los datos del adaptador proceso actual en texActual //Separamos cada propiedad con un salto de línea string texActual = $"Name: [{proceso.Name}]" + $"\r\n Process ID: [{proceso.ProcessId}]" + $"\r\n Command Line: [{proceso.CommandLine}]" + $"\r\n Executable Path: [{proceso.ExecutablePath}]" + $"\r\n Page File Usage (Bytes): [{proceso.PageFileUsage}]" + $"\r\n Thread Count: [{proceso.ThreadCount}]" + $"\r\n Working Set Size (Bytes): [{proceso.WorkingSetSize}]"; //Si es el primer proceso añadimos el textActual, si es el //segundo o sucesivos, añadimos un salto de línea antes para separarlos texto += texto == "" ? texActual : $"\r\n{texActual}"; } } txtProcesos.Text = texto; } |
Aplicación ProyectoA – Obtener Procesos WMI en funcionamiento
Probaremos la aplicación que obtiene los procesos en ejecución en el equipo y sus datos básicos. Para ello, compilaremos el código fuente anterior pulsando F5. Una vez ejecutada la aplicación, pulsaremos en el botón «Obtener procesos». Devolverá, por ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Name: [wsl.exe] Process ID: [17948] Command Line: [C:\Windows\System32\wsl.exe -d docker-desktop -u root -e wsl-bootstrap run --base-image "/c/Program Files/Docker/Docker/resources/wsl/docker-for-wsl.iso" --cli-iso "/c/Program Files/Docker/Docker/resources/wsl/docker-wsl-cli.iso"] Executable Path: [C:\Program Files\WSL\wsl.exe] Page File Usage (Bytes): [5828] Thread Count: [5] Working Set Size (Bytes): [8380416] Name: [wsl.exe] Process ID: [17960] Command Line: [C:\Windows\System32\wsl.exe -d docker-desktop -e /usr/bin/vpnkit-bridge --pid-file=/run/vpnkit-bridge.pid --addr=stdio guest] Executable Path: [C:\Program Files\WSL\wsl.exe] Page File Usage (Bytes): [5832] Thread Count: [5] Working Set Size (Bytes): [8560640] Name: [wslhost.exe] Process ID: [18120] Command Line: [ --distro-id {f9439294-5072-4e2b-a5c5-54f7e0e290e0} --vm-id {038acbcc-9e6e-4e19-8528-53842305f24a} --handle 756 --event 680 --parent 684] Executable Path: [C:\Program Files\WSL\wslhost.exe] Page File Usage (Bytes): [5608] Thread Count: [2] Working Set Size (Bytes): [8294400] Name: [wslhost.exe] Process ID: [18096] Command Line: [ --distro-id {f9439294-5072-4e2b-a5c5-54f7e0e290e0} --vm-id {038acbcc-9e6e-4e19-8528-53842305f24a} --handle 752 --event 776 --parent 780] Executable Path: [C:\Program Files\WSL\wslhost.exe] Page File Usage (Bytes): [5608] Thread Count: [2] Working Set Size (Bytes): [8294400] |

Descarga del código fuente en C# de Visual Studio .Net Community 2022 de la aplicación completa
Para descargar el código fuente completo de este ejemplo WMI con C#, en Visual Studio .Net Community 2022, con .NET 6.0, accede al siguiente enlace (es completamente gratuito):