Todo lo que quise saber de mi disco y no me atreví a preguntarlo

Tal como os tengo acostumbrados, con el trasfondo de preguntas que se repiten y repiten, os facilito un ejemplo de cómo rastrear toda la información de nuestro disco “lógico” utilizando el conocido “System.Management” del ‘Framework 2.0’.

En el siguiente ejemplo rellenamos un “DomainUpDown” con los nombres de las características de nuestro disco, a continuación rellenamos un ‘label’ con la descripción de la característica cada vez que el “DUD” cambia de indice… sencillo, verdad? Utilizando este método podremos acceder a las propiedades disponibles sin tener que buscar sus nombres de antemano. A pesar de que os anticipo que a menudo muchos de nosotros intentamos obtener información o características que no están disponibles para ese “disco” o bien no existen!.  No olvidéis que la información es la de WIN32_DiskDrive.

MisDiscos

Para los mas profundos en búsqueda de información mas “Fisica” podeis cambiar la “query” por la de Win32_PhysicalMedia.

Private MisDiscos As New ManagementObjectSearcher(«SELECT * FROM Win32_PhysicalMedia»)

Espero vuestras conversaciones J
Cuidaros,
Pep Lluis,

Imports System.Management

 

Public Class Form1

   

    ‘Obtener toda la informacion de mis discos (Logicos)

    Private MisDiscos As New ManagementObjectSearcher(«SELECT * FROM Win32_DiskDrive»)

    ‘Almacen del valor de las caracteristicas segun propiedad

    Private DiscInfo As New ManagementObject

 

    Private Sub Form1_Load(…..) Handles MyBase.Load

        Dim MiInfo = From Hd As ManagementObject In MisDiscos.Get Select Hd

        ‘Seleccionar la info del disco(0)

        ‘O bien proporcionar un combo para su seleccion
        DiscInfo = MiInfo(0)

        ‘Obtener el nombre de la propiedad

        ‘Rellenar el DUD con los nombres

        Me.DomainUpDown1.Items.AddRange( _

           ( _

              From Pn As Management.PropertyData _

              In DiscInfo.Properties _

              Select Pn.Name _

            ).ToArray)

        ‘Por defecto seleccionar el primer indice

        Me.DomainUpDown1.SelectedIndex = 1

    End Sub

   

    ‘ Al cambiar el indice del item seleccionado…

   

    Private Sub DomainUpDown1_SelectedItemChanged() _
         
Handles DomainUpDown1.SelectedItemChanged

        Try

            ‘obtener la descripcion de la propiedad

            Descripcion.Text = DiscInfo.Properties(Me.DomainUpDown1.Text).Value

        Catch ex As Exception

            ‘en caso de error…

            Descripcion.Text = «¿?»

        End Try

    End Sub

End Class

In English o en Spanish

Fruto de una pregunta de Jesus, sobre la conveniencia de usar el entorno en una u otro lengua, os dejo un par de argumentos para animaros a seguir la conversación.

Empecé a programar en «Assembler» hace mas de 30 años sin tener conocimiento alguno de Ingles y para aquellos entonces no existía ninguna posibilidad de obtener información alguna en otro lenguaje distinto al “Americano” , respecto a los compiladores o cualquier tema relacionado con la programación. La mayoría de nosotros aprendíamos con el diccionario al lado del teclado… Ni te cuento!

Creo que la mejor idea es decidir en función a tu ámbito de trabajo, no cabe la menor duda que si tu carrera profesional se desarrollara en un entorno de negocio donde se utiliza el Español y el equipo interactúa en Español la mejor decisión es utilizar el Visual Studio en Español, programando el código en “Español” con comentarios, nomenclaturas, definiciones etc. Es increíble gozar del excelente trabajo realizado por MS para proveer a los desarrolladores de una adaptación perfecta a un gran número de idiomas y vale la pena aprovechar todo ese potencial. Utilizar Visual Studio no es una simple decisión de mandatos de Lenguaje y menús… no olvides que toda documentación, ayuda y enlaces es fundamental tenerla en la lengua que hablamos, para de esa forma disponer de un rápido entendimiento y compresión sin dejar dudas en la interpretación Inglés/Español/Frances/Aleman… date cuenta que detrás de cada lenguaje un numeroso equipo de personas que no solo traducen texto, si no que adaptan e interpretan el conocimiento para cada uno de los idiomas/culturas.

Si por el contrario tu futuro se fija en el entorno anglosajón y tu negocio interactuara con equipos o desarrolladores de otros países, entonces no cabe duda que la mejor opción sea tomar el esfuerzo de pensar en “Ingles” y realizar tus desarrollos como si vivieras en un país de lengua Inglesa, incluyendo entorno, documentación…etc.

