Archivo

Entradas Etiquetadas ‘WMI’

Procesos y Threads (GLibWMI)

Lunes, 14 de marzo de 2016 Sin comentarios
Share Button

threadA partir de esta consulta en el clubdelphi, sobre procesos y threads he decidido crear esta entrada; Para ello he compilado la librería GLibWMI en Delphi Seatle. La última versión que hay en la web está compilada y comprobada para Delphi XE7 y funciona sin problemas, así que era de esperar que en Seatle lo hiciera también sin cambios.

Yo mismo la estoy usando en algún proyecto antiguo en Delphi 6/7  y en algunas de las versiones más nuevas de Delphi XE.

Volviendo al tema que nos ocupa, en este caso nos interesa obtener información de los threads asociados a un determinado proceso que está corriendo en la máquina.

Para ello seguiremos los siguientes pasos:

  1. Acceder a la información del proceso
  2. Acceder a la información de los threads asociados a ese proceso.

Me voy a basar en la librería GLibWMI, aunque se puede hacer lo mismo utilizando código, sino deseamos instalar librerías de componentes adicionales.

Dentro de los componentes de GLibWMI, hay algunos que ya nos permiten acceder a clases “destacadas” o “habituales”. Entre ellos se encuentra ProcessInfo, por ejemplo, que nos da información  de los procesos ejecutandose (lo usaremos para el primer paso), pero WMI tiene muchas clases más.

Para acceder a cualquier otra clase o a datos particulares de una concreta, hay un componente llamado WMISQL, que nos permite lanzar “sentencias SQL” (algo parecido) sobre clases de WMI. Este componente es el que nos permitirá acceder a la información de los Threads (para los que no tenemos componente específico).

INFORMACIÓN DEL PROCESO

La información de los procesos funcionando en la máquina nos la da la clase Win32_Process.

Podemos utilizar el componente ProcessInfo. Basta con “soltar” el componente en un formulario y activarlo.

Este componente nos ofrece una lista de objetos TProcessProperties, la propiedad ObjectCount que nos da el número de elementos encontrados y la propiedad ObjectIndex que marca el elemento actual.

Podemos encontrar y obtener datos de un proceso con un código similar a este:

0
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
var
  str:string;
  i:integer;
  p:TProcessProperties; // para abreviar
begin
  // ini
  Memo1.Lines.Clear;
  // Activarlo
  ProcessInfo1.Active := True;
  // tenemos elementos?
  if (ProcessInfo1.ObjectsCount "MAYOR QUE" 0) then begin   //!!! Cambiar "MAYOR QUE" por el operador...
    // Buscamos un proceso concreto
    for i := 0 to (ProcessInfo1.ObjectsCount -1 ) do begin
      p := ProcessInfo1.ProcessProperties;
      // es el ibServer
      if (AnsiCompareText('ibserver.exe', p.Caption) = 0) then begin
        Memo1.Lines.Add('Nombre:        ' + p.Name);
        Memo1.Lines.Add('Caption:       ' + p.Caption);
        Memo1.Lines.Add('CommandLine:   ' + p.CommandLine);
        Memo1.Lines.Add('Path del EXE:  ' + p.ExecutablePath);
        Memo1.Lines.Add('Handle:        ' + p.Handle);
        Memo1.Lines.Add('Prioridad:     ' + IntToStr(p.Priority));
        Memo1.Lines.Add('Identificador: ' + IntToStr(p.ProcessId));
        Memo1.Lines.Add('Num. threads:  ' + IntToStr(p.ThreadCount));
 
        Break
      end;
      // Siguiente
      ProcessInfo1.ObjectIndex := ProcessInfo1.ObjectIndex + 1;
    end;
  end;
end;

 

Si lo ejecutamos obtendremos algo como esto:

En este caso, el componente ProcessInfo no es el más adecuado, ya que estamos obteniendo la información de TODOS los procesos, cuando sólo queremos acceder a uno sólo (ibserver, en el ejemplo anterior).

Para este caso, es más conveniente utilizar el componente WMISQL. Ya que podemos “minimizar” el tráfico de datos que solicitamos.

