Comando xcopy no funciona para versiones windows 64 bits

602 views
Skip to first unread message

Manuel Francisco Suarez Marin

unread,
Jul 23, 2014, 5:17:11 PM7/23/14
to publice...@googlegroups.com
Realicé un pequeño aplicativo para realizar copias de seguridad automáticas de directorios completos desde una ruta predeterminada a otra ruta predeterminada desde el mismo equipo o desde equipos diferentes. Este aplicativo funciona bien en windows xp de 32 bits,  pero cuando trato de utilizarlo en windows de 64 bits no me funciona el comando "!xcopy"
La instrucción que utilizo es la siguiente:

lcRutadatos = 'D:\contable\datos'
lcSubdir = 'C:\copia_contable\datos_140723_1610'

!xcopy &lcRutadatos /e &lcSubdir

donde me aparece el mensaje de "Aplicación de 16 bits no compatible: El programa o característica "\??\c:\program files (x86)\microsoft visual foxpro 7\run.pif" no se puede iniciar o ejecutar porque no es compatible con versiones de 64 bits de Windows. Consulte con el fabricante de software si existe una versión disponible que sea compatible con Windows de 64 bits"

Agradezco si me pueden colaborar con esto

Manuel Suarez
Barranquilla, Colombia

Fernando D. Bozzo

unread,
Jul 23, 2014, 5:21:29 PM7/23/14
to publice...@googlegroups.com
Tal vez te convenga usar Windows Scripting Host (WSH)

Edgar Acevedo

unread,
Jul 24, 2014, 1:31:16 AM7/24/14
to publicesvfoxpro
Prueba a utilizar MIRROR.EXE en lugar del XCOPY.
Te lo he adjuntado como MIRROR.TXT, bájalo y renómbralo a MIRROR.EXE
Es un Freeware, no tendrás que comprarlo.

Saludos,   

Edgar Acevedo.
MIRROR.TXT

arquinav

unread,
Jul 24, 2014, 7:57:47 AM7/24/14
to publice...@googlegroups.com
en vfp9 lo hago con COPY FILE comando nativo.

Carlos Miguel FARIAS

unread,
Jul 24, 2014, 10:55:55 AM7/24/14
to Grupo Fox
En Fox DOS, para backups, arme un algoritmo con las funciones de acceso a archivos F... de bajo nivel que provee Fox.
Copiaba todo, tablas e indices, como solo copia los datos específicos (tablas e indices reales, no temporales, o de trabajo) la copia es menos voluminosa.
Lo que me sorprendió es que el tiempo de copia, no alcanzaba a duplicar la del xcopy, por lo que como además era selectivo, el tiempo final de backup era casi idéntico.
Lo mate con una barra de progreso que informaba lo que iba copiando y % de avance (tardaba con eso como 5 veces más).
El copy file, solo me deja mostrar la barra de progreso por archivo, y los grandes, parecía que el sistema se congelaba.
Igual, es una buena idea.
Saludos: Miguel, La Pampa (RA)

Fernando D. Bozzo

unread,
Jul 24, 2014, 11:30:43 AM7/24/14
to publice...@googlegroups.com
Miguel, en algún momento se me ocurrió hacer algo así, pero más por investigar que por necesidad.

Para el FOPEN/FRWITE usás lo típico de abrir el archivo origen e ir escribiendo en el destino, o usás alguna otra forma más elaborada?


Saludos.-

Carlos Miguel FARIAS

unread,
Jul 24, 2014, 5:40:06 PM7/24/14
to Grupo Fox
En una tabla de definición de la BD (no había DBC cuando la cree), tenía todas las tablas de la aplicación, indicando si las mismas tenían solo dbf y si además tenían estructural y memo.
No usaba idx y no estructurales, no al menos en el backup.
Estos últimos, es muy común que en cualquier momento, se desactualicen (independientemente de "caídas" del sistema), por lo que, al restaurar la bd, es preferible re-indexar, igual, al restaurar la bd, siempre reindexaba los estructurales, uno nunca sabe.
La rutina se encargaba de cerrar o forzar el cerrado de cualquier tabla abierta (backup en frío)
Entonces, se abre la tabla, y con un bucle, se toma cada tabla de la aplicación, y con un bucle se iba leyendo bloque a bloque el archivo de origen y escribiendo en destino.
Esto pensado para máquinas corriendo DOS, a las que difícilmente podías configurar memoria extendida y demás "cochinadas" del DOS para obtener hasta con suerte dos MB.
La ventaja era que como al empezar la copia del archivo, sabía el tamaño de este, podía detectar si destino tenia capacidad suficiente. La rutina permitía hacer backup directamente a disquetes y pedir el reemplazo a medida que se llenaban.
Para copiar usaba FREAD, con un bloque de 4096 caracteres, porque era el tamaño de unidad de lectura en el S.O. más común en el momento que lo instrumente.
Para el 2000 +/-, con los usuarios, ya capacitados, se empezó a hacer la copia hacia el mismo disco (la rutina creaba una carpeta AD HOC) y luego de ahí lo copiaban a unidad ZIP o a CD.
Saludos: Miguel, La Pampa (RA)

