Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: Meta en 6 Abril 2021, 19:33 pm



Título: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 6 Abril 2021, 19:33 pm
Hola:

Quiero añadir unidades detectadas de si hay lectores en un PC o ordenador.

Cada vez que me detecta dos lectores en el comboBox me lo rellena así:

F
:
G
:

Como cuatros elementos cuando en realidad son dos y debe mostrarlos así:
F:
G:

Me da igual si solo también se queda como abajo.
F
G

¿Hay alguna forma de corregir estas cosas?

Saludos.


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: K-YreX en 6 Abril 2021, 23:23 pm
Sin tener más datos sobre cómo lo has implementado, la solución más genérica que se me ocurre es comparar si el valor es igual a ":" antes de agregarlo al combobox y en caso afirmativo, ignorar ese elemento.

Viendo el código de esa parte del programa igual se puede obtener una solución más "limpia" por decirlo de alguna manera.


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 6 Abril 2021, 23:44 pm
Lo intenté hacer con remove al comoBox, se borra, pero cuando encuentra otra unidad sigue el problema.

Código
  1. private void Form1_Load(object sender, EventArgs e)
  2.  
  3. {
  4.    // Nombre de la unidad.
  5.    ConsigueComponentes("Win32_CDROMDrive", "Id");
  6.  
  7.    foreach (char item in datos)
  8.    {
  9.        comboBox_Unidad.Items.Add(item);
  10.    }
  11.  
  12.    // Selecciona la primera unidad.
  13.    comboBox_Unidad.SelectedIndex = 0;
  14.  
  15.    // Limpiar.
  16.    datos = "";
  17.  
  18. }


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: K-YreX en 7 Abril 2021, 07:29 am
Claro, si digamos que en <datos> tienes algo como:
Código:
C:D:F:
Y vas recorriendo y agregando carácter a carácter pues agregarás:
Código:
C
:
D
:
F
:

Otra solución:
Código
  1. string[] unidades = datos.Split(':');
  2. foreach(string unidad in unidades)
  3.  combobox.Items.Add(unidad);
Resultado:
Código:
C
D
F
G
El delimitador (':') no se incluye en las subcadenas. Para incluirlo puedes hacerlo manualmente:
Código
  1. combobox.Items.Add(unidad + ":");
O mediante un for() y el método Substring() o similares para recoger dos caracteres en vez de uno.


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 7 Abril 2021, 11:01 am
No se que pasa.
En vez de verse:

F:
G:

En el comboBox, aparece esto.