Para ello, este componente posee la propiedad SQL.

Aquí vemos las propiedades de este componente:

Añadiremos esta sentencia:

0
SELECT * FROM Win32_Process WHERE name = "ibserver.exe"

Si tan sólo queremos algunos datos, podemos afinar más la consulta para dejarla así:

0
1
SELECT Caption, CommandLine, ExecutablePath, Name, Handle, Handlecount, 
Priority, ProcessId, ThreadCount FROM Win32_Process WHERE name = "ibserver.exe"

 

Una vez activamos el componente, podemos acceder al resultado de la siguiente manera (vemos 2 opciones diferentes utilizando un TMemo -con la respuesta tal cual la da WMI- y un ValueListEditor -cuadro inferior-).

0
1
2
3
4
5
6
7
8
9
10
   // ini
  Memo1.Lines.Clear;
  // Activar
  WMISQL1.Active := True;
  // tenemos elementos?
  if (WMISQL1.ObjectsCount > 0) then begin
    // respuesta de WMI
    Memo1.Lines.Text := WMISQL1.AllProperties.Text;
    // Lista de propiedades
    ValueListEditor1.Strings.AddStrings(WMISQL1.Properties);
  end;

Como resultado obtendremos algo como esto:

Vemos que la propiedad ThreadCount nos devuelve 5.

 

INFORMACIÓN DE THREADS

Volviendo al tema original, una vez tenemos el identificador de nuestro proceso (en este caso el ProcessID=5848), necesitamos obtener los threads de este proceso y los datos asociados.

Para ver más información, podéis acceder a este link donde están todas las propiedades accesibles, la explicación de cada una de ellas y los diferentes valores que adoptan.

Vamos a utilizar en este caso otro componente WMISQL (o reaprovechar el mismo) y cambiaremos la consulta por esta otra:

0
SELECT * FROM Win32_Thread WHERE ProcessHandle=5848

 

Si activamos el componente en diseño (que se puede hacer) ya podemos ver que la propiedad ObjectCount es 5, por lo tanto ibserver tiene en este momento, 5 threads en marcha que dependen de él.

Con el siguiente código podemos obtener información de cada uno de ellos:

0
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
var
  i, j:integer;
  str:string;
  h, m, s:int64;
  p:TStrings;  // para abreviar
begin
  // ini
  Memo1.Lines.Clear;
  ValueListEditor1.Strings.Clear;
  // Activar
  WMISQL1.Active := True;
  // tenemos elementos?
  if (WMISQL1.ObjectsCount > 0) then begin
    // recorrer los threads y obtener datos
    for i := 0 to (WMISQL1.ObjectsCount - 1) do begin
      p := WMISQL1.Properties;
      j := StrToIntDef(p.Values['ElapsedTime'], 0); // milisegundos
      if (j > 0) then begin
      h := (j DIV 3600000);                        // horas
      m := (j - (h * 3600000)) DIV 60000;          // minutos
      s := (j MOD 60000) DIV 1000;                 // segundos
        Memo1.Lines.Add(Format('Tiempo ejec.:   %d:%d:%d', [h, m, s]));
      end;
      Memo1.Lines.Add('Handle:         ' + p.Values['Handle']);
      Memo1.Lines.Add('Prioridad:      ' + p.Values['Priority']);
      Memo1.Lines.Add('Prioridad base: ' + p.Values['PriorityBase']);
      Memo1.Lines.Add('Id. proceso:    ' + p.Values['ProcessHandle']);
      Memo1.Lines.Add('Estado:         ' + p.Values['ThreadState']);
      Memo1.Lines.Add('··········································');
    end;
  end;
end;

 

El resultado al mostrarlo por pantalla será algo similar a esto:

Con esto ya hemos acabado. La idea es mostrar la potencia de WMI y la sencillez con la que podemos utilizar esa información accediendo desde Delphi. Como os he dicho, podéis acceder a WMI sin necesidad de componentes, utilizando código delphi.

En entradas anteriores hemos comentado cómo hacerlo.

Un saludo y hasta la próxima.

