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
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
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ª
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ª
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ª
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ª
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ª
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: