No puedo obtener estadística de subida y bajada de red en XP

Iniciado por Lekim, 15 Septiembre 2015, 19:32 PM

0 Miembros y 1 Visitante están viendo este tema.

Lekim

Hola,

Con VB.Net 2010 y utilizando System.Net.NetworkInformation obtengo el valor de datos de subida y bajada de mi conexión.

El caso es que me funciona en Vista y Windows7  pero no en XP.

Esta es la función que he utilizado:

Código (vbnet) [Seleccionar]

Public Class InformationNetWork
Dim Estado As String
Dim DatosRecibidos As String
Dim DatosEnviados As String

   Public Function EnumerateNetwok()
       Dim properties As System.Net.NetworkInformation.IPGlobalProperties = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties()
       Dim ipstat As System.Net.NetworkInformation.IPGlobalStatistics = properties.GetIPv4GlobalStatistics()


       '//Estado de red
       Dim ipv4Stats As System.Net.NetworkInformation.IPv4InterfaceStatistics
       ipv4Stats = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(0).GetIPv4Statistics


       DatosRecibidos = ipv4Stats.BytesReceived.ToString
       DatosEnviados = ipv4Stats.BytesSent.ToString


       '//Estado Conexión

       Dim ipv4Time As System.Net.NetworkInformation.IPGlobalProperties = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties()
       Try
           Dim n = ipv4Time.GetActiveTcpConnections().Cast(Of System.Net.NetworkInformation.TcpConnectionInformation).First(Function(el) el.State)
           Estado = n.State
       Catch ex As Exception
           Estado = "Desconectado"
       End Try
       Return 0
   End Function



   Public Property DatesRecibidos As String
       Get
           Return DatosRecibidos
       End Get
       Set(ByVal value As String)
       End Set
   End Property
   Public Property DatesEnviados As String
       Get
           Return DatosEnviados
       End Get
       Set(ByVal value As String)
       End Set
   End Property
End Class


Y para llamarlo hago lo siguiente:

Código (vbnet) [Seleccionar]
   
Public Class Form1
Dim Subida As Decimal
   Dim Bajada As Decimal
   Dim OldSubida As Decimal
   Dim OldBajada As Decimal
   Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
       Dim InfoNet As New InformationNetWork
       InfoNet.EnumerateNetwok()


       Label4.Text = FormatNumber(((InfoNet.DatesEnviados / 1024 / 1024)), 2) & " MB"
       Label5.Text = FormatNumber(((InfoNet.DatesRecibidos / 1024 / 1024)), 2) & " MB"
       If OldSubida <> Convert.ToDecimal(FormatNumber(((InfoNet.DatesEnviados / 1024 / 1024)), 2)) Then
           Label6.Text = Convert.ToDecimal(FormatNumber(((InfoNet.DatesEnviados / 1024 / 1024)), 2)) + OldSubida & " MB"
           Label7.Text = Convert.ToDecimal(FormatNumber(((InfoNet.DatesRecibidos / 1024 / 1024)), 2)) + OldBajada & " MB"
           Label9.Text = (Convert.ToDecimal(FormatNumber(((InfoNet.DatesEnviados / 1024 / 1024)), 2)) + OldSubida) + _
               (Convert.ToDecimal(FormatNumber(((InfoNet.DatesRecibidos / 1024 / 1024)), 2)) + OldBajada) & " MB"

           Subida = Convert.ToDecimal(FormatNumber(((InfoNet.DatesEnviados / 1024 / 1024)), 2)) + OldSubida
           Bajada = Convert.ToDecimal(FormatNumber(((InfoNet.DatesRecibidos / 1024 / 1024)), 2)) + OldBajada
       End If
   End Sub

End Class

dato000

Tal vez en XP no este compilado para la versión de .NET que usa el sistema operativo.




Eleкtro

#2
1.
El motivo de que en un equipo te funcione y en otro no, probablemente se deba a que en esta orden asumes que la primera interfáz de todas que se encuentre (0) es la que se debe monitorizar, y eso no siempre tiene por que ser así, ya que otros equipos tendrán varias interfaces o simplemente la primera interfáz encontrada no será la que realmente quieras monitorizar.

Código (vbnet,3) [Seleccionar]
'//Estado de red
Dim ipv4Stats As IPv4InterfaceStatistics
ipv4Stats = NetworkInterface.GetAllNetworkInterfaces(0).GetIPv4Statistics


Debes comprobar con evaluaciones qué interfáz es la que realmente quieres monitorizar, empezando por filtrar los adaptadores de Internet y verificar cuales de ellos están activos:
Código (vbnet) [Seleccionar]
If NetworkInterface.GetIsNetworkAvailable() Then

   Dim interfaces As NetworkInterface() = NetworkInterface.GetAllNetworkInterfaces()

   For Each ni As NetworkInterface In interfaces

       If ni.OperationalStatus = OperationalStatus.Up Then

           If (ni.NetworkInterfaceType <> NetworkInterfaceType.Tunnel) AndAlso
              (ni.NetworkInterfaceType <> NetworkInterfaceType.Loopback) Then

               Dim statistics As IPv4InterfaceStatistics = ni.GetIPv4Statistics()

               If (statistics.BytesReceived > 0) AndAlso (statistics.BytesSent > 0) Then
                   ' En ste punto tenemos una interfáz de red (Internet) activa...
                   ' ...una de varias que pueden haber conectadas y activas al PC.
               End If

           End If

       End If

   Next ni

End If