(https://social.msdn.microsoft.com/Forums/getfile/1660120)
Ver imagen (https://social.msdn.microsoft.com/Forums/getfile/1660120).

En este otro código de abajo, solo se me ve así:
G:
:

¿Dónde está la F:?  ;D

Código
  1.        void UnidadDisco()
  2.        {
  3.            // Nombre de la unidad.
  4.            ConsigueComponentes("Win32_CDROMDrive", "Id");
  5.  
  6.            // Delimitador.
  7.            string[] unidades = datos.Split(':');
  8.  
  9.            foreach (string unidad in unidades)
  10.            {
  11.                comboBox_Unidad.Items.Add(unidad + ":");
  12.            }
  13.  
  14.            // Selecciona la primera unidad.
  15.            comboBox_Unidad.SelectedIndex = 0;
  16.        }

Saludos.


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Serapis en 7 Abril 2021, 18:16 pm
Es aún más sencillo, en NET muchas colecciones admiten la adicion de un array directamente con 'AddRange', lo que nos evita la necesidad de usar un bucle...

Código
  1. private void button1_Click(object sender, EventArgs e)
  2.        {        
  3.            string[] uds= "C:D:F:G:".Split(':');
  4.            comboBox1.Items.AddRange(uds);
  5.  
  6.            //comboBox1.Items.AddRange(unidades.Split(':'));  //el Split se puede hacer en una sola linea.
  7.        }
  8.  

Si además quieres que aparezcan los dos puntos, es preferible modificar el string de entrada, remplazando los dos puntos por los puntos y un espacio (y entonces hacer el Split por el espacio).


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 7 Abril 2021, 19:17 pm
La idea es que me detecte las unidades de disco que tengo instalada o detectada. ;)


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: K-YreX en 7 Abril 2021, 19:19 pm
No se que pasa.
En vez de verse:

F:
G:

En el comboBox, aparece esto.

(https://social.msdn.microsoft.com/Forums/getfile/1660120)
Ver imagen (https://social.msdn.microsoft.com/Forums/getfile/1660120).

En este otro código de abajo, solo se me ve así:
G:
:

¿Dónde está la F:?  ;D

Código
  1.        void UnidadDisco()
  2.        {
  3.            // Nombre de la unidad.
  4.            ConsigueComponentes("Win32_CDROMDrive", "Id");
  5.  
  6.            // Delimitador.
  7.            string[] unidades = datos.Split(':');
  8.  
  9.            foreach (string unidad in unidades)
  10.            {
  11.                comboBox_Unidad.Items.Add(unidad + ":");
  12.            }
  13.  
  14.            // Selecciona la primera unidad.
  15.            comboBox_Unidad.SelectedIndex = 0;
  16.        }

Saludos.
Por un lado, no se puede ver la imagen. Ni en el cuadro de imagen ni mediante el enlace de "Ver imagen".
Y por otro lado, si no se muestra correctamente la F tiene que ser porque en la variable <datos> no está bien guardado.
Si el resultado ha sido:
Código:
G:
:
tiene que ser porque en <datos> estaba almacenado la siguiente cadena: "G::".

Prueba a imprimir el contenido de <datos> para comprobarlo.


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Serapis en 7 Abril 2021, 20:47 pm
La idea es que me detecte las unidades de disco que tengo instalada o detectada. ;)
Usa GetDevices... quizás tengas que añadir una referencia al ensamblado.


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 7 Abril 2021, 22:56 pm
Si lo hago así:
Código
  1.        void UnidadDisco()
  2.        {
  3.            // Nombre de la unidad.
  4.            ConsigueComponentes("Win32_CDROMDrive", "Id");
  5.  
  6.            // Delimitador.
  7.            string[] unidad = datos.Split(' ');
  8.            comboBox_Unidad.Items.AddRange(unidad);
  9.  
  10.            //comboBox_Unidad.Items.AddRange(unidades.Split(':'));  //el Split se puede hacer en una sola linea.
  11.  
  12.            // Selecciona la primera unidad.
  13.            comboBox_Unidad.SelectedIndex = 0;
  14.        }

Me di cuenta que en dato primero pone F:
Luego hace otra pasada en el código de abajo.
Código
  1.        void ConsigueComponentes(string hwclass, string syntax)
  2.        {
  3.            ManagementObjectSearcher mos = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hwclass);
  4.            foreach (ManagementObject mj in mos.Get())
  5.            {
  6.                if (Convert.ToString(mj[syntax]) != "")
  7.                {
  8.                    datos = Convert.ToString(mj[syntax]);
  9.                }
  10.            }
  11.        }

Y se pone en G: borrando la F:


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: K-YreX en 7 Abril 2021, 23:52 pm
Claro, entonces el problema estaba en que no se estaba guardando en <datos> todas las unidades sino que se van sobreescribiendo en cada iteración. Entonces tienes que concatenar todo y preferiblemente como dice Serapis añadiendo un espacio entre cada unidad para separarlos mediante el espacio y mantener los dos puntos...
Código
  1. datos += mj[syntax].ToString() + " ";
  2. ...
  3. string[] unidades = datos.Split(' ');


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 8 Abril 2021, 01:29 am
Funciona mejor, casi perfecto.  ;-) ;-) ;-) ;-) ;-) ;-)

Ahora pone:
G:
F:
Espacio enblanco

No se que pinta en el último elemento un espacio en blanco, queda feo.

Solo hace falta corregir ese último detalle.

Lo demás, perfecto.

 :silbar: :silbar: :silbar: :silbar: :silbar:


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: [D]aniel en 8 Abril 2021, 02:29 am
Hola, si aparece una línea vacía al final del combobox debe ser porque hay un salto de línea al final del string, algo como:

C:D:E:F:\n

o también puede ser porque el Split no está operando como debería o puede que el código esté detectando una unidad que no existe.


Saludos


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 8 Abril 2021, 11:40 am
Buenas gente:

Desde que llegue en el depurador hasta aquí indicado.

