el Guille, la Web del Visual Basic, C#, .NET y más...
Ir al índice de Visual Studio 2008 y .NET Framework 3.5 Utilidades .NET Framework 3.5

Explicación detallada de la utilidad gsCopia

 
Publicado el 13/Dic/2007
Actualizado el 31/Ene/2009
Autor: Guillermo 'guille' Som

Nueva versión en el ZIP del código fuente (v1.0.4.0)


Explicación detallada de la utilidad gsCopia. Aquí te explico el código usado en esta utilidad, con las capturas de los formularios usados y explicación del código que la hace posible.



 

La batallita del agüelo:

Esta utilidad inicialmente la he hecho para que un colega mío (que no está muy puesto en esto de los Windows y su uso) pudiera hacer copias de los datos de algunos programas que usa con frecuencia (programas de facturación).

La idea era poner un disco USB y copiar las cosas nuevas (o modificadas) en el USB. Pero como seguramente sabrás, el nombre de la unidad USB puede cambiar dependiendo de que haya otras unidades. Es decir, si pones un disco USB (pendrive) en tu equipo, puede que le asigne la letra F. Si pones otro, seguramente le asignará la letra G, y así... Pero si resulta que la letra en la que quieres copia es la F y ya has puesto otro USB, pues ya no sería la letra F, sino la G.

¿Y cual es el problema?
El problema es que si esa copia la haces por medio de algún fichero .bat (o .cmd), pues la cosa se puede ir al garete si no está puesto el disco que debe estar puesto... así que... me dije, lo mejor es hacerle una aplicacioncilla que permita cambiar el nombre de la unidad, para esos casos en los que tenga más de un disco USB.

Por tanto, esta utilidad lo que hace es como lo que haría una orden guardada en un fichero .bat (para usar alguna utilidad desde la línea de comandos) y ejecuta esa orden, indicando qué directorios quieres copiar y en que unidad lo quieres copiar.

Esas órdenes las he configurado inicialmente usando el xcopy y el robocopy. Y he puesto las opciones que yo suelo usar habitualmente con esos dos ejecutables.

La diferencia entre xcopy y robocopy es que el primero copia los ficheros, pero deja en el destino los que ya no existan en el origen; mientras que robocopy, si en el origen ya no hay un fichero y está en el destino, lo borra del destino.
En realidad se puede configurar el robocopy para que no los borre, pero así te aseguras de que lo que estás copiando es lo mismo que tienes actualmente en el "original".

Y eso es lo que hace esta utilidad... o al menos es una de las cosas que hace, ya que si en el destino le dices que lo quieres copiar en la unidad G, y resulta que no hay ninguna unidad extraíble con esa letra, pues el programa avisa (ver la figura 6). Es decir, se comprueba que haya un disco extraíble (los discos USB se tratan como extraíbles) con la letra en la que indicas como destino.

 

¿Qué cosas pueden servirte de esta utilidad?

Como suele ser costumbre, las utilidades que publico no son solo eso: utilidades, sino que son cosas de las que puedes sacar ideas para hacer otras cosas o para aprender cómo hacer ciertas cosas.

En particular, esta utilidad seguramente la usaré en mi próximo libro "Las recetas del Guille para Visual Basic 2005 y 2008" para explicar algunas de las cosas que hace... que como extra, pues te las voy a contar aquí... (espero que después los editores no me regañen por haberlo hecho, je, je).

Te enumero las cosillas que te pueden ser de utilidad, pero antes quiero que veas las pantallas (o formularios) usados en esta utilidad.

Qué opciones tiene esta utilidad

En la figura 1 tienes el formulario principal en modo de diseño.

En la parte de arriba tienes un combo con los directorios de origen, en ese combo (al igual que en resto) se van guardando las distintas cosas que vayas indicando, con idea de poder tener varias configuraciones almacenadas.
El otro combo es para indicar la unidad de destino.
Para seleccionar tanto el origen como el destino, existen dos botones para hacer eso (los que pone Seleccionar).

En el origen puedes indicar varios directorios separados por puntos y comas (al seleccionar o al arrastrar en ese combo, se añade a lo que ya haya), de esa forma puedes hacer copias de múltiples directorios de una sola vez.

En el destino solo puedes indicar un valor. Ese valor NO debe ser el directorio raíz de la unidad (ahora te explico porqué).

El botón ese de "Comprobar ahora", lo que hace es buscar entre las unidades extraíbles la primera que contenga un fichero llamado gsCopia.txt. Si ninguna de las unidades extraíbles tiene ese fichero, entonces muestra la primera unidad extraíble que encuentre.