Share Button
Categories: Delphi, Ejemplos, GLibWMI, WMI Tags: , ,

Actualización de GLibWMI a Delphi XE7 (2.1b)

Miércoles, 10 de septiembre de 2014 4 comentarios
Share Button

Imagen_entrada1Como he hecho en otras ocasiones coincidiendo con el lanzamiento de las nuevas versiones de Delphi, en este caso también he realizado la compilación de la librería para la versión XE7 de Delphi.

En esta versión, aprovechando, he añadido alguna mínima corrección y algún cambio sugerido por los usuarios.

Además de alguna demo nueva para el componente de consultas WMI.

Tenéis una descripción más amplia de la librería y algunas capturas de pantalla junto con el listado de todos los componentes que incluye, en la sección dedicada a ella.

Los componentes también se pueden descargar desde Sourceforge.

ejemplos

 

Se puede descargar la librería completa, las demos compiladas (sólo ejecutables) y el código fuente de las demos.

Share Button

“Server PING” utilizando WMI…

Domingo, 13 de octubre de 2013 1 comentario
Share Button

Imagen1Ya he hablado otras veces en el blog de la WMI (Windows Management Instrumentation), con ejemplos y artículos; Además también podéis encontrar en la sección de componentes la librería GLibWMI que utiliza esta característica de windows para acceder a diferente información de un  sistema que corra el susodicho S.O. de Microsoft.

En este caso quiero compartir con vosotros una sencilla aplicación que permite “monitorizar” a través de PING el estado de un ordenador remoto.

Esta pequeña aplicación la he creado a partir de la necesidad de conocer el tiempo de respuesta de un equipo a lo largo de una jornada. Necesitaba saber si a lo largo de unas horas se producían cortes o bajadas en el tiempo de respuesta.

Para ello he realizado un ping periódico y almacenando los resultados, para poder analizar a posteriori si la respuesta ha sido homogénea.

imagesPodemos realizar un PING desde Delphi utilizando las librerías Indy, mediante el componente TIdIcmpClient y otra opción es  utilizar la librería ICMP.DLL de Windows y Winsock.

En este caso, lo he realizado utilizando una tercera opción que es, mediante WMI.

Leer más…

Share Button
Categories: Delphi, Ping, WMI Tags: , ,

GlibWMI 1.8beta liberada (Sourceforge)

Miércoles, 24 de febrero de 2010 6 comentarios
Share Button

Acabo de cerrar la versión 1.8b de la librería GLibWMI.

Nuevos componentes y algunas correciones a errores referentes a propiedades y “leaks” de memoria (los más importantes).

La librería está accesible completa en SourceForge (GLibWMI).

SourceForge

Podéis descargar los fuentes vía SVN desde:

http://glibwmi.svn.sourceforge.net/svnroot/glibwmi/

O también podéis descargar los ficheros desde aquí.

Share Button

GlibWMI 1.6beta liberada (Sourceforge)

Viernes, 22 de enero de 2010 2 comentarios
Share Button

Acabo de cerrar la versión 1.6 beta.

He subido la versión completa a Sourceforge.  A partir de ahora estará disponible allí completa (fuentes incluídos) con licencia GNU.

En esta última versión se han añadido nuevos componentes, nuevos métodos y corrección de algunos errores.

También se pueden descargar los ficheros desde aquí.

Por supuesto (y como siempre), se aceptan cualquier tipo de comentarios, dudas, sugerencias, críticas,…

ACTUALIZACIÓN: A partir de este momento se pueden descargar los fuentes vía SVN desde:

http://glibwmi.svn.sourceforge.net/svnroot/glibwmi/

Un saludo.

Share Button

GLibWMI Versión 1.3 (beta)

Lunes, 11 de enero de 2010 Sin comentarios
Share Button

Acabo de empaquetar la versión 1.3 (beta) de la librería de componentes GLibWMI, basados en la WMI de Windows.

Básicamente he añadido nuevos componentes y he corregido algunos errores que incluía la demo general. Además he testado la librería en Delphi 2009 sin ningun problema a la hora de compilar. Doy por supesto que en todas las intermedias entre D7 y D2009 fucionará sin problemas.

