Introducción:
en esta revisión de la utilidad gsCopia, se hacen ciertas comprobaciones de que el path a
copiar (el origen) es correcto (o casi), además de que se comprueba si se usan caracteres
comodines o algún nombre de fichero, en esos casos, se pasa esa información a la utilidad de
copia y hará lo que se espera.
Por ejemplo, si le indicas algo como lo de la figura 1, se copiarán solo los ficheros con la
extensión .dll del directorio indicado.
También puedes usar los caracteres comodines para hacer otros filtros, como es el caso de la
figura 2, en el que se indica que solo se copien los ficheros que empiecen por FP y tengan la
extensión .dll (fp*.dll)
Nota:
Debes tener en cuenta que yo solo lo he probado con xcopy y con robocopy, si usas otra utilidad,
deberías hacer tus propias comprobaciones.
También se comprueba si se está ejecutando como administrador y se avisa por medio de un
"escudito".
En la figura 1 puedes ver ese escudo cuando se ejecuta en Windows Vista y no se está ejecutando
como administrador:
Figura 1. La utilidad en ejecución (no como administrador)
Si se ejecuta como administrador, se muestra un escudo verde, tal como puedes ver en la
figura 2:
Figura 2. La utilidad en ejecución (como administrador)
Al pulsar en el escudo (haciendo un clic), te muestra un mensaje de aviso indicando ese
hecho.
Además de estos cambios, también he hecho unos cambios menores, como es que se deshabilite el
botón de comprobación si se selecciona la opción "Deshabilitar los botones de selección".
Y también he asignado correctamente algunos tooltips que se me colaron al copiar y pegar
controles, je, je.
Aquí tienes el código con los cambios que he hecho en esta revisión 1.0.1.6.
Pulsa en el siguiente link si quieres ver el código anterior
(el de la versión 1.0.1.0)
Este es el bucle del método btnCopiar_Click, el resto del código de ese método no ha
cambiado.
For Each datoOri As String In datosOrig
progressBar1.Value = 0
' Quitar las comillas dobles que tenga (14/Dic/07)
datoOri = datoOri.Trim((ChrW(34) & " ").ToCharArray)
' Es posible que el origen tenga una especificación (14/Dic/07)
' por ejemplo: c:\datos\*.txt
Dim di As DirectoryInfo = Nothing
Dim dirOriTmp As String = datoOri
' Si tiene caracteres comodines, usar el nombre del directorio
If dirOriTmp.IndexOfAny("*?".ToCharArray) > -1 Then
dirOriTmp = Path.GetDirectoryName(datoOri)
' Si se usa robocopy, indicar los ficheros como argumento
' El formato es:
' ROBOCOPY source destination [file [file]...] [options]
' por tanto, se pueden agregar a los parámetros
If util.Contains("robocopy") Then
Dim index As Integer = datoOri.LastIndexOf("\")
If index > -1 Then
params = ChrW(34) & datoOri.Substring(index + 1) & ChrW(34) & " " & params
datoOri = datoOri.Substring(0, index)
dirOriTmp = datoOri
Else
' Si llega aquí es que algo no va bien...
MessageBox.Show("Parece que el origen: " & vbCrLf & _
datoOri & vbCrLf & _
"no es un directorio correcto.", _
"Copiar", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
' Restaurar los valores internos
Me.Cursor = Cursors.Default
progressBar1.Visible = False
statusInfo.Text = statusInfo.Tag.ToString
btnCopiar.Text = "Copiar"
habilitarControles(True)
yaEstoy = False
cboDestino.Focus()
Exit Sub
End If
End If
ElseIf dirOriTmp.EndsWith("\") Then
' Si acaba en \ quitarlo, porque no copiará nada con xcopy (con robocopy también funciona así)
dirOriTmp = dirOriTmp.Substring(0, dirOriTmp.Length - 1)
datoOri = dirOriTmp
End If
' Último intento,
' si da error es que hay algo más que no está bien
' Intentarlo al menos 2 veces...
Dim intentos As Integer = 0
Dim conFallo As Boolean = False
While intentos < 2
Try
di = New DirectoryInfo(dirOriTmp)
' Si llega aquí, es que no ha dado error
conFallo = False
Exit While
Catch ex As Exception
' en ese caso, se filtra el directorio
dirOriTmp = Path.GetDirectoryName(dirOriTmp)
intentos += 1
conFallo = True
End Try
End While
' Si llega con fallos, avisar y salir
If conFallo Then
MessageBox.Show("Parece que el origen: " & vbCrLf & _
datoOri & vbCrLf & _
"no es un directorio correcto.", _
"Copiar", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
' Restaurar los valores internos
Me.Cursor = Cursors.Default
progressBar1.Visible = False
statusInfo.Text = statusInfo.Tag.ToString
btnCopiar.Text = "Copiar"
habilitarControles(True)
yaEstoy = False
cboDestino.Focus()
Exit Sub
End If
' Si no existe, es que será un fichero (14/Dic/07)
If di.Exists = False Then
' El directorio será el padre:
dirOriTmp = di.Parent.FullName
di = New DirectoryInfo(dirOriTmp)
End If
' Usar siempre el directorio de origen
Dim dirDest As String = dest & If(dest.EndsWith("\"), "", "\") & di.Name
Dim sb As New StringBuilder
' Usar comillas dobles por si tiene espacios (14/Dic/07)
sb.AppendFormat("""{0}"" ""{1}"" {2}", datoOri, dirDest, params)
statusInfo.Text = "Copiando en " & dirDest & "..."
Dim proceso As New Process
With proceso
.StartInfo.Arguments = sb.ToString
.StartInfo.FileName = util
If My.Settings.OcultarVentana Then
.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
Else
.StartInfo.WindowStyle = ProcessWindowStyle.Normal
End If
.StartInfo.WorkingDirectory = datoOri
.Start()
progressBar1.Value = 1
Do
Application.DoEvents()
If cancelar Then
.Kill()
.Close()
Exit For
End If
Loop While .HasExited = False
End With
Next
Para ver las cosas nuevas, busca (14/Dic/07), y como más o menos está comentado todo lo que
he hecho, pues no tendrás problemas para entender los cambios.
Al principio del evento Form_Load he hecho la comprobación de si se está ejecutando como
administrador, y lo único que hago es usar una imagen u otra según como se esté ejecutando.
Private Sub Form1_Load() Handles MyBase.Load
' Comprobar si se ejecuta como administrador (14/Dic/07)
comoAdministrador = EsAdministrador()
If comoAdministrador Then
Me.statusOpAdmin.Image = My.Resources.escudo16_OK
Me.statusOpAdmin.ToolTipText = " Ejecutando como administrador "
Else
Me.statusOpAdmin.Image = My.Resources.escudo16_Exclamation
Me.statusOpAdmin.ToolTipText = " No estás ejecutando como administrador "
End If
La variable comoAdministrador está definida en el formulario, y es de tipo Boolean, se usará
también en el código que te mostraré más abajo.
El control statusOpAdmin en realidad es una etiqueta del StatusStrip. Y cuando se produce el
evento Click se ejecuta el siguiente código en el que se muestra un MessageBox con
el texto adecuado:
Private Sub statusOpAdmin_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles statusOpAdmin.Click
If comoAdministrador Then
MessageBox.Show("Estás ejecutando la aplicación como administrador" & vbCrLf & _
"de esta forma no tendrás problemas al copiar.", _
"Copiar", _
MessageBoxButtons.OK, _
MessageBoxIcon.Information)
Else
MessageBox.Show("No estás ejecutando la aplicación como administrador" & vbCrLf & _
"es posible que algunas cosas no las puedas copiar." & vbCrLf & _
"Si detectas problemas al copiar, " & _
"deberías ejecutar la aplicación como adminsitrador.", _
"Copiar", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
End If
End Sub
La función que comprueba si es administrador o no es la que ya te mostré hace unos meses,
pero te la pongo aquí nuevamente:
' Comprobar si se ejecuta como administrador
Private Function EsAdministrador() As Boolean
My.User.InitializeWithWindowsUser()
Return My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator)
End Function
Y esto es todo... aunque parezcan pocos cambios, en realidad hacen que la utilidad sea más
"útil", je, je.
Nos vemos.
Guillermo