Código
  1.        void UnidadDisco()
  2.        {
  3.            // Nombre de la unidad.
  4.            ConsigueComponentes("Win32_CDROMDrive", "Id");
  5.  
  6.            // Delimitador.
  7.            string[] unidad = datos.Split(' ');
  8.            comboBox_Unidad.Items.AddRange(unidad);
  9.  
  10.  
  11.            //comboBox_Unidad.Items.AddRange(unidades.Split(':'));  //el Split se puede hacer en una sola linea.
  12.  
  13.            // Selecciona la primera unidad.
  14.            comboBox_Unidad.SelectedIndex = 0;
  15.        }

Se añade un espacio por la cara.
(https://i.postimg.cc/jSPSrBmz/ComoBox.png)

Saludos.


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: [D]aniel en 8 Abril 2021, 16:25 pm
Hola, prueba a poner al final del Split:

Código:
System.StringSplitOptions.RemoveEmptyEntries

o

Código:
StringSplitOptions.RemoveEmptyEntries

Eso lo tenés que poner como parámetro en tu Split();.


Saludos


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: K-YreX en 8 Abril 2021, 20:24 pm
Exactamente, como dice [D]aniel se soluciona.
Como estás añadiendo un espacio después de cada unidad, te queda una cadena como esta (sustituyo cada espacio por un _):
Código:
datos = "G:_F:_"
Primer Split -> "G:" (parte izquierda) + "F:_" (parte derecha)
Segundo Split -> "G:" + "F:" (parte izquierda) + "" (parte derecha)
Por eso al final queda un último elemento que es una cadena vacía. Porque es lo que queda a la derecha del último espacio.

Otra solución válida es:
Código
  1. datos = ... // datos = "G:_F:_"
  2. datos = datos.Trim(); // Elimina espacios iniciales y finales -> datos = "G:_F:"
  3. string[] unidades = datos.Split(' ');


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: Meta en 9 Abril 2021, 22:51 pm
Funciona.
Código
  1.        void UnidadDisco()
  2.        {
  3.            // Nombre de la unidad.
  4.            ConsigueComponentes("Win32_CDROMDrive", "Id");
  5.  
  6.            datos = datos.Trim();
  7.  
  8.            // Delimitador.
  9.            string[] unidad = datos.Split(' ');
  10.            comboBox_Unidad.Items.AddRange(unidad);
  11.  
  12.  
  13.            //comboBox_Unidad.Items.AddRange(unidades.Split(':'));  //el Split se puede hacer en una sola linea.
  14.  
  15.            // Selecciona la primera unidad.
  16.            comboBox_Unidad.SelectedIndex = 0;
  17.        }

Me he dado cuenta que en el otro programa más grande no.

Ya no me dice si tiene disco o no.
Código
  1. using System;
  2. using System.Management; // No olvidar y añadir en Dependencias, NuGet.
  3. using System.Runtime.InteropServices;
  4. using System.Text;
  5. using System.Windows.Forms;
  6.  
  7. namespace Lector_discos_Net_5_01_cs
  8. {
  9.    public partial class Form1 : Form
  10.    {
  11.        public Form1()
  12.        {
  13.            InitializeComponent();
  14.        }
  15.  
  16.        // Variable.
  17.        string datos = "";
  18.  
  19.        [DllImport("winmm.dll")]
  20.        public static extern Int32 mciSendString(string lpstrCommand,
  21.            StringBuilder lpstrReturnString,
  22.            int uReturnLength,
  23.            IntPtr hwndCallback);
  24.  
  25.        StringBuilder rt = new StringBuilder(127);
  26.  
  27.        private void button_Abrir_Click(object sender, EventArgs e)
  28.        {
  29.            label_Mensaje.Text = "Abriendo...";
  30.            Application.DoEvents();
  31.            mciSendString("set CDAudio!" + comboBox_Unidad.Text + " door open", rt, 127, IntPtr.Zero);
  32.  
  33.            /*
  34.                Si quieres por ejemplo elegir la unidad que quieras, en este caso la H, se le asigana !H
  35.                como indica abajo. En vez de CDAudio, CDAudio!H.
  36.                mciSendString("set CDAudio!H door open", rt, 127, IntPtr.Zero);
  37.             */
  38.  
  39.            label_Mensaje.Text = "Abierto.";
  40.            discoSiNo();
  41.        }
  42.  
  43.        private void button_Cerrar_Click(object sender, EventArgs e)
  44.        {
  45.            label_Mensaje.Text = "Cerrando...";
  46.            Application.DoEvents();
  47.            mciSendString("set CDAudio!" + comboBox_Unidad.Text + " door closed", rt, 127, IntPtr.Zero);
  48.            label_Mensaje.Text = "Cerrado.";
  49.            label_Mensaje_disco.Text = "Disco en el lector: Leyendo...";
  50.            discoSiNo();
  51.        }
  52.  
  53.        // Lectura de dispositivos.
  54.        void ConsigueComponentes(string hwclass, string syntax)
  55.        {
  56.            ManagementObjectSearcher mos = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hwclass);
  57.            foreach (ManagementObject mj in mos.Get())
  58.            {
  59.                if (Convert.ToString(mj[syntax]) != "")
  60.                {
  61.                    //datos = Convert.ToString(mj[syntax]);
  62.                    datos += Convert.ToString(mj[syntax]).ToString() + " ";
  63.                }
  64.            }
  65.        }
  66.  
  67.        // Comprobar si hay disco en el lector.
  68.        void discoSiNo()
  69.        {
  70.            // Disco en la unidad del lector.
  71.            ConsigueComponentes("Win32_CDROMDrive", "MediaLoaded");
  72.  
  73.            // ¿Disco en el lector?
  74.            if (datos == "True")
  75.            {
  76.                label_Mensaje_disco.Text = "Disco en el lector: Sí.";
  77.            }
  78.  
  79.            else
  80.            {
  81.                label_Mensaje_disco.Text = "Disco en el lector: No.";      
  82.            }
  83.  
  84.            // Limpiar.
  85.            datos = "";
  86.  
  87.  
  88.        }
  89.  
  90.        private void Form1_Load(object sender, EventArgs e)
  91.        {
  92.            discoSiNo();
  93.  
  94.            // Nombre de la unidad.
  95.            ConsigueComponentes("Win32_CDROMDrive", "Id");
  96.  
  97.            // Borra espacios en blanco.
  98.            datos = datos.Trim();
  99.  
  100.            // Delimitador.
  101.            string[] unidad = datos.Split(' ');
  102.            comboBox_Unidad.Items.AddRange(unidad);
  103.  
  104.  
  105.            // Selecciona la primera unidad.
  106.            comboBox_Unidad.SelectedIndex = 0;
  107.  
  108.            // Limpiar.
  109.            datos = "";
  110.        }
  111.    }
  112. }
  113.  