¿Para que sirve eso?
Pues para poder facilitar la búsqueda del disco de destino... aunque una vez que todo está configurado ya no hace falta comprobar nada... pero bueno, lo puse... y ahí está.

El CheckBox ese que indica "Comprobar el disco de destino" está deshabilitado, y en un principio lo puse para que al iniciarse la aplicación buscara la unidad extraíble que tuviera ese fichero "especial", pero como en realidad no es necesario que esté, pues... lo he deshabilitado... seguramente en una futura versión lo quitaré, ya que no lo uso y no creo que lo vaya a usar...

El botón Copiar, pues... me imagino que ya sabes para que sirve... ¡exacto! para empezar a hacer la copia.

Hay dos "zonas" para la configuración. Los controles de esas dos zonas están en dos controles GroupBox.
Esos grupos están dentro de un control FlowLayoutPanel con idea de que al "contraerlas" se desplacen y se junten. Esto es para simular (un poco) los controles Expander de WPF (que seguramente habrás visto en Windows Vista).
Pero no son controles Expander de WPF, sino que está simulados. Y para simularlos he usado un control Panel que contiene un PictureBox (para la imagen del expander) y una etiqueta (para el texto). Cada uno de esos paneles están en cada GroupBox.
Al hacer clic en el botón, se oculta o expande el GroupBox correspondiente.
Cuando se muestra (expandido) se muestran todos los controles que contiene. Cuando se contraen, solo se muestra el botón (que es el PictureBox) y el texto (que es la etiqueta). En el caso de la imagen, cuando se contrae, se muestra con la punta de la flecha hacia abajo (ver la figura 7).

En el primer grupo están las opciones de la utilidad usada para copiar. En el combo de la Utilidad externa, estarán las utilidades que queramos usar. Como te he comentado antes, de forma predeterminada están la utilidad xcopy.exe y robocopy.exe.
En el otro combo (Parámetros) están los parámetros a usar con cada utilidad, (esos parámetros no están sincronizados con las utilidades, pero... esto es un mal menor...).
También hay varias opciones (CheckBox) para indicar si se debe ocultar la ventana MS-DOS (o ventana de comandos) que se abre con cada una de esas utilidades y si se debe mostrar el disco de destino cuando la copia termine. En realidad, si la utilidad no fuera del tipo "consola", también servirá para ocultar la ventana que la aplicación use.

Como te comentaba antes, el destino NO debe ser el directorio raíz de la unidad, es decir, si la unidad es la F, no se puede indicar F:\ como directorio de destino, bueno, como poder, si se puede, pero el programa no lo permitirá.
La razón es que robocopy.exe elimina las cosas que no están en el destino, por tanto, si se permitiera el uso del directorio raíz, lo que podría pasar es que se borrara todo lo que ya hubiera en el disco extraíble... y la verdad es que eso no es buena idea.
Lo recomendable es usar un directorio. Ese directorio no tiene porqué existir, ya que se creará al hacer la copia (solo lo he probado con un nivel, y esa creación no la hace mi utilidad, sino que lo hace el propio robocopy o xcopy).

Además de que lo bueno de usar carpetas, es que en un mismo disco extraíble puedes tener más de una carpeta de destino. En el caso de este colega que te comenté antes, le he creado dos opciones de copia, una para las copias diarias y la otra para las copias mensuales. Como el disco que usa es de 2 GB, y lo que tiene que copiar no pasa de 700 MB, pues no tendrá problemas de almacenamiento.

En el segundo grupo, el de Opciones de configuración, te permite indicar si se deshabilitan los botones de selección y también permite indicar si se permite la escritura en esos combos de opciones.
¿Por qué?
A ver... sin ganas de que nadie se moleste, este colega mío es como muchos de los que suelen usar los ordenadores (o computadoras), es decir, saben lo justo y necesario, pero no lo saques de usar las aplicaciones que suelen usar, así que... para evitar que escriban algo que no deben escribir o pulsen en el botón de selección, pues le he puesto una opción para que una vez que tiene las cosas seleccionadas (el origen, el destino, la utilidad de copia y los parámetros), pues... ¡que no escriban! ya que si lo hacen, pues... en fin... que cualquiera sabe lo que pueden hacer, je, je...
¡De verdad! Hay muchos que no saben ni lo que es una carpeta o un directorio... ¡que te lo digo yo!

Je, je, je, me acabo de acordar de hace unos años, cuando tenía que explicar por teléfono a alguien que hiciera algo en el ordenador... le iba dando las instrucciones justas y exactas de cada cosa que tenía que hacer... y les decía... ¡no pienses! solo haz lo que te voy diciendo... je, je, je, al principio se enfadaban conmigo por decirles que no pensaran, pero después, (cuando se equivocaban), se daban cuenta de que se lo decía porque sabía que se iban a equivocar... en fin...