Los componentes nuevos son:

  • CProcessInfo:  Información acerca de los procesos que hay ejecutándose en el sistema..
  • CServiceInfo:   Información detalleda de los servicios que hay instalados en el sistema..
  • CDesktopMonitorInfo:   Información detallada sobre el monitor o dispositivo de visualización que hay en el sistema.
  • CComputerSystemInfo:   Información acerca del sistema en General.
  • CStartupCommandInfo:    Información acerca de los procesos que se ejecutan automáticamente cuando el usuario hace el Login en el sistema.

<Ver más detalles>

Share Button

Componentes GLibWMI

Viernes, 8 de enero de 2010 53 comentarios
Share Button

GLibWMI es una librería/biblioteca de componentes enfocados a la Administración de Sistemas Windows.
Están basados en la WMI de Windows (Windows Management Instrumentation). Podéis conocer algo más sobre WMI en la entrada del blog titulada “WMI – Introducción“.

_________________________________________________________

ACTUALIZACIÓN:  1o/09/2014.

Liberada la Versión 2.1b.

Nuevas propiedades en los componentes y algunos errores corregidos.

Además la librería se ha compilado con Delphi XE7 sin problemas.

ejemplos_thumb.png

<DESCARGAR LIBRERÍA COMPLETA>

<DESCARGAR SOURCE DEMOS>

<DESCARGAR EXE DEMOS>

_________________________________________________________

ACTUALIZACIÓN:  01/08/2013.

Liberada la Versión 2.0b.

Nuevos componentes añadidos (BootConfigurationInfo, DesktopInfo CodecsInfo, RegistryInfo, TimeZoneInfo) y corrección de algunos bugs.
Compilado para las nuevas versiones de Delphi, incluídas XE4 y XE5.

 Versión 2.0 GLibWMI

<DESCARGAR LIBRERÍA COMPLETA>

<DESCARGAR SOURCE DEMOS>

<DESCARGAR EXE DEMOS>

_________________________________________________________

ACTUALIZACIÓN:  23/02/2010.

Liberada la Versión 1.8b.

Nuevos componentes añadidos y corrección de algunos bugs; Correción en la recuperación de propiedades y algunas pérdidas de memoria.

Actualizadas las demos con los nuevos componentes.

Como la anterior verión, los últimos cambios están subidos en Sourceforge (GLibWMI).

<Descargar librería completa;  Sources+Bin>

<Descargar demos; Sources+Bin>

<Descargar demos; Bin>

_________________________________________________________

ACTUALIZACIÓN:  22/01/2010.

Versión 1.6b.

He subido el proyecto a Sourceforge (GLibWMI). La ultima versión estará disponible allí para su descarga.

Se distribuye con licencia GNU y todos los ficheros (incluídos los fuentes se pueden descargar).

Descargar ficheros:

<GLibWMI completa 1.6b>
<GLibWMI demos 1.6b>
<GLibWMI EXE demos 1.6b>

_________________________________________________________

La librería está en fase beta y se puede usar de forma libre y gratuíta.

Las versiones actuales están disponibles (ficheros compilados) para D6, D7 y D2009.

Se pueden descargar diferentes paquetes:

<GLibWMI>
<GLibWMI para Delphi 6>
<GLibWMI para Delphi 7>
<GLibWMI para Delphi 2009>
<Demos compiladas>>

Funciona sin problemas en sistemas basados en Windows 2000 y posteriores.
Para más información consultar:
Operating System Availability of WMI Components

Como bien he dicho, están en fase beta, así que se aditen sugerencias, errores, comentarios,…

Un saludo.

Share Button

Inventario de software instalado (WMI)

Martes, 24 de noviembre de 2009 2 comentarios
Share Button

Siguiendo con los ejempos y ahondando en las posibilidades de WMI (Windows Management Instrumentation), a raiz de este hilo en los foros del ClubDelphi, referente al software instalado en nuestro ordenador, he probado a obtener la lista de programas instalados utilizando la WMI.