Título: Re: Corregir o quitar elementos del comBoBox
Publicado por: K-YreX en 10 Abril 2021, 01:11 am
Normal que en el segundo código no funcione si estás intentando comparar el contenido de <datos> a "True" (línea 74) cuando no estás guardando "True". Y tú me dirás que sí, que en la línea 71 llamas a la función y guarda "True" en <datos> pero entonces yo te diré "y qué pasa con el espacio que estás añadiendo al final?? (línea 62)"

Por otra parte decir que ese código tiene demasiado acoplamiento. Utilizas todo el tiempo la misma variable <datos> para guardar cada uno de los resultados. Es mejor que la función devuelva un string con el resultado y ya tú lo asignarás a la variable que quieras en cada momento.

Una mejor opción sería algo como esto:
Código
  1. private static readonly char SEPARADOR = "|"; // Separador de elementos. Por si en algun momento necesitas cambiarlo por otro
  2.  
  3. private string ConsigueComponentes(string hwclass, string syntax) {
  4.    string resultado = string.Empty;
  5.    ManagementObjectSearcher mos = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hwclass);
  6.    foreach (ManagementObject mj in mos.Get()) {
  7.        if (!string.IsNullOrEmpty(mj[syntax].ToString()))
  8.            resultado += mj[syntax].ToString() + SEPARADOR;
  9.    }
  10.    // El ultimo separador nunca lo vas a necesitar para nada -> Lo puedes eliminar directamente y quitarte futuros problemas
  11.    resultado = resultado.Remove(resultado.Length - 1);
  12.    return resultado;
  13. }
  14.  
  15. // Mejor tener un metodo que te diga si hay o no hay disco con true/false y luego ya lo usaras donde lo necesites
  16. private bool HayDisco() {
  17.    string resultado = ConsigueComponentes(...);
  18.    return (resultado == "True");
  19. }
  20.  
  21. private void Form_Load(object sender, EventArgs e) {
  22.    ...
  23.    string[] unidades = ConsigueComponentes(...).Split(SEPARADOR);
  24.    comboBox.Items.AddRange(unidades);
  25.    ...
  26. }