Sigamos, en ese mismo grupo de opciones de configuración hay un botón para Configurar el contenido de las listas, al pulsar en ese botón, se muestra el otro formulario (figura 2), y permite eliminar cosas de las listas (combos). Esto es útil para quitar los valores que la aplicación tiene por defecto y para quitar las unidades de destino en la que se muestra el directorio raíz. Ahora veremos algunas cosas que tiene o hace ese formulario, que no es mucho, pero vale la pena.

Además del botón de Salir (también te puedes imaginar para qué sirve), en la parte de abajo del todo, hay un control StatusStrip con una etiqueta para mostrar la info esa que ves en la figura 1 y también para mostrar el directorio que se está copiando en cada momento. También tiene un control ProgressBar, al que le he asignado el valor Marquee en la propiedad Style, con idea de que se vaya mostrando un cursor en "vaivén", para que así sepa el usuario que se está haciendo algo, aunque no se muestra el porcentaje, ya que en estos casos en los que se deben copiar muchos ficheros, pues... es complicado ser exactos con el tiempo de copia... y si no me crees... que le pregunten a los que hacen los programas y muestran esas barras de progreso (y no solo en Windows); la verdad es muy complicado ser exactos con el tiempo de copia... así que... no me he complicado la vida y he preferido que sea ese estilo para que se vea algo de acción, pero nada más.

La etiqueta esa roja con las letras blancas (para que resalte y se vea bien), la uso para indicar que no hay ninguna unidad extraíble instalada. Y también lo uso para indicar que la unidad de destino no está en presente en el equipo. Ahora veremos cómo se hacen esas comprobaciones.

Y esto es todo lo que tiene el formulario principal. Cuando te muestre el código, veremos cómo se hacen algunas de las cosas que se deben hacer, por ejemplo, comprobar que unidades extraíbles hay, etc.

 

Figura 1. Formulario principal en modo de diseño
Figura 1. Formulario principal en modo de diseño

 

El formulario de configuración de las listas (contenido de los combos), prácticamente lo que tiene es un contenedor con el control de imagen para usar como botón de expansión, la etiqueta del texto a mostrar en cada grupo, un control ListView para mostrar los elementos de cada combo y un botón para eliminar los elementos seleccionados.

Esos cuatro contenedores están también contenidos en un control FlowLayoutPanel, con idea de que si se contraen (ocultan) los paneles, se agrupen y se desplacen adecuadamente. El formulario también se adapta a ese contenido, de forma que si estuvieran todos contraídos, pues sería más pequeño. En realidad no es una funcionalidad "necesaria" en esta ventana, pero... ahí está...

En la parte inferior están los dos botones de cualquier cuadro de diálogo (Aceptar y Cancelar) además de un botón Deshacer, con idea de que si borras más de la cuenta, poder dejarlo como estaba.
Para poner una línea 3D de separación, uso dos etiquetas, para hacer lo que te explico en Crear líneas 3D para usar como separación, así que de esto, seguramente no te hablaré más, ya que usando ese link puedes ver el código y la explicación.

Al entrar por primera vez en este formulario, se quedarán deshabilitados los botones de Deshacer y Aceptar, que solo se activarán si borras algo de cualquiera de las listas.

Para borrar, puedes usar el botón Eliminar o bien pulsar la tecla Delete (Supr), y eso borrará del control ListView que corresponda... (sí, ya lo sé, que eso es lo lógico, pero... para que quede claro, no sea que pienses que si pulsas en el botón de eliminar del primer grupo te lo borra todo...).

 

Figura 2. El formulario de configuración del contenido de las listas
Figura 2. El formulario de configuración del contenido de las listas

 

Algunas capturas de la aplicación en ejecución

Antes de entrar en detalle sobre el código (que seguramente te pondré en una página aparte), veamos algunas capturas de la utilidad en pleno funcionamiento, con idea de que veas cómo quedarían algunas cosas al estar en funcionamiento.

En la primera toma (figura 3), está la aplicación con todas las opciones disponibles.

 

Figura 3. En ejecución, toma 1ª
Figura 3. En ejecución, toma 1ª

En la segunda toma (figura 4) se ha seleccionado la opción No permitir la escritura en las opciones.
Cuando se marca esa opción, se selecciona la de Deshabilitar los botones de selección (que también se deshabilita, ya que no tiene ningún sentido poder seleccionar algo si el combo no permite que se escriba en él).