Para ello podemos utilizar la clase Win32_Product.
Si accedemos a su descripción en MSDN, obtenemos la siguiente descripción de la clase:

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
class Win32_Product : CIM_Product
{
  uint16   AssignmentType;
  string   Caption;
  string   Description;
  string   IdentifyingNumber;
  string   InstallDate;
  datetime InstallDate2;
  string   InstallLocation;
  sint16   InstallState;
  string   HelpLink;
  string   HelpTelephone;
  string   InstallSource;
  string   Language;
  string   LocalPackage;
  string   Name;
  string   PackageCache;
  string   PackageCode;
  string   PackageName;
  string   ProductID;
  string   RegOwner;
  string   RegCompany;
  string   SKUNumber;
  string   Transforms;
  string   URLInfoAbout;
  string   URLUpdateInfo;
  string   Vendor;
  uint32   WordCount;
  string   Version;
};

Podemos disponer así de toda la información, referente a cada uno de los programas/aplicaciones instalados en nuestro equipo (*NOTA*).

Para ello, lo primero que debemos hacer es Importar a Delphi la librería “Microsoft WMI Scripting v1.X Library (Version 1.X)“, si no lo hemos hecho ya.
En la Introducción sobre WMI, se explica un poco más detalladamente.

Una vez importada, lo siguiente (dentro de nuestro ejemplo) es conectar con nuestro proveedor (en este caso nuestra máquina local):

1
2
3
4
5
6
    // Create the Location object
    Locator := CoSWbemLocator.Create();
    // Connect to the WMI service, with the root\cimv2 namespace
    aServices := Locator.ConnectServer(STR_EMPTY, {Server}
        STR_CIM2_ROOT, {user}STR_EMPTY, {password}STR_EMPTY,
        STR_EMPTY,STR_EMPTY, 0, nil);

A continuación, si la conexión ha sido correcta, realizamos la consulta sobre la clase Win32_Product, que nos dará la información que necesitamos.

1
2
3
// realizar la consulta
ObjSet := Services.ExecQuery('SELECT * FROM Win32_Product',
 'WQL', wbemFlagReturnImmediately and wbemFlagForwardOnly , nil);

A partir de ahí basta con recorrer los elementos obtenidos y e nuestro caso formatear algunas propiedades para mostrarlas (Caption, InstallDate, Vendor y Version), aunque todas las demás están igualmente a disponsición del programador.

Recordad de colocar en el USES las dos units comentadas antes.

Se puede descargar el código de ejemplo desde aquí y el ejecutable compilado desde aquí.

<Ejemplo_sources>

<Ejemplo_Ejecutable>

(*NOTA*): Recordemos (link), que una de las características de WMI es que permite “Administración remota”, con lo que si tenemos los suficientes permisos, este código también puede servir para inventariar otras máquinas.

Share Button

WMI – Introducción

Martes, 24 de noviembre de 2009 2 comentarios
Share Button

No hace mucho me cruce con esta “palabrota” este concepto: WMI.

A priori parece sólo eso, una “palabrota” más, de las muchas que nos encontramos en nuestro día a día “informático”. Pero rascando, rascando ha aparecido una perla oculta bajo una capa de polvo.

WMI son las iniciales de “Windows Management Instrumentation”. Se me hace complicado explicar en pocas palabras qué es, pero si tuviera que hacerlo, diría que es algo así como “Una puerta de acceso a la Administración de Sistemas Windows” ( ;-D Windows Management Instrumentation).

Junto a WMI aparecen dos “palabrotas” dos conceptos más que nos ayudan a saber de dónde viene.

  • WBEM (Web-Based Enterprise Management )
  • CMI (Common Model Information).

Si las juntamos todas nos queda que, WMI es una implementación que Microsoft ha hecho para Windows, de un estandard llamado WBEM que sirve para la administración de sistemas vía web y que está basado en CIM, que vienen a ser unas clases que nos dan acceso a diferente información del un equipo.

(Traducción al idioma Terrícola):

“A través de WMI yo puedo administrar un equipo basado en Windows, local o remoto, independientemente de la versión del sistema, utilizando las clases que me provee CIM.”