Fernando D. Bozzo

unread,
Jul 24, 2014, 6:01:05 PM7/24/14
to publice...@googlegroups.com
Yo hice una prueba antes, e intenté hacer una optimización, leyendo el máximo permitido por FREAD( 65535 bytes) y guardando en una variable hasta 256 pedazos (16 MB, el máximo de una variable) y luego guardando en destino con FWRITE que increiblemente no tiene ese límite de 65535, y la verdad es que esa prueba me dejó mal sabor...

Puse un wait windows nowait "Leyendo..." y uno para el "Escribiendo...", y no podía creer que la lectura de los 16 MB se tardaba como 5 segundos y la escritura de lo mismo era casi instantánea! ¿una escritura más rápida que una lectura? Así que luego hice un SET COVERAGE TO <archivo> para analizar el programa y ver dónde se iban los tiempos, que no me lo podía creer, y efectivamente, se iba en el FREAD.


Este es el programa, por si a alguno le interesa:


*-- Fernando D. Bozzo
*-- 24/07/2014
LPARAMETERS tcOrigen, tcDestino

TRY
    LOCAL lnHandle_O, lnHandle_D, lcStr, laDir(1,1), I, lnSecs, loEx as Exception

    IF EMPTY(tcOrigen)
        tcOrigen    = 'C:\DESA\CORRUPCION_TABLAS\corrupcion.zip'
    ENDIF
    IF EMPTY(tcDestino)
        tcDestino    = 'C:\DESA\CORRUPCION_TABLAS\corrupcion.zip.2'
    ENDIF

    IF ADIR( laDir, tcOrigen ) = 0
        ERROR 1, tcOrigen
    ENDIF
   
    IF laDir(1,2) = 0
        lnHandle_D    = FCREATE( tcDestino, 0 )
        FCLOSE(lnHandle_D)
        EXIT
    ENDIF
   
    SET COVERAGE TO (FULLPATH('copyfile.log'))
    lnSecs        = SECONDS()
    lnHandle_O    = FOPEN( tcOrigen, 0 )
    lcStr        = ''

    IF lnHandle_O > -1 THEN
        lnHandle_D    = FCREATE( tcDestino, 0 )

        DO WHILE NOT FEOF( lnHandle_O )
            WAIT WINDOW NOWAIT 'Leyendo...'
            FOR I = 1 TO 256
                lcStr    = lcStr + FREAD( lnHandle_O, 65535 )
               
                IF FEOF( lnHandle_O )
                    EXIT
                ENDIF
            ENDFOR
           
            WAIT WINDOW NOWAIT 'Escribiendo...'
            FWRITE( lnHandle_D, lcStr )
            lcStr    = ''
        ENDDO
    ENDIF

CATCH TO loEx
    MESSAGEBOX( loEx.Message )
   
FINALLY
    FCLOSE(lnHandle_O)
    FCLOSE(lnHandle_D)
    SET COVERAGE TO
    WAIT WINDOW NOWAIT "Tiempo de copia: " + TRANSFORM(SECONDS()-lnSecs) + " segundos"

ENDTRY

RETURN




Y este el análisis del log con el Coverage Profiler:



                                        *-- Fernando D. Bozzo
                                        *-- 24/07/2014
                                        LPARAMETERS tcOrigen, tcDestino
                                       
0 Hits    1st 0.000000   Avg 0.000000   TRY
0 Hits    1st 0.000000   Avg 0.000000       LOCAL lnHandle_O, lnHandle_D, lcStr, laDir(1,1), I, lnSecs, loEx as Exception
                                       
0 Hits    1st 0.000000   Avg 0.000000       IF EMPTY(tcOrigen)
0 Hits    1st 0.000000   Avg 0.000000           tcOrigen    = 'C:\DESA\CORRUPCION_TABLAS\corrupcion.zip'
                                            ENDIF