Al tener esa opción seleccionada, los combos pasan a ser de "solo lectura" (la propiedad DropDownStyle tiene un valor DropDownList en lugar del valor DropDown, que es el predeterminado y el que permite que se escriba).

Como seguramente sabrás, si el "estilo" de un control ComboBox es DropDown, permite que se escriba algo en ellos. Pero cuando el valor es DropDownList, no permite que se escriba, ya que solo permite seleccionar alguno de los valores que tenga en la lista. En cualquier caso, la propiedad Text se puede seguir usando para indicar el texto a mostrar. La diferencia entre estos dos estilos es que si está en modo DropDown, si se escribe algo que no está en la lista, se permite, y se muestra eso que se haya escrito. Pero si está en modo DropDownList y se asigna a la propiedad Text algo que no esté en los elementos de la lista, pues no se muestra nada, (en realidad sigue mostrando lo que hubiera antes de asignar un valor que no está en la lista, pero sin dar error ni nada de eso); en el caso de que lo indicado en el texto esté en los elementos del combo, se mostrará ese elemento; por tanto, esa forma de crear los combos es útil cuando no queremos que el usuario indique otra cosa diferente de lo que hay, que es lo que se pretende cuando se "impide" la escritura en esos controles, es decir, dejar lo que haya, pero no poder asignar nada nuevo. 

Figura 4. En ejecución, toma 2ª
Figura 4. En ejecución, toma 2ª

En la tercera toma (figura 5) se muestra un aviso de que no hay unidades extraíbles... es decir, nos está avisando de que debemos poner alguna. En este caso, como no hay unidad extraíble, el botón Copiar también está deshabilitado. 

Figura 5. En ejecución, toma 3ª
Figura 5. En ejecución, toma 3ª

En la cuarta toma (figura 6), si que hay (al menos) una unidad extraíble pero entre las unidades extraíbles halladas no está la que se ha indicado en la unidad de destino, por tanto, se deshabilita el botón de copia y se avisa de ese hecho. 

Figura 6. En ejecución, toma 4ª
Figura 6. En ejecución, toma 4ª

Todo este proceso de comprobación de si hay unidades, etc., se hace en un método llamado "hayUnidadExtraible". Ese método se llama desde un temporizador, el cual se está ejecutando de continuo. Aunque, si una de esas veces se detectó alguna unidad extraíble, el tiempo de comprobación pasa a ser de 3 segundos; en caso de que no se haya detectado ninguna unidad extraíble, la comprobación se hace cada segundo; de esta forma, si se quita o se pone una unidad extraíble mientras la aplicación está en ejecución, se actualizará adecuadamente ese aviso.

 

En la última toma (figura 7) se muestra la aplicación con los dos grupos "replegados", y como no hay ningún aviso y el botón de copiar está habilitado, significa que la unidad extraíble de destino está insertada.

Figura 7. En ejecución, toma 5ª
Figura 7. En ejecución, toma 5ª

 

Si quieres ver el código fuente de esta aplicación (y de la función que comprueba las unidades extraíbles que hay instaladas en el equipo), puedes verlo al completo bajándote el proyecto para Visual Basic 2008 (lee la nota que hay más abajo para que no te pille de sorpresa si te da error al cargarlo). Ese proyecto lo puedes abrir tanto con la versión "normal" de Visual Studio 2008 como con la versión Express de Visual Basic 2008 (ya sabes que las versiones Express son totalmente gratuitas y cien por cien operativas).

Y si quieres ver el código en línea, puedes hacerlo usando este link: El código fuente de la utilidad gsCopia para Visual Basic 2008.

 

Si quieres que publique también el código de C#

Por ahora solo está el código fuente y el proyecto para Visual Basic 2008, no se si algún día de estos publicaré el de C#... lo mismo si se me pasa el mosqueo que tengo con algunos que se creen más listos que otros solo por usar un lenguaje que no es de la familia BASIC... ya veremos...
Si me lo piden mucha gente, pues lo mismo me animo, así que... usa este link (de mis foros) para pedirme el código de C#... y como la experiencia me ha enseñado que la gente no suele leer... pues lo mismo no hay tantas peticiones como para que me tome "la molestia" de convertirlo a C#... (si hay menos de 10 peticiones, no lo publico, je, je).

Actualización del 12/Ene/08:
Pues parece que no hay mucho interés en que publique el código de C#... hasta hoy solo hay 2 peticiones.
En fin...

 

Espero que te sea de utilidad.

Nos vemos.
Guillermo

P.S.
Te recomiendo que veas las revisiones realizadas:



 


La fecha/hora en el servidor es: 23/12/2024 7:49:14

La fecha actual GMT (UTC) es: 

©Guillermo 'guille' Som, 1996-2024