Y esto visto desde el punto de vista de un programador tiene muy buena pinta.

Este podría ser un gráfico sencillo de su estructura.

Dicho esto, yo me pregunto, ¿Qué tiene de bueno WMI y qué puede hacer por mi? (en el terreno más práctico)

  • Utilizando WMI podemos consultar información sobre nuestro equipo. Desde las aplicaciones instaladas, a la información de la BIOS, discos duros instalados, particiones creadas, Antivirus instalado si lo hay, nivel de carga de la batería (si conviene), procesos ejecutándose, acceso a los servicios instalados, acceso a las tareas programadas, y la lista sigue y sigue…
  • Cuando hablamos de administración significa que no sólo podemos consultar estos parámetros, sino también modificarlos en muchos casos.
  • Administración remota. Significa que lo dicho anteriormente se aplica también a administración remota. Es decir, no sólo podemos hacerlo en nuestro equipo, sino en el resto de equipos de la red. WMI está presente en sistemas Windows 2000 con SP2 en adelante. Para los anteriores (95, 98 y NT 4.0) se puede descargar un SDK para instalarlo (link).
  • Es extensible. Microsoft añade nuevas clases a cada versión de Windows. Además se pueden crear nuevos proveedores de WMI que amplíen funcionalidades.
  • Acceso desde la línea de comandos. Existe una herramienta para trabajar desde la línea de comandos con WMI (link).

Utilizándola podemos por ejemplo obtener los procesos ejecutándose si desde una ventana de MS-DOS escribimos:

1
2
3
4
WMIC PROCESS
WMIC PROCESS LIST BRIEF (mejora la visualización)
WMIC /output:”c:\procesos.txt” PROCESS LIST BRIEF 
(para obtener salida a un fichero)

Lenguaje de consulta similar a SQL llamado WQL (WMI Query Language). Utilizándolo podemos desde una ventana MS-DOS ejecutar comandos como estos:

1
2
3
4
5
WMIC PRINTER WHERE Default=”TRUE”
(obtener info sobre la impresora predeterminada)
WMIC PRINTER WHERE Default=”TRUE” LIST FULL
WMIC PRINTER WHERE default="TRUE" GET DriverName,PortName,PrintProcessor
(para obtener determinados datos de la impresora predeterminada)

Aquí se pueden ver unos cuantos ejemplos más a parte de la extensa documentación existente en las páginas de Microsoft.

Una vez hecha esta introducción (muy genérica) sobre WMI, me gustaría centrarme en las aplicaciones que pueden acceder a ella. Microsoft proporciona las API de WMI para scripts, aplicaciones Visual Basic, aplicaciones C++ y .NET Framework. Eso no quiere decir que no se pueda acceder desde casi cualquier lenguaje. En mi caso me voy a centrar en el acceso a ella desde Delphi.

Para acceder desde Delphi a WMI lo primero que necesitamos en Importar la librería desde el menú de Project/Import Type Library (pasos aquí):

“Microsoft WMI Scripting v1.X Library (Version 1.X)“

Una vez importada la librería tendremos la unit WbemScripting_TLB.pas generada y lista para utilizar. En nuestros programas deberemos incluir en la clausula USES, esta unit junto con la de ActiveX.

Antes de acabar esta entrada (espero poder publicar más, ya que el tema me parece muy interesante) podemos ver cómo utilizar la WMI para acceder a los datos del disco duro. En este caso, para simplificar vamos a acceder a los datos del primer disco (DiskDrive) existente en el sistema. Para ello se utiliza la clase: Win32_DiskDrive

http://msdn.microsoft.com/en-us/library/aa394132%28VS.85%29.aspx

Basta con crear un nuevo proyecto en Delphi, añadir un memo y un botón y colocar el siguiente código (no explico más, ya que incluye los comentarios):

Recordad de colocar en el USES las dos units comentadas antes.

Se puede descargar el código de ejemplo desde aquí y el ejecutable compilado desde aquí.

<WMI_Ejemplo1_sources>

<WMI_Ejemplo1_Binary>

Share Button