“Server PING” utilizando WMI…
Ya 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.
Podemos 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.
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 <> 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.
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:
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.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Muy interesante. Y funciona de maravilla.
Saludos
Excelente ejemplo.
Muy funcional.
Funcionaria igual para Win64?
@Antonio
Gracias Antonio.
Es un ejemplo muy antiguo y bastante básico para probar el funcionamiento de WMI. Como tienes el código disponible puedes modificarlo a tu gusto.
Lo bueno de WMI es que funciona en todos los sistemas operativos de Windows (que tengan el servicio en marcha) ya sean de 32 o de 64. Basta con que compiles el proyecto en la arquirectura que desees.
Un saludo.
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