0 Hits    1st 0.000000   Avg 0.000000       IF EMPTY(tcDestino)
0 Hits    1st 0.000000   Avg 0.000000           tcDestino    = 'C:\DESA\CORRUPCION_TABLAS\corrupcion.zip.2'
                                            ENDIF
                                       
0 Hits    1st 0.000000   Avg 0.000000       IF ADIR( laDir, tcOrigen ) = 0
0 Hits    1st 0.000000   Avg 0.000000           ERROR 1, tcOrigen
                                            ENDIF
                                           
0 Hits    1st 0.000000   Avg 0.000000       IF laDir(1,2) = 0
0 Hits    1st 0.000000   Avg 0.000000           lnHandle_D    = FCREATE( tcDestino, 0 )
0 Hits    1st 0.000000   Avg 0.000000           FCLOSE(lnHandle_D)
0 Hits    1st 0.000000   Avg 0.000000           EXIT
                                            ENDIF
                                           
0 Hits    1st 0.000000   Avg 0.000000       SET COVERAGE TO (FULLPATH('copyfile.log'))
1 Hit     1st 0.000184   Avg 0.000184       lnSecs        = SECONDS()
1 Hit     1st 0.000622   Avg 0.000622       lnHandle_O    = FOPEN( tcOrigen, 0 )
1 Hit     1st 0.000062   Avg 0.000062       lcStr        = ''
                                       
1 Hit     1st 0.000046   Avg 0.000046       IF lnHandle_O > -1 THEN
1 Hit     1st 0.020831   Avg 0.020831           lnHandle_D    = FCREATE( tcDestino, 0 )
                                       
1 Hit     1st 0.000059   Avg 0.000059           DO WHILE NOT FEOF( lnHandle_O )
13 Hits   1st 0.004293   Avg 0.002155               WAIT WINDOW NOWAIT 'Leyendo...'
13 Hits   1st 0.000654   Avg 0.000108               FOR I = 1 TO 256
3106 Hits 1st 0.000305   Avg 0.012421                   lcStr    = lcStr + FREAD( lnHandle_O, 65535 )
                                                       
3106 Hits 1st 0.000002   Avg 0.000137                   IF FEOF( lnHandle_O )
1 Hit     1st 0.000030   Avg 0.000030                       EXIT
                                                        ENDIF
3105 Hits 1st 0.000039   Avg 0.000053               ENDFOR
                                                   
13 Hits   1st 0.001731   Avg 0.001573               WAIT WINDOW NOWAIT 'Escribiendo...'
13 Hits   1st 0.052120   Avg 0.050576               FWRITE( lnHandle_D, lcStr )
13 Hits   1st 0.002155   Avg 0.002005               lcStr    = ''
13 Hits   1st 0.000053   Avg 0.000089           ENDDO
                                            ENDIF
                                       
1 Hit     1st 0.000000   Avg 0.000000   CATCH TO loEx
0 Hits    1st 0.000000   Avg 0.000000       MESSAGEBOX( loEx.Message )
                                           
1 Hit     1st 0.000027   Avg 0.000027   FINALLY
1 Hit     1st 0.001880   Avg 0.001880       FCLOSE(lnHandle_O)
1 Hit     1st 0.012949   Avg 0.012949       FCLOSE(lnHandle_D)
1 Hit     1st 0.000042   Avg 0.000042       SET COVERAGE TO
0 Hits    1st 0.000000   Avg 0.000000       WAIT WINDOW NOWAIT "Tiempo de copia: " + TRANSFORM(SECONDS()-lnSecs) + " segundos"
                                       
0 Hits    1st 0.000000   Avg 0.000000   ENDTRY
                                       
0 Hits    1st 0.000000   Avg 0.000000   RETURN

                                       

Me llamó mucho la atención que solo el primer FREAD fuera rápido (0.000305 segundos) y que la media fuera de 0.012 segundos (demasiado)

O sea, para el archivo que usé de prueba (unos 200 MB):
  • Tiempo de lectura: 3106 hits * 0.012421 segs = 38,579626 segundos
  • Tiempo de escritura: 13 hits * 0.05212 segs = 0,67756 segundos


En fin, luego de ver esto (que me tardó como 10 veces más que el COPY), creo que es mejor un COPY FILE de Fox por archivo y llevar el progreso por archivo.


Saludos.-


Fernando D. Bozzo