Para sacar el mayor provecho a nuestra capacidad, es fundamental desenvolvernos en el lenguaje en el que tenemos nuestros pensamientos… de esa forma evitamos tener que andar “traduciendo” ganando consecuentemente tiempo y concentración.

Saludos a todos,
Pep Lluis,

Actualizar una Tabla de una BD SQL utilizando un DataGridView

A menudo en los foros aparece la pregunta de cómo actualizar una BD utilizando un DataGridView. Aquí os dejo una forma de realizarlo. Espero que os sea útil.

Saludos,
Pep Lluis,


‘Definir enlace a datos y objetos del form

Private MiConexion As New SqlConnection( _

   «Datasource=.\SQLEXPRESS;AttachDbFilename=C:\Temp\NORTHWND.MDF» + _
   «;Integrated Security=True;Connect Timeout=30;User Instance=True»)
Private MiAdaptador As New SqlDataAdapter(«SELECT * FROM Shippers», MiConexion)
Private MiDataSet As New DataSet()

Private MiEnlazador As New BindingSource

 

Private MidataGriView As New DataGridView

Private BotonGuardar As New Button

‘En tiempo de carga…
Private Sub Form1_Load(…..) Handles MyBase.Load
    MessageBox.Show(My.Computer.FileSystem.CurrentDirectory)

    ‘Poner titulo a la aplicacion

    Me.Text = «Mantenimiento de Shippers»

    ‘Añadir DataGriView

    MidataGriView.Dock = DockStyle.Top

    Me.Controls.Add(MidataGriView)

    BotonGuardar.Dock = DockStyle.Bottom

    ‘Añadir Boton de Guardar

    BotonGuardar.Text = «Guardar Cambios»

    Me.Controls.Add(BotonGuardar)

    AddHandler BotonGuardar.Click, AddressOf Guardar
    Dim commandbuilder As New SqlCommandBuilder(Me.MiAdaptador)

    MiConexion.Open()

    MiAdaptador.Fill(MiDataSet)

    MiEnlazador.DataSource = MiDataSet.Tables(0)

    MidataGriView.DataSource = MiEnlazador

End Sub

‘Actualizar la tabla enlazada con el DataGridView

Private Sub Guardar(…..)
    Me.MiAdaptador.Update(CType(Me.MiEnlazador.DataSource, DataTable))

End Sub

AndAlso? What Else!

Muchos de nosotros, sobre todo los históricos de VB, hemos pasado días enteros escribiendo sentencias donde abundan un buen numero de liados entramados de condicionales…

If Expresion1 And (Not Expresion2) And Expresion3 Then ….

Es normal dentro de nuestra concentración al escribir código, que pongamos nuestro foco de atención en resolver el planteamiento más que en imaginarnos lo que ocurre en el momento de su ejecución. Sin ir más lejos cuántos de nosotros nos abstraemos del algoritmo y pensamos en las miles o millones de veces que llegara a ejecutarse la evaluación de dichas expresiones. Y cuántos de nosotros  a pesar de ejecutarse en un procesador capaz de recorrer  millones de Instrucciones por segundo, intentamos abstraernos en un pensamiento “ecologista” en tanto a no malbaratar la circulación inútil de ‘bitios’. La respuesta es “Algunos de nosotros SI pensamos en todo esto” y como no, VB también!

Ahora toca preguntarnos ¿y esto que viene a contarnos?… la respuesta seria pues AndAlso, what else!

Cuando detrás de un condicional ‘If’ agrupamos varias expresiones enlazadas con operadores, a saber ‘Or’… ‘And’, debemos tener muy en cuenta que el resultado será fruto de la evaluación de todos ellos con el consecuente consumo de procesador.

Expresión 1

AND Expresión 2

Resultado

Verdadero

Verdadero

Verdadero

Verdadero

Falso

Falso

Falso

Verdadero

Falso

Falso

Falso

Falso

 

Pero para que tanto ruido?
Intentando buscar justificaciones, escribiendo un poquito más tendremos a nuestra disposición ‘AndAlso’

Expresión 1

ANDALSO Expresión 2

Resultado

Verdadero

Verdadero

Verdadero

Verdadero

Falso

Falso

Falso

No se Evalúa

Falso

 

Aun así seguro que mas de uno ponéis cara de extrañados, bien el matiz se encuentra en que “No se Evalúa” significa que “No se procesa” por lo que si encadenamos varias evaluaciones de expresiones con ‘and’, usando ‘andalso’ ahorraremos en consumo de proceso, por lo que solo continuara evaluando las expresiones si la precedente es ‘Verdadera’ y finalizara la evaluación del resto de expresiones al obtener el primer ‘falso’.

