Inicio > Delphi, Ping, WMI > “Server PING” utilizando WMI…

“Server PING” utilizando WMI…

domingo, 13 de octubre de 2013 Dejar un comentario Ir a comentarios
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.

Utilizaré la clase Win32_PingStatus. Según la documentación, la llamada a la clase nos retornará los siguientes valores para un comando PING estándard.

class Win32_PingStatus
{
  string  Address;
  uint32  BufferSize = 32;
  boolean NoFragmentation = FALSE;
  uint32  PrimaryAddressResolutionStatus;
  string  ProtocolAddress = “”;
  string  ProtocolAddressResolved = “”;
  uint32  RecordRoute = 0;
  boolean ReplyInconsistency;
  uint32  ReplySize;
  boolean ResolveAddressNames = FALSE;
  uint32  ResponseTime;
  uint32  ResponseTimeToLive;
  string  RouteRecord[];
  string  RouteRecordResolved[];
  String  SourceRoute = “”;
  uint32  SourceRouteType = 0;
  uint32  StatusCode;
  uint32  Timeout = 1000;
  uint32  TimeStampRecord[];
  string  TimeStampRecordAddress[];
  string  TimeStampRecordAddressResolved[];
  uint32  TimeStampRoute = 0;
  uint32  TimeToLive = 80;
  uint32  TypeofService = 0;
};

En este caso, utilizaremos el valor de la propiedad ResponseTime (Int32) para el tiempo de respuesta y el valor de StatusCode (Int32) para conocer el valor de retorno de la función.

En la tabla siguiente se muestran los valores posibles de retorno de la función.

image

La sentencia SQL que utilizaré para la llamada será la siguiente:

SELECT * FROM Win32_PingStatus where Address= <Host> AND BufferSize=32

El código de la función PING para llamar a la clase y obtener los resultados es el siguiente:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function TForm2.Ping(const AHost:string;
       var ResponseTime:integer; var StatusCode:integer):integer;
var
  Locator:ISWbemLocator;
  Services:ISWbemServices;
  SObject:ISWbemObject;
  ObjSet:ISWbemObjectSet;
  Enum:IEnumVariant;
  TempObj:OleVariant;
  Value:Cardinal;
  TS:TStrings;
  tmp:string;
  aWSQL:string;
begin
 
  // SQL de consulta
  aWSQL := 'SELECT * FROM Win32_PingStatus where Address="' + AHost +
       '" AND BufferSize=32';
 
  try
    Locator := CoSWbemLocator.Create();
    // Conectar con el Servicio de WMI
    Services := Locator.ConnectServer(
        STR_LOCALHOST,        {ordenador local}
        STR_CIM2_ROOT,        {root}
        STR_EMPTY, STR_EMPTY, {usuario y password -en local no son necesarios-}
        STR_EMPTY,STR_EMPTY, 0, nil);
    // Acceder a los datos
    ObjSet := Services.ExecQuery(aWSQL, 'WQL',
                wbemFlagReturnImmediately and wbemFlagForwardOnly , nil);
    Enum :=  (ObjSet._NewEnum) as IEnumVariant;
    // Hemos encontrado algun objeto?
    if (Enum.Next(1, TempObj, Value) = S_OK) then begin
      SObject := IUnknown(TempObj) as ISWBemObject;
      // encontrado?
      if (SObject &lt;&gt; nil) then begin
        // Acceder a la propiedad
        SObject.Properties_;
        // Cargamos las propiedades
        TS := TStringList.Create();
        try
          //TS.Add(SObject.GetObjectText_(0));
          TS.Text := SObject.GetObjectText_(0);
          // Devolvemos los valores que nos interesan
          // Extraer los datos que necesitamos
          ParseDataResponse(TS, ResponseTime, StatusCode);
 
        finally
          FreeAndNil(TS);
        end;
      end;
    end;
  except
    // Recuperar excepciones
  end;
end;

A partir de las lecturas, el programa almacena los datos en un fichero para cada día. Además permite mostrar los resultados en un gráfico.

 

Imagen688

Una opciones básicas de configuración nos permitirán modificar el Host y el intervalo en que queremos realizar los PING.

También podemos revisar los resultados de días anteriores existentes y volcar el gráfico a un fichero gráfico en disco.

Los datos se almacenan en un fichero de texto (1 para cada día).

Podéis descargar los fuentes del proyecto y el fichero binario EXE de los siguientes enlaces:

<Código fuente del proyecto>

<EXE del proyecto>

Mejoras

El proyecto muestra lo necesario y básico para utilizar WMI.

Está claro que se podrían aplicar muchas mejoras, pero eso es algo que dejo para cada uno, si os parece apropiado. Por supuesto si alguien se anima y quiere compartirlas las publicaré en el blog si me las enviáis.

Por ejemplo, una de las primeras podría ser, la de ampliar el programa para poder utilizar varios servidores. También se podría mejorar añadiendo threads a la operación de PING. Se podrían mejorar y ampliar las opciones de configuración para hacerlo más flexible, y configurar unos avisos para detectar cuando un servidor deja de operar dentro de unos límites “aceptables”. Para mejorar el almacenamiento y exportación de datos, podríamos utilizar una Base de Datos (embebded) en lugar de los ficheros de texto, cosa que nos permitiría sacar más partido a los datos almacenados.

Como veis las posibilidades son muchas. Ya sabéis si alguien se anima, espero que comparta las mejoras con nosotros.

Acabo con un pequeño vídeo del programa en funcionamiento.

 NOTA: He resubido los proyectos de nuevo (código y binario), porque había un pequeño error a la hora de recuperar los datos esperados.

Un saludo y hasta la próxima.

Share Button
Categories: Delphi, Ping, WMI Tags: , ,
  1. Domingo
    domingo, 13 de octubre de 2013 a las 20:09 | #1

    Muy interesante. Y funciona de maravilla.

    Saludos

  1. Sin trackbacks aún.
What is 24 + 27 ?
Please leave these two fields as-is:
IMPORTANTE! Para continuar, debes contestar la pregunta anterior (para evitar SPAM) :-)