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:

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.

Vota este post
Categories: Delphi, Ping, WMI Tags: , ,
Subscribe
Notify of
guest

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

4 Comments
Inline Feedbacks
Ver todos los comentarios
Domingo
Domingo
10 years ago

Muy interesante. Y funciona de maravilla.

Saludos

Antonio
Antonio
5 years ago

Excelente ejemplo.

Muy funcional.

Funcionaria igual para Win64?

Alejandro G
Alejandro G
10 months ago

Muy buen ejemplo para lo que no los conocen poder parender a usar WMI para monitoreo.

Mi consulta ahora es, que conviene mas para monitorear un servidor, WMI o ir directamente por el ping. Ya se que en algunos casos no tenemos permisos y no está corriedo el servicio de WMI, pero en los casos de que se pueda con los dos cual aconsejas.

Saludos

4
0
Would love your thoughts, please comment.x
()
x