Sin duda simpáticas historias.
Pep Lluis,

Por Cierto os he hablado de ‘OrElse’… vaya! pues tambien existe!

Expresión 1

Expresión 2

Resultado

Verdadero

No se evalúa

Verdadero

Falso

Verdadero

Verdadero

Falso

Falso

Falso

Lo de WhatElse vamos a dejarlo para otro dia jajajajaja.

Como puedo posicionar el ‘CurrentCell’ de mi DataGridView

Que nadie se lo tome a mal! Pero después de reírnos un rato, nos encontramos a menudo perdiendo la tarde en búsqueda de cómo realizar las cosas más sencillas. Intentando dar respuesta a la repetida pregunta de cómo posicionarnos dentro de nuestro DataGridView… Ahí va la respuesta:

Dim Columna As Integer = 0, Fila As Integer = 0
Me.DataGridView1.CurrentCell = _
   Me.DataGridView1(Columna, Fila)

La de tumbos que a veces damos, porque creo que difícil no es! J
Saludos,
Pep Lluis,

Enumerar los puertos COM en un ‘combo’ listos para ser seleccionados.

En algunas ocasiones he leído alguna respuesta en los foros contestando la forma en que podemos enumerar nuestros puertos “COM” y dejarlos listos para ser seleccionados por el usuario… sin entrar en valorar complejas respuestas con ‘For Each’ ‘Add’ y etc, os dejo un código ejemplo de cómo… pero en una sola línea!!

Me.ComboBox1.Items.AddRange(My.Computer.Ports.SerialPortNames.ToArray)

… luego en ‘ComboBox1.SelectedIndexChanged’
PuertoSerie.Close()
PuertoSerie.PortName = ComboBox1.SelectedItem
PuertoSerie.Open()

Saludos,
Pep Lluis,

Una simple cuestión de hilos.

A cuerda de una pregunta en el foro (para principiantes),  donde se cuestiona porque el ‘timer’ deja de funcionar y no refresca el paso de los segundos cuando efectuamos una llamada a un procedimiento… vamos a exponer el siguiente argumento para intentar esclarecerlo.

Nuestro ‘Form’ se está rondando en su hilo de ejecución… por lo que cuando efectúas la llamada para «procesar la rutina», el ‘timer’ deja de refrescarse por falta de turno de ejecución al estar (nuestro hilo) ocupado en espera de recibir el retorno de la llamada a tal procedimiento.

Para no bloquear nuestro hilo de ejecución y poder continuar con otras tareas, deberemos llamar a ese proceso creando un nuevo hilo de ejecución, utilizando ‘Threading.Thread’ … aquí dejo un ejemplo donde muestra las dos situaciones de una forma muy básica.

En situación de ejecución, nuestro ‘form’ visualiza la fecha y hora actual en la barra de titulo. Al pulsar sobre el botón 1 se lanza la llamada al procedimiento ‘readline’ en espera de leer una línea recibida por el puerto serie, todo el ‘form’ quedara congelado hasta recibir esa línea, que de buena tinta sabemos que nunca llegara J  por lo tanto la barra de titulo quedara inanimada, pues el hilo está ocupado y el ‘timer1’ no dispone de turno de ejecución para dispar los eventos ‘tick’.

Sin embargo al hacer clic sobre el segundo botón, este crea un nuevo hilo de ejecución que apunta al mismo procedimiento pero con una nueva asignacion de ejecucion, haciendo autónomo su proceso en la llamada al procedimiento, así pues en este caso la barra de titulo reflejara en todo momento la fecha y hora, con independencia de si el procedimiento a finalizado o no, pues el hilo principal del ‘form’ continuara atendiendo y repartiendo la ejecución entre todos los objetos que tiene a su cargo… inclusive el nuevo hilo.

Para rodar este ejemplo, solo tienes que crear un nuevo proyecto ‘winform’ añadir un ‘timer’ y dos ‘Button’.

Espero que os sea útil y pido ‘sorrys’ por el rollo!
Pep Lluis,