(Si tienes adaptadores "virtuales" de Ethernet cómo por ejemplo TAP-Win podría ser un problema con el código que he mostrado, debes omitir esas interfaces claro está)




2.
La estructuración en general de la Class InformationNetwork es incorrecta, el dato más importante a tener en cuenta es que defines una función EnumerateNetwok sin un valor de retorno asignado, por ende no es una función como tal, y, no se con que intención, devuelves un 0 que no utilizarás en ninguna evaluación posterior.

Por mencionar algo más, esta evaluación es inecesaria (¿con que intención checkeas una conexión TCP establecida?, de esa manera no se verifica si el adaptador está activo, solo si "X" conexión TCP lo está), el casteo es innecesario, el método lambda también, y no especificas el type de la variable declarada:
Citar
Código (vbnet) [Seleccionar]
Dim n = ipv4Time.GetActiveTcpConnections().Cast(Of System.Net.NetworkInformation.TcpConnectionInformation).First(Function(el) el.State)

Código (vbnet) [Seleccionar]
Dim state As TcpState = ipv4Time.GetActiveTcpConnections.First.State

En general debes limpiar todo el código de esa y la otra class, añade las declaraciones Option apropiadas y posteriormente corrige todos los errores de compilación que te vas a encontrar debido a los malos hábitos de programación que has aplicado en ambas classes.

Código (vbnet) [Seleccionar]
Option Explicit On
Option Strict On
Option Infer Off

Class
...
End Class





En resumen, simplemente debes asgurarte de que interfáz quieres monitorizar, y complementariamente sigue también las indicaciones del punto 2. para producir un código limpio y evitar malos hábitos que te causarán otros problemas.

Saludos








Eleкtro

#3
Una alternativa que puedes utilizar serían los contadores de rendimiento.

He desarrollado la siguiente Class que permite monitorizar el tráfico de una interfáz de red, o incluso el tráfico de un proceso, quiero decir del proceso actual o de un ensamblado .Net externo (en ambos casos para monitorizar el tráfico de un proceso primero es necesario habilitar los contadores de rendimiento en el archivo de configuración de la aplicación, "app.config"), con características básicas para controlar el intervalo de actualización y demás, y con algoritmos simples para medir la velocidad de descarga y subida (los he escrito en un par de horas, dan buenos resultados si se asigna un intervalo de actualización de 1 segundo, son muy mejorables pero por el momento lo he dejado así).




Son dos classes distintas, NetworkTrafficMonitor y ProcessTrafficMonitor, en esta demostración hago uso del monitor del tráfico del proceso actual:






Un ejemplo del modo de empleo, el mismo que he utilizado para la app de la imagen GIF:
Código (vbnet) [Seleccionar]
Imports NetworkUtil
Imports NetworkUtil.NetworkTrafficMonitor

Public NotInheritable Class Form1 : Inherits Form

   Dim WithEvents procNetMon As NetworkUtil.ProcessTrafficMonitor

   Private Sub Form1_Load() Handles MyBase.Load

       Me.procNetMon = New ProcessTrafficMonitor(Process.GetCurrentProcess.Id)
       Me.procNetMon.UpdateBehavior = UpdateBehaviorEnum.FireAlwaysAfterTick
       Me.procNetMon.UpdateInterval = 1000 ' 1 sec.
       Me.procNetMon.Start()

   End Sub

   Private Sub ProcNetMon_TrafficChanged(ByVal sender As Object, ByVal e As ProcessTrafficMonitor.TrafficChangedEventArgs) _
   Handles procNetMon.TrafficChanged

       Me.LabelBytesReceived.Text = String.Format("Bytes received: {0} kb", (e.BytesReceived / 1024).ToString("n2"))
       Me.LabelDlSpeed.Text = String.Format("DL Speed: {0} kb/sec", (e.DiffBytesReceived / 1024).ToString("n2"))

       Me.LabelBytesSent.Text = String.Format("Bytes sent: {0} kb", (e.BytesSent / 1024).ToString("n2"))
       Me.LabelUlSpeed.Text = String.Format("UL Speed: {0} kb/sec", (e.DiffBytesSent / 1024).ToString("n2"))

   End Sub

   Private Sub BtDownloadUrl_Click() Handles BtDownloadUrl.Click

       Dim url As String = "http://download.thinkbroadband.com/10MB.zip"
       Dim client As New WebClient()
       client.DownloadFileAsync(New Uri(url), Path.GetTempFileName())

   End Sub

   Private Sub BtPauseMon_Click() Handles BtPauseMon.Click

       If Me.procNetMon.IsActive Then
           Me.procNetMon.Stop()
       Else
           Me.procNetMon.Start()
       End If

   End Sub

End Class


La Class NetworkTrafficMonitor, que es en lo que podrías estar interesado, se maneja exactamente de la misma manera, ya que ProcessTrafficMonitor la heredo de esta;
La única diferencia es el constructor, que toma cómo argumento el nombre de una interfáz de red activa.

Ejemplo:
Código (vbnet) [Seleccionar]
Dim WithEvents netMon As New NetworkTrafficMonitor(NetworkTrafficMonitor.GetAvaliableInterfaceNames.First)




El código fuente lo puedes descargar aquí, simplemente copiar pegar y utilizar:

Network/Process Traffic Monitor in VBNet, By Elektro - PasteBin

PD: Si usas la class, te sugiero separar las subclasses que hay definidas en varios archivos.




Diagrama de classes:



   

 






Espero que les sirva de algo a ti y a los que estén interesados :)

Saludos