unread,
Jul 24, 2014, 6:10:31 PM7/24/14
to publice...@googlegroups.com
Como no me quedé tranquilo con la prueba, hice la separación del FREAD y de la acumulación en la variable, y me deja nuevamente perplejo:


3106 Hits 1st 0.000177   Avg 0.000235                   lcStrR    = FREAD( lnHandle_O, 8192 )    && 65535
3106 Hits 1st 0.000094   Avg 0.011991                   lcStr    = lcStr + lcStrR


Se suponía que las asignaciones de variables VAR = VAR + algo en Fox están optimizadas, pero en este caso eso es más lento (durante la carga, no al inicio) que el FREAD.

En fin, es un curiosidad que quería comentar :-)

Carlos Miguel FARIAS

unread,
Jul 24, 2014, 6:10:55 PM7/24/14
to Grupo Fox
Creo que tu algoritmo no pierde tiempo en el FREAD() si no en la suma de la string a la string que tenías.
Proba de leer cada bloque y escribirlo.
La respuesta está en tu lo que dices, el primer FREAD fue rápido (sumo a string vacia, no hay movimiento de memoria) pero luego, a medida que concatena la lectura a la cadena anterior, debe reacomodar todo en memoria.
lcStr    = lcStr + FREAD( lnHandle_O, 65535 )
y al final de cada archivo, mandate un FFLUSH, para optimizar-.
Saludos: Miguel, La Pampa (RA)

Carlos Miguel FARIAS

unread,
Jul 24, 2014, 6:13:15 PM7/24/14
to Grupo Fox
Justo cruzamos mensaje, confirmas lo que te decía.
Lo que pasa que estas metiendo 64kb en cada tanda, y eso, para la estructura de VFP es una bocha.
Recordad que hasta hace un tiempo, los procedimientos no podían tener más de 64kb justamente por una limitación en la versión del compilador de C que se usaba para crear el VFP y el runtime.
Saludos: Miguel, La Pampa (RA)

Fernando D. Bozzo

unread,
Jul 24, 2014, 6:19:23 PM7/24/14
to publice...@googlegroups.com
Vale, última prueba: Viendo que el cuello de botella era la variable, hice escritura directa, probando con 2 tamaños de bloque (8192 y 65535) para ver con cuál es más rápido, y para las máquinas actuales con 65535 va más rápido.

El tiempo final es muy parecido al COPY FILE ahora:

        DO WHILE NOT FEOF( lnHandle_O )
            lcStrR    = FREAD( lnHandle_O, 65535 )    && 65535
            FWRITE( lnHandle_D, lcStrR )
        ENDDO


Al fin! :-)

Fernando D. Bozzo

unread,
Jul 24, 2014, 6:20:05 PM7/24/14
to publice...@googlegroups.com
Exacto!, era eso.

Fernando D. Bozzo

unread,
Jul 24, 2014, 6:23:30 PM7/24/14
to publice...@googlegroups.com
Es cierto, para la próxima me queda comprobar a partir de qué tamaño de variable la acumulación se comienza a poner lenta.

Saludos!

Staff de Desarrollos EfiMax

unread,
Jul 24, 2014, 6:39:24 PM7/24/14
to publice...@googlegroups.com

Sólo una pequeña acotación Fernando el FREAD va a ser más lento que el FWRITE, debido a que este último no escribe directamente en el disco; aunque el programa indique que si, si no en el buffer del disco duro el cual viene por hardware, si quieres tiempos sin esta variable debes de deshabilitarlo desde el administrador de dispositivos, igual la escritura tomara más tiempo.

 

Que estés bien.

 

 

 

____________________________________

Carlos Omar Figueroa López

Ingeniero Industrial y de Sistemas

http://www.efimax.com.mx

Fernando D. Bozzo

unread,
Jul 25, 2014, 1:29:29 AM7/25/14
to publice...@googlegroups.com

No había tenido en cuenta el buffering.

Gracias por recordármelo! :-P

Carlos Miguel FARIAS

unread,
Jul 25, 2014, 6:10:53 AM7/25/14
to Grupo Fox

En uno de los post te comente del fflush para forzar a disco. Que lo hacia al menos al final de cada tabla.
En realidad si el s.o. hace buffering no me importa, ya que es una función de optimización de él.
Cuando usabas lcsrt hacías una suerte de buffering.
Lo que importa es si es eficiente o no.


Saludos: Miguel, La Pampa (RA)

Reply all
Reply to author
Forward
0 new messages