Public Class Form1
    Private Puerto As New System.IO.Ports.SerialPort

    Private Sub Form1_Load(…..) Handles MyBase.Load
        Me.Timer1.Interval = 1000
        Me.Timer1.Enabled = True
        Me.Button1.Text = «Llamar Procedimiento»
        Me.Button2.Text = «Ejecutar nuevo Hilo»
        Puerto = My.Computer.Ports.OpenSerialPort(«COM1»)
    End Sub


    Private Sub Timer1_Tick(…..) Handles Timer1.Tick
        Me.Text = Date.Now
    End Sub

    Private Sub Button1_Click(…..) Handles Button1.Click
        Me.Button1.Enabled = False
        Me.Text = «*Ejecucion sin crear Hilo «
        Procedimiento()
        Me.Button1.Enabled = True
    End Sub

    Private Sub Button2_Click(…..) Handles Button2.Click
        Me.Button2.Enabled = False
        Me.Text = «*Ejecutar creando un nuevo Hilo»
        Dim MiHilo As New Threading.Thread(AddressOf Procedimiento)
        MiHilo.Start()
        ‘el timer continua con su ejecucion…        
        ‘Antes de lanzar una nueva llamada
        ‘deberiamos cancelar el hilo en espera
        ‘ejecutando : MiHilo.Abort() o controlando
        ‘su estado o control por ejemplo con :
        MiHilo.IsAlive
        MiHilo.Suspend()
        MiHilo.Sleep()
    End Sub

    Private Sub Procedimiento()
       
        ‘Esta funcion esta efectuando una llamada
        ‘a un procedimento que no finalizara hasta
        ‘completarse o exceder su tiempo de espera.
        Dim datos = Puerto.ReadLine
    End Sub
End
Class

FCS Frame Check Secuence – CRC Cyclic Redundancy Check algorithm

En la mayoría de antiguos protocolos de comunicaciones “sobre todo Serie”, disponemos de algunos mecanismos para la detección y corrección de errores en el intercambio de tramas. En concreto hablando del puerto serie, a primer nivel disponemos del control de paridad con el que conseguimos descartar algunos de los errores de transmisión a nivel de byte, sin embargo muchos protocolos implementan un control a nivel de trama, en el que se realiza una suma de verificación de todos los bytes transmitidos. Esto es conocido como FCS o CRC que no deja de ser una referencia a un ‘checksum’ o verificación redundante. El resultado de la misma es añadido al final de la trama y enviado con el resto de datos. Una vez recibido por el terminal o dispositivo se efectuara la misma operación calculando de nuevo la FCS y comprobando que coincide con la transmitida… con ello conseguiremos tener un elevado porcentaje de confianza en tanto la integridad de los datos recibidos.

El cálculo puede presentarse más o menos complejo dependiendo de la implementación de esta verificación según el protocolo, aunque la mayoría de ellos se conforman con aplicar un simple ‘XOR’… veamos un ejemplo común:

   
    ‘ Calculo de la FCS de una trama
    ‘ Esta funcion devolvera el valor hexadecimal
    ‘ en forma de dos caracters ASCII

    Private Function Fcs(ByVal Trama As String) As String
        Dim MiFcs As Integer = 0
        For Each c In Trama
            MiFcs = Asc(c) Xor MiFcs
        Next
        Return Hex(MiFcs).ToString
    End Function

Para los amantes de bool… Recordemos la tabla para el ‘Or’ Exclusivo : MiFcs = Asc(c) Xor MiFcs

p

q

p ≠ q

Falso

Falso

Falso

Falso

Verdadero

Verdadero

Verdadero

Falso

Verdadero

Verdadero

Verdadero

Falso

Entonces solo nos faltara alinear los valores binarios del resultado anterior; efectuar el ‘Xor’ y continuar efectuando la misma operación hasta agotar el ultimo byte. Demostrar el tema de acarreos y resultados con 16/32 bits en hexadecimal lo dejamos para otro dia J o bién podeis continuar leyendo en : http://www.ietf.org/rfc/rfc2615.txt?number=2615 Por ahora me conformo pensando que :  Hex(MiFcs).ToString, soluciona mi problema. 

Resultado_Anterior

0

1

0

1

0

1

0

1

Byte_Actual

0

0

1

1

1

0

0

1

Resultado_Actual

0

1

1

0

1

1

0

0

Ya no os podéis quejar que con el avance de los lenguajes nos alejamos de los ‘Bites’.

Saludos,
Pep Lluis,

PD. EN VB6 Tenia este aspecto

‘ ** Calculo de la Fcs

‘ Al mas puro VB6

Private Function Fcs$(Var)

Dim p As Integer, q As Integer

 For p = 1 To Len(Var)

   q = q Xor Asc(Mid$(Var, p, 1))

 Next p

Fcs$ = Right$(«0» + Hex$(q), 2)

End Function

 

Dar Grant Access a un usuario de SQL 2005 Express

Algunas de las preguntas relacionadas con SQL Express y los errores generados al intentar abrir una conexión en una implementación diferente de la máquina de desarrollo, son debidas a que el usuario no dispone del suficiente ‘Grant Access’ J

Desde el símbolo de sistema (Ejecutando como Administrador) y entendiendo que no dispones del  ‘Management Studio’ :

Cmd Grant